vgapp 0.7.9 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/app/langs/en/buttons.json +16 -0
  3. package/app/langs/en/messages.json +32 -0
  4. package/app/langs/en/titles.json +6 -0
  5. package/app/langs/ru/buttons.json +16 -0
  6. package/app/langs/ru/messages.json +32 -0
  7. package/app/langs/ru/titles.json +6 -0
  8. package/app/modules/base-module.js +12 -1
  9. package/app/modules/module-fn.js +20 -9
  10. package/app/modules/vgalert/js/vgalert.js +12 -6
  11. package/app/modules/vgalert/readme.md +1 -1
  12. package/app/modules/vgcollapse/readme.md +1 -1
  13. package/app/modules/vgdropdown/js/vgdropdown.js +140 -38
  14. package/app/modules/vgdropdown/readme.md +225 -0
  15. package/app/modules/vgfiles/js/base.js +499 -0
  16. package/app/modules/vgfiles/js/droppable.js +159 -0
  17. package/app/modules/vgfiles/js/loader.js +389 -0
  18. package/app/modules/vgfiles/js/render.js +83 -0
  19. package/app/modules/vgfiles/js/sortable.js +155 -0
  20. package/app/modules/vgfiles/js/vgfiles.js +796 -280
  21. package/app/modules/vgfiles/readme.md +193 -0
  22. package/app/modules/vgfiles/scss/_animations.scss +18 -0
  23. package/app/modules/vgfiles/scss/_mixins.scss +73 -0
  24. package/app/modules/vgfiles/scss/_variables.scss +103 -26
  25. package/app/modules/vgfiles/scss/vgfiles.scss +573 -60
  26. package/app/modules/vgformsender/js/vgformsender.js +5 -1
  27. package/app/modules/vgformsender/readme.md +1 -1
  28. package/app/modules/vglawcookie/js/vglawcookie.js +96 -62
  29. package/app/modules/vglawcookie/readme.md +102 -0
  30. package/app/modules/vgloadmore/js/vgloadmore.js +212 -112
  31. package/app/modules/vgloadmore/readme.md +145 -0
  32. package/app/modules/vgsidebar/js/vgsidebar.js +6 -4
  33. package/app/utils/js/components/ajax.js +172 -122
  34. package/app/utils/js/components/animation.js +124 -39
  35. package/app/utils/js/components/backdrop.js +54 -31
  36. package/app/utils/js/components/lang.js +69 -88
  37. package/app/utils/js/components/params.js +34 -31
  38. package/app/utils/js/components/scrollbar.js +118 -67
  39. package/app/utils/js/components/templater.js +14 -4
  40. package/app/utils/js/dom/cookie.js +107 -64
  41. package/app/utils/js/dom/data.js +68 -20
  42. package/app/utils/js/dom/event.js +272 -239
  43. package/app/utils/js/dom/manipulator.js +135 -62
  44. package/app/utils/js/dom/selectors.js +134 -59
  45. package/app/utils/js/functions.js +183 -349
  46. package/build/vgapp.css +1 -1
  47. package/build/vgapp.css.map +1 -1
  48. package/package.json +1 -1
  49. package/app/utils/js/components/overflow.js +0 -28
@@ -1,332 +1,365 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * Bootstrap event.js
3
+ * Bootstrap event.js (рефакторинг)
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
- * Скрипт для прослушивания события
6
+ * Утилита для гибкого управления DOM-событиями с поддержкой делегирования, пространств имён и one-off обработчиков.
7
7
  */
8
8
 
9
9
  /**
10
- * Константы
10
+ * ==================================
11
+ * КОНСТАНТЫ
12
+ * ==================================
11
13
  */
12
14
 
13
- const namespaceRegex = /[^.]*(?=\..*)\.|.*/
14
- const stripNameRegex = /\..*/
15
- const stripUidRegex = /::\d+$/
16
- const eventRegistry = {} // Events storage
17
- let uidEvent = 1
15
+ const NAMESPACE_REGEX = /[^.]*(?=\..*)\.|.*/
16
+ const STRIP_NAME_REGEX = /\..*/
17
+ const STRIP_UID_REGEX = /::\d+$/
18
18
  const customEvents = {
19
19
  mouseenter: 'mouseover',
20
20
  mouseleave: 'mouseout'
21
- }
21
+ };
22
22
 
23
+ // Список нативных событий для валидации
23
24
  const nativeEvents = new Set([
24
- 'click',
25
- 'dblclick',
26
- 'mouseup',
27
- 'mousedown',
28
- 'contextmenu',
29
- 'mousewheel',
30
- 'DOMMouseScroll',
31
- 'mouseover',
32
- 'mouseout',
33
- 'mousemove',
34
- 'selectstart',
35
- 'selectend',
36
- 'submit',
37
- 'keydown',
38
- 'keypress',
39
- 'keyup',
40
- 'orientationchange',
41
- 'touchstart',
42
- 'touchmove',
43
- 'touchend',
44
- 'touchcancel',
45
- 'pointerdown',
46
- 'pointermove',
47
- 'pointerup',
48
- 'pointerleave',
49
- 'pointercancel',
50
- 'popstate',
51
- 'gesturestart',
52
- 'gesturechange',
53
- 'gestureend',
54
- 'focus',
55
- 'blur',
56
- 'change',
57
- 'reset',
58
- 'select',
59
- 'submit',
60
- 'focusin',
61
- 'focusout',
62
- 'load',
63
- 'unload',
64
- 'beforeunload',
65
- 'resize',
66
- 'move',
67
- 'DOMContentLoaded',
68
- 'readystatechange',
69
- 'error',
70
- 'abort',
71
- 'scroll'
72
- ])
25
+ 'click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu',
26
+ 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove',
27
+ 'selectstart', 'selectend', 'submit', 'keydown', 'keypress', 'keyup',
28
+ 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel',
29
+ 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel',
30
+ 'popstate', 'gesturestart', 'gesturechange', 'gestureend',
31
+ 'focus', 'blur', 'change', 'reset', 'select', 'focusin', 'focusout',
32
+ 'load', 'unload', 'beforeunload', 'resize', 'move',
33
+ 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll'
34
+ ]);
73
35
 
74
36
  /**
75
- * Приватные методы
37
+ * ==================================
38
+ * ПРИВАТНЫЕ ПОЛЯ
39
+ * ==================================
76
40
  */
77
41
 
78
- function makeEventUid(element, uid) {
79
- return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++
80
- }
42
+ const eventRegistry = {}; // Хранилище событий
43
+ let uidEvent = 1; // Глобальный идентификатор
81
44
 
82
- function getElementEvents(element) {
83
- const uid = makeEventUid(element)
45
+ /**
46
+ * ==================================
47
+ * ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
48
+ * ==================================
49
+ */
84
50
 
85
- element.uidEvent = uid
86
- eventRegistry[uid] = eventRegistry[uid] || {}
51
+ /**
52
+ * Генерирует уникальный ID для события.
53
+ * @param {Element} element
54
+ * @param {string|null} uid
55
+ * @returns {string|number}
56
+ */
57
+ const makeEventUid = (element, uid = null) => {
58
+ if (!element.uidEvent) {
59
+ element.uidEvent = uid ? `${uid}::${uidEvent++}` : uidEvent++;
60
+ }
61
+ return element.uidEvent;
62
+ };
87
63
 
88
- return eventRegistry[uid]
89
- }
64
+ /**
65
+ * Получает или создаёт хранилище событий для элемента.
66
+ * @param {Element} element
67
+ * @returns {Object}
68
+ */
69
+ const getElementEvents = (element) => {
70
+ const uid = makeEventUid(element);
71
+ eventRegistry[uid] = eventRegistry[uid] || {};
72
+ return eventRegistry[uid];
73
+ };
90
74
 
91
- function bootstrapHandler(element, fn) {
92
- return function handler(event) {
93
- hydrateObj(event, { delegateTarget: element })
75
+ /**
76
+ * Создаёт обёртку для вызова обработчика.
77
+ * @param {Element} element
78
+ * @param {Function} fn
79
+ * @param {boolean} isOneOff
80
+ * @returns {Function}
81
+ */
82
+ const createHandler = (element, fn, isOneOff) => {
83
+ const handler = function (event) {
84
+ hydrateObj(event, { delegateTarget: element });
94
85
 
95
- if (handler.oneOff) {
96
- EventHandler.off(element, event.type, fn)
86
+ if (isOneOff) {
87
+ EventHandler.off(element, event.type, fn);
97
88
  }
98
89
 
99
- return fn.apply(element, [event])
100
- }
101
- }
90
+ return fn.apply(element, [event]);
91
+ };
102
92
 
103
- function bootstrapDelegationHandler(element, selector, fn) {
104
- return function handler(event) {
105
- const domElements = element.querySelectorAll(selector)
93
+ handler.delegationSelector = null;
94
+ handler.callable = fn;
95
+ handler.oneOff = isOneOff;
96
+ handler.uidEvent = null;
106
97
 
107
- for (let { target } = event; target && target !== this; target = target.parentNode) {
108
- for (const domElement of domElements) {
109
- if (domElement !== target) {
110
- continue
111
- }
98
+ return handler;
99
+ };
112
100
 
113
- hydrateObj(event, { delegateTarget: target })
101
+ /**
102
+ * Создаёт делегированный обработчик.
103
+ * @param {Element} element
104
+ * @param {string} selector
105
+ * @param {Function} fn
106
+ * @param {boolean} isOneOff
107
+ * @returns {Function}
108
+ */
109
+ const createDelegatedHandler = (element, selector, fn, isOneOff) => {
110
+ const handler = function (event) {
111
+ const candidates = Array.from(element.querySelectorAll(selector));
112
+ for (let target = event.target; target && target !== element; target = target.parentNode) {
113
+ if (!candidates.includes(target)) continue;
114
114
 
115
- if (handler.oneOff) {
116
- EventHandler.off(element, event.type, selector, fn)
117
- }
115
+ hydrateObj(event, { delegateTarget: target });
118
116
 
119
- return fn.apply(target, [event])
117
+ if (isOneOff) {
118
+ EventHandler.off(element, event.type, selector, fn);
120
119
  }
121
- }
122
- }
123
- }
124
-
125
- function findHandler(events, callable, delegationSelector = null) {
126
- return Object.values(events)
127
- .find(event => event.callable === callable && event.delegationSelector === delegationSelector)
128
- }
129
120
 
130
- function normalizeParameters(originalTypeEvent, handler, delegationFunction) {
131
- const isDelegated = typeof handler === 'string'
132
- // TODO: выдает "false" вместо селектора, поэтому нужно проверить. boot
133
- const callable = isDelegated ? delegationFunction : (handler || delegationFunction)
134
- let typeEvent = getTypeEvent(originalTypeEvent)
135
-
136
- if (!nativeEvents.has(typeEvent)) {
137
- typeEvent = originalTypeEvent
138
- }
139
-
140
- return [isDelegated, callable, typeEvent]
141
- }
121
+ return fn.apply(target, [event]);
122
+ }
123
+ };
142
124
 
143
- function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {
144
- if (typeof originalTypeEvent !== 'string' || !element) {
145
- return
146
- }
125
+ handler.delegationSelector = selector;
126
+ handler.callable = fn;
127
+ handler.oneOff = isOneOff;
128
+ handler.uidEvent = null;
147
129
 
148
- let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction)
130
+ return handler;
131
+ };
149
132
 
150
- // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position
151
- // this prevents the handler from being dispatched the same way as mouseover or mouseout does
152
- if (originalTypeEvent in customEvents) {
153
- const wrapFunction = fn => {
154
- return function (event) {
155
- if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) {
156
- return fn.call(this, event)
157
- }
158
- }
133
+ /**
134
+ * Обёртка для mouseenter/mouseleave.
135
+ * @param {Function} fn
136
+ * @returns {Function}
137
+ */
138
+ const withRelatedTargetCheck = (fn) => {
139
+ return function (event) {
140
+ if (
141
+ !event.relatedTarget ||
142
+ (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))
143
+ ) {
144
+ return fn.call(this, event);
159
145
  }
146
+ };
147
+ };
160
148
 
161
- callable = wrapFunction(callable)
149
+ /**
150
+ * Нормализует параметры события.
151
+ * @param {string} originalTypeEvent
152
+ * @param {Function|string} handler
153
+ * @param {Function} delegationFunction
154
+ * @returns {[boolean, Function, string]}
155
+ */
156
+ const normalizeParameters = (originalTypeEvent, handler, delegationFunction) => {
157
+ const isDelegated = typeof handler === 'string';
158
+ const callable = isDelegated ? delegationFunction : (handler || delegationFunction);
159
+ let typeEvent = originalTypeEvent.replace(STRIP_NAME_REGEX, '');
160
+
161
+ // Замена кастомных событий
162
+ if (customEvents[typeEvent]) {
163
+ typeEvent = customEvents[typeEvent];
162
164
  }
163
165
 
164
- const events = getElementEvents(element)
165
- const handlers = events[typeEvent] || (events[typeEvent] = {})
166
- const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null)
166
+ // Если не нативное событие — оставляем как есть
167
+ if (!nativeEvents.has(typeEvent)) {
168
+ typeEvent = originalTypeEvent;
169
+ }
167
170
 
168
- if (previousFunction) {
169
- previousFunction.oneOff = previousFunction.oneOff && oneOff
171
+ return [isDelegated, callable, typeEvent];
172
+ };
170
173
 
171
- return
174
+ /**
175
+ * Добавляет обработчик.
176
+ * @param {Element} element
177
+ * @param {string} originalTypeEvent
178
+ * @param {Function|string} handler
179
+ * @param {Function} delegationFunction
180
+ * @param {boolean} oneOff
181
+ */
182
+ const addHandler = (element, originalTypeEvent, handler, delegationFunction, oneOff) => {
183
+ if (typeof originalTypeEvent !== 'string' || !element) return;
184
+
185
+ const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);
186
+ const events = getElementEvents(element);
187
+ const handlers = events[typeEvent] ||= {};
188
+ const key = isDelegated ? handler : null;
189
+ const existing = findHandler(handlers, callable, key);
190
+
191
+ if (existing) {
192
+ existing.oneOff = existing.oneOff && oneOff;
193
+ return;
172
194
  }
173
195
 
174
- const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''))
175
- const fn = isDelegated ?
176
- bootstrapDelegationHandler(element, handler, callable) :
177
- bootstrapHandler(element, callable)
196
+ let fn = isDelegated
197
+ ? createDelegatedHandler(element, handler, callable, oneOff)
198
+ : createHandler(element, callable, oneOff);
178
199
 
179
- fn.delegationSelector = isDelegated ? handler : null
180
- fn.callable = callable
181
- fn.oneOff = oneOff
182
- fn.uidEvent = uid
183
- handlers[uid] = fn
200
+ const uid = makeEventUid(fn, originalTypeEvent.replace(NAMESPACE_REGEX, ''));
201
+ fn.uidEvent = uid;
202
+ handlers[uid] = fn;
184
203
 
185
- element.addEventListener(typeEvent, fn, isDelegated)
186
- }
204
+ element.addEventListener(typeEvent, fn, isDelegated);
205
+ };
187
206
 
188
- function removeHandler(element, events, typeEvent, handler, delegationSelector) {
189
- const fn = findHandler(events[typeEvent], handler, delegationSelector)
190
-
191
- if (!fn) {
192
- return
193
- }
207
+ /**
208
+ * Находит обработчик в хранилище.
209
+ * @param {Object} handlers
210
+ * @param {Function} callable
211
+ * @param {string|null} delegationSelector
212
+ * @returns {Object|undefined}
213
+ */
214
+ const findHandler = (handlers, callable, delegationSelector) => {
215
+ return Object.values(handlers).find(
216
+ h => h.callable === callable && h.delegationSelector === delegationSelector
217
+ );
218
+ };
194
219
 
195
- element.removeEventListener(typeEvent, fn, Boolean(delegationSelector))
196
- delete events[typeEvent][fn.uidEvent]
197
- }
220
+ /**
221
+ * Удаляет обработчик.
222
+ * @param {Element} element
223
+ * @param {Object} events
224
+ * @param {string} typeEvent
225
+ * @param {Function} callable
226
+ * @param {string|null} delegationSelector
227
+ */
228
+ const removeHandler = (element, events, typeEvent, callable, delegationSelector) => {
229
+ const handler = findHandler(events[typeEvent], callable, delegationSelector);
230
+ if (!handler) return;
198
231
 
199
- function removeNamespacedHandlers(element, events, typeEvent, namespace) {
200
- const storeElementEvent = events[typeEvent] || {}
232
+ element.removeEventListener(typeEvent, handler, Boolean(delegationSelector));
233
+ delete events[typeEvent][handler.uidEvent];
234
+ };
201
235
 
202
- for (const [handlerKey, event] of Object.entries(storeElementEvent)) {
203
- if (handlerKey.includes(namespace)) {
204
- removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)
236
+ /**
237
+ * Удаляет обработчики по пространству имён.
238
+ * @param {Element} element
239
+ * @param {Object} events
240
+ * @param {string} typeEvent
241
+ * @param {string} namespace
242
+ */
243
+ const removeNamespacedHandlers = (element, events, typeEvent, namespace) => {
244
+ const handlers = events[typeEvent] || {};
245
+ for (const [key, handler] of Object.entries(handlers)) {
246
+ if (key.includes(namespace)) {
247
+ removeHandler(element, events, typeEvent, handler.callable, handler.delegationSelector);
205
248
  }
206
249
  }
207
- }
250
+ };
208
251
 
209
- function getTypeEvent(event) {
210
- // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
211
- event = event.replace(stripNameRegex, '')
212
- return customEvents[event] || event
213
- }
214
-
215
- function hydrateObj(obj, meta = {}) {
252
+ /**
253
+ * Добавляет свойства в объект события, безопасно.
254
+ * @param {Object} obj
255
+ * @param {Object} meta
256
+ * @returns {Object}
257
+ */
258
+ const hydrateObj = (obj, meta = {}) => {
216
259
  for (const [key, value] of Object.entries(meta)) {
217
260
  try {
218
- obj[key] = value
261
+ obj[key] = value;
219
262
  } catch {
220
263
  Object.defineProperty(obj, key, {
221
264
  configurable: true,
222
- get() {
223
- return value
224
- }
225
- })
265
+ get() { return value; }
266
+ });
226
267
  }
227
268
  }
228
-
229
- return obj
230
- }
269
+ return obj;
270
+ };
231
271
 
232
272
  /**
233
- * События
234
- * @type {{one(*, *, *, *): void, trigger(*, *, *): (null|*), off(*, *, *, *): void, on(*, *, *, *): void}}
273
+ * ==================================
274
+ * ОСНОВНОЙ МОДУЛЬ: EventHandler
275
+ * ==================================
235
276
  */
277
+
236
278
  const EventHandler = {
237
279
  /**
238
- * Прослушиватель событий (элемент, событие (полный список смотри в константе nativeEvents, источник события или хендлер, функция обратного вызова))
239
- * @param element
240
- * @param event
241
- * @param handler
242
- * @param delegationFunction
280
+ * Добавляет прослушиватель события.
281
+ * @param {Element} element
282
+ * @param {string} event — тип события (с опциональным пространством имён)
283
+ * @param {Function|string} handler — селектор (если делегирование) или функция
284
+ * @param {Function} [delegationFunction] — функция, вызываемая при делегировании
243
285
  */
244
286
  on(element, event, handler, delegationFunction) {
245
- addHandler(element, event, handler, delegationFunction, false)
287
+ addHandler(element, event, handler, delegationFunction, false);
246
288
  },
247
289
 
248
290
  /**
249
- * Прослушиватель событий, но замыкается и больше не повторяется на элементе
250
- * @param element
251
- * @param event
252
- * @param handler
253
- * @param delegationFunction
291
+ * Добавляет одноразовый обработчик.
292
+ * @param {Element} element
293
+ * @param {string} event
294
+ * @param {Function|string} handler
295
+ * @param {Function} [delegationFunction]
254
296
  */
255
297
  one(element, event, handler, delegationFunction) {
256
- addHandler(element, event, handler, delegationFunction, true)
298
+ addHandler(element, event, handler, delegationFunction, true);
257
299
  },
258
300
 
259
301
  /**
260
- * Удаление обработчика
261
- * @param element
262
- * @param originalTypeEvent
263
- * @param handler
264
- * @param delegationFunction
302
+ * Удаляет обработчик(и).
303
+ * @param {Element} element
304
+ * @param {string} originalTypeEvent
305
+ * @param {Function|string} [handler]
306
+ * @param {Function} [delegationFunction]
265
307
  */
266
308
  off(element, originalTypeEvent, handler, delegationFunction) {
267
- if (typeof originalTypeEvent !== 'string' || !element) {
268
- return
269
- }
270
-
271
- const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction)
272
- const inNamespace = typeEvent !== originalTypeEvent
273
- const events = getElementEvents(element)
274
- const storeElementEvent = events[typeEvent] || {}
275
- const isNamespace = originalTypeEvent.startsWith('.')
309
+ if (typeof originalTypeEvent !== 'string' || !element) return;
276
310
 
277
- if (typeof callable !== 'undefined') {
278
- // Simplest case: handler is passed, remove that listener ONLY.
279
- if (!Object.keys(storeElementEvent).length) {
280
- return
281
- }
282
-
283
- removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null)
284
- return
285
- }
311
+ const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);
312
+ const events = getElementEvents(element);
313
+ const isNamespace = originalTypeEvent.startsWith('.');
314
+ const inNamespace = typeEvent !== originalTypeEvent;
286
315
 
316
+ // Удаление по пространству имён
287
317
  if (isNamespace) {
288
- for (const elementEvent of Object.keys(events)) {
289
- removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1))
318
+ for (const eventType of Object.keys(events)) {
319
+ removeNamespacedHandlers(element, events, eventType, originalTypeEvent.slice(1));
290
320
  }
321
+ return;
291
322
  }
292
323
 
293
- for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {
294
- const handlerKey = keyHandlers.replace(stripUidRegex, '')
324
+ const storeElementEvent = events[typeEvent] || {};
295
325
 
326
+ // Удаление конкретного обработчика
327
+ if (typeof callable !== 'undefined') {
328
+ removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null);
329
+ return;
330
+ }
331
+
332
+ // Удаление всех обработчиков события
333
+ for (const [key, eventObj] of Object.entries(storeElementEvent)) {
334
+ const handlerKey = key.replace(STRIP_UID_REGEX, '');
296
335
  if (!inNamespace || originalTypeEvent.includes(handlerKey)) {
297
- removeHandler(element, events, typeEvent, event.callable, event.delegationSelector)
336
+ removeHandler(element, events, typeEvent, eventObj.callable, eventObj.delegationSelector);
298
337
  }
299
338
  }
300
339
  },
301
340
 
302
341
  /**
303
- * Пользовательские события. Подробнее тут https://learn.javascript.ru/dispatch-events
304
- * @param element
305
- * @param event
306
- * @param args
307
- * @returns {*|null}
342
+ * Генерирует пользовательское событие.
343
+ * @param {Element} element
344
+ * @param {string} event — имя события
345
+ * @param {Object} [args] — дополнительные данные
346
+ * @returns {Object}
308
347
  */
309
348
  trigger(element, event, args) {
310
- if (typeof event !== 'string' || !element) {
311
- return null
312
- }
313
-
314
- let bubbles = true;
315
- let nativeDispatch = true;
316
- let defaultPrevented = false;
317
-
318
- const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)
319
-
320
- if (defaultPrevented) {
321
- evt.preventDefault()
322
- }
323
-
324
- if (nativeDispatch) {
325
- element.dispatchEvent(evt)
326
- }
327
-
328
- return evt
349
+ if (typeof event !== 'string' || !element) return null;
350
+
351
+ const evt = hydrateObj(
352
+ new CustomEvent(event, {
353
+ bubbles: true,
354
+ cancelable: true,
355
+ detail: args
356
+ }),
357
+ args
358
+ );
359
+
360
+ element.dispatchEvent(evt);
361
+ return evt;
329
362
  }
330
- }
363
+ };
331
364
 
332
- export default EventHandler
365
+ export default EventHandler;