vgapp 0.0.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 (48) hide show
  1. package/.gitattributes +1 -0
  2. package/CHANGELOG.md +0 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/app/modules/base-module.js +97 -0
  6. package/app/modules/module-fn.js +119 -0
  7. package/app/modules/vgcollapse/js/vgcollapse.js +219 -0
  8. package/app/modules/vgdropdown/js/vgdropdown.js +279 -0
  9. package/app/modules/vgdropdown/scss/_variables.scss +9 -0
  10. package/app/modules/vgdropdown/scss/vgdropdown.scss +41 -0
  11. package/app/modules/vgformsender/js/vgformsender.js +400 -0
  12. package/app/modules/vgformsender/scss/vgformsender.scss +19 -0
  13. package/app/modules/vgmodal/js/vgmodal.js +346 -0
  14. package/app/modules/vgmodal/scss/_variables.scss +25 -0
  15. package/app/modules/vgmodal/scss/vgmodal.scss +111 -0
  16. package/app/modules/vgnav/js/vgnav.js +498 -0
  17. package/app/modules/vgnav/scss/_breakpoints.scss +127 -0
  18. package/app/modules/vgnav/scss/_hamburger.scss +62 -0
  19. package/app/modules/vgnav/scss/_placement.scss +70 -0
  20. package/app/modules/vgnav/scss/_toggle.scss +20 -0
  21. package/app/modules/vgnav/scss/_variables.scss +68 -0
  22. package/app/modules/vgnav/scss/vgnav.scss +150 -0
  23. package/app/modules/vgsidebar/js/vgsidebar.js +165 -0
  24. package/app/modules/vgsidebar/scss/_variables.scss +19 -0
  25. package/app/modules/vgsidebar/scss/vgsidebar.scss +90 -0
  26. package/app/utils/js/components/backdrop.js +54 -0
  27. package/app/utils/js/components/overflow.js +28 -0
  28. package/app/utils/js/components/params.js +44 -0
  29. package/app/utils/js/components/placement.js +59 -0
  30. package/app/utils/js/components/responsive.js +83 -0
  31. package/app/utils/js/components/scrollbar.js +114 -0
  32. package/app/utils/js/dom/data.js +51 -0
  33. package/app/utils/js/dom/event.js +331 -0
  34. package/app/utils/js/dom/manipulator.js +62 -0
  35. package/app/utils/js/dom/selectors.js +65 -0
  36. package/app/utils/js/functions.js +272 -0
  37. package/app/utils/scss/animate.scss +4074 -0
  38. package/app/utils/scss/default.scss +277 -0
  39. package/app/utils/scss/functions.scss +3 -0
  40. package/app/utils/scss/mixin.scss +11 -0
  41. package/app/utils/scss/variables.scss +80 -0
  42. package/build/vgapp.css +4538 -0
  43. package/build/vgapp.css.map +1 -0
  44. package/build/vgapp.js +3230 -0
  45. package/build/vgapp.js.map +1 -0
  46. package/index.js +29 -0
  47. package/package.json +43 -0
  48. package/webpack.config.js +63 -0
@@ -0,0 +1,400 @@
1
+ import BaseModule from "../../base-module";
2
+ import {Manipulator} from "../../../utils/js/dom/manipulator";
3
+ import EventHandler from "../../../utils/js/dom/event";
4
+ import VGModal from "../../vgmodal/js/vgmodal";
5
+ import {makeRandomString, mergeDeepObject, normalizeData} from "../../../utils/js/functions";
6
+ import Selectors from "../../../utils/js/dom/selectors";
7
+ import VGCollapse from "../../vgcollapse/js/vgcollapse";
8
+ import {getSVG} from "../../module-fn";
9
+
10
+ /**
11
+ * Constants
12
+ */
13
+ const NAME = 'form-sender';
14
+ const NAME_KEY = 'vg.fs';
15
+
16
+ /**
17
+ * Constants Classes
18
+ */
19
+
20
+
21
+ /**
22
+ * Constants Events
23
+ */
24
+ const EVENT_KEY_SUCCESS = 'vg.fs.success';
25
+ const EVENT_KEY_ERROR = 'vg.fs.error';
26
+ const EVENT_KEY_BEFORE = 'vg.fs.before';
27
+
28
+ const EVENT_SUBMIT_DATA_API = `submit.${NAME_KEY}.data.api`;
29
+
30
+ class VGFormSender extends BaseModule {
31
+ constructor(element, params = {}) {
32
+ super(element, params);
33
+
34
+ this._params = this._getParams(element, mergeDeepObject({
35
+ redirect: '',
36
+ validate: false,
37
+ submit: false,
38
+ fields: [],
39
+ alert: {
40
+ enabled: true,
41
+ type: 'modal'
42
+ },
43
+ ajax: {
44
+ route: '',
45
+ target: '',
46
+ method: 'get',
47
+ },
48
+ classes: {
49
+ general: 'vg-form-sender',
50
+ alertCollapse: 'vg-form-sender-collapse',
51
+ alertModal: 'vg-form-sender-modal',
52
+ validation: 'needs-validation',
53
+ wasValidate: 'was-validated'
54
+ }
55
+ }, params));
56
+
57
+ this._params.ajax.route = Manipulator.get(this._element, 'action').toLowerCase();
58
+ this._params.ajax.method = Manipulator.get(this._element, 'method').toLowerCase();
59
+ this._button = Selectors.find('[type="submit"]', this._element) || Selectors.find('[form="' + this._element.id + '"]') || null;
60
+
61
+ this._params.isBtnText = Manipulator.get(this._element, 'data-btn-text') !== 'false';
62
+ this._params.isJsonParse = Manipulator.get(this._element, 'data-json-parse') !== 'false';
63
+ this._params.isShowPass = Manipulator.get(this._element, 'data-show-pass') === 'true';
64
+ }
65
+
66
+ static get NAME() {
67
+ return NAME;
68
+ }
69
+
70
+ static get NAME_KEY() {
71
+ return NAME_KEY;
72
+ }
73
+
74
+ build() {
75
+ this._element.classList.add(this._params.classes.general);
76
+
77
+ if (this._params.validate) {
78
+ Manipulator.set(this._element, 'novalidate', '');
79
+ this._element.classList.add(this._params.classes.validation);
80
+ }
81
+
82
+ // TODO сделать добавление глаза если есть ввод пароля
83
+
84
+ return this
85
+ }
86
+
87
+ request(data, event) {
88
+ const _this = this;
89
+
90
+ _this._alertBefore();
91
+
92
+ _this._params.ajax.fields = data;
93
+
94
+ _this._route(function (status, data) {
95
+ _this._element.classList.remove('was-validated');
96
+
97
+ if (_this._params.alert.enabled) {
98
+ if (typeof status === 'string' && status === 'error') {
99
+ _this._alertError(event, data);
100
+ } else if (typeof status === 'string' && status === 'success') {
101
+ _this._alertSuccess(event, data);
102
+ }
103
+ }
104
+
105
+ if (_this._params.redirect) {
106
+ window.location.href = _this._params.redirect;
107
+ }
108
+ });
109
+ }
110
+
111
+ _alertBefore() {
112
+ const _this = this;
113
+
114
+ if (_this._params.alert.type === 'collapse') {
115
+ [...document.getElementsByClassName(_this._params.classes.alertCollapse)].forEach(function (element) {
116
+ if (element && element.classList.contains('show')) {
117
+ VGCollapse.getOrCreateInstance(element, {toggle: false}).hide();
118
+ }
119
+ });
120
+ }
121
+
122
+ _this._statusButton('before');
123
+ EventHandler.trigger(_this._element, EVENT_KEY_BEFORE, _this);
124
+ }
125
+
126
+ _alertError(event, data) {
127
+ const _this = this;
128
+
129
+ _this._statusButton('after');
130
+ _this._jsonParse(data, 'error');
131
+ EventHandler.trigger(_this._element, EVENT_KEY_ERROR, [event, _this, data]);
132
+ }
133
+
134
+ _alertSuccess(event, data) {
135
+ const _this = this;
136
+
137
+ _this._statusButton('after');
138
+ _this._jsonParse(data, 'success');
139
+ EventHandler.trigger(_this._element, EVENT_KEY_SUCCESS, [event, _this, data]);
140
+ }
141
+
142
+ _statusButton(status) {
143
+ const _this = this;
144
+
145
+ if (!_this._button) return;
146
+
147
+ let btnSubmitText = _this._button,
148
+ btnText = {
149
+ send: 'Отправляем...',
150
+ text: 'Отправить'
151
+ };
152
+
153
+ if (Manipulator.has(_this._button, 'data-spinner') && status === 'before') {
154
+ _this._button.insertAdjacentHTML('afterbegin', '<span class="spinner-border spinner-border-sm me-2"></span>');
155
+ }
156
+
157
+ if (Manipulator.has(_this._button, 'data-text')) {
158
+ btnText.text = Manipulator.get(_this._button, 'data-text');
159
+ } else {
160
+ let $btnText = _this._button.querySelector('[data-text]');
161
+ if ($btnText) {
162
+ btnText.text = Manipulator.get($btnText, 'data-text');
163
+ btnSubmitText = $btnText;
164
+ }
165
+ }
166
+
167
+ if (Manipulator.has(_this._button, 'data-text-send')) {
168
+ btnText.send = Manipulator.get(_this._button, 'data-text-send');
169
+ } else {
170
+ let $btnTextSend = _this._button.querySelector('[data-text-send]');
171
+ if ($btnTextSend) {
172
+ btnText.send = Manipulator.get($btnTextSend, 'data-text-send');
173
+ btnSubmitText = $btnTextSend;
174
+ }
175
+ }
176
+
177
+ if (status === 'before') {
178
+ if (_this._params.isBtnText) {
179
+ btnSubmitText.innerHTML = btnText.send;
180
+ }
181
+ Manipulator.set(_this._button,'disabled', 'disabled');
182
+ }
183
+
184
+ if (status === 'after') {
185
+ if (_this._params.isBtnText) {
186
+ btnSubmitText.innerHTML = btnText.text;
187
+ }
188
+ Manipulator.remove(_this._button,'disabled');
189
+
190
+ let spinner = _this._button.querySelector('.spinner-border');
191
+ if (spinner) spinner.remove();
192
+ }
193
+ }
194
+
195
+ _jsonParse(data, status) {
196
+ const _this = this;
197
+
198
+ if (_this._params.isJsonParse && typeof data === 'string') {
199
+ let parserData = {};
200
+
201
+ try {
202
+ parserData = JSON.parse(data);
203
+ _this.alert(parserData, status);
204
+ } catch (e) {
205
+ _this.alert(data, status);
206
+ }
207
+ } else {
208
+ _this.alert(data, status);
209
+ }
210
+ }
211
+
212
+ alert(data, status) {
213
+ const _this = this;
214
+
215
+ if (typeof data === "object") {
216
+ if ('errors' in data) {
217
+ status = normalizeData(data.errors) ? 'error' : 'success';
218
+ }
219
+ }
220
+
221
+ if (!_this._params.alert.enabled) {
222
+ return;
223
+ }
224
+
225
+ if (_this._params.alert.type === 'modal') {
226
+ _this._alertModal(data, status)
227
+ }
228
+
229
+ if (_this._params.alert.type === 'collapse') {
230
+ _this._alertCollapse(data, status)
231
+ }
232
+ }
233
+
234
+ _alertModal(data, status) {
235
+ const _this = this;
236
+
237
+ // Есть ли открытые модалки, закрываем
238
+ [...document.getElementsByClassName('modal')].forEach(function (element) {
239
+ if (element && element.classList.contains('show')) {
240
+ let mBS = bootstrap.Modal.getOrCreateInstance(element);
241
+ mBS.hide();
242
+ }
243
+ });
244
+
245
+ [...document.getElementsByClassName('vg-modal')].forEach(function (element) {
246
+ if (element && element.classList.contains('show')) {
247
+ const mVG = VGModal.getOrCreateInstance(element);
248
+ mVG.hide();
249
+ }
250
+ });
251
+
252
+ let $modal = Selectors.find('.' + _this._params.classes.alertModal);
253
+ if ($modal) $modal.remove();
254
+
255
+ let id = _this._params.classes.general + '-' + makeRandomString();
256
+ VGModal.init(id, {
257
+ classes: {
258
+ alert: _this._params.classes.alertModal
259
+ }
260
+ }, function (self) {
261
+ let element = self._element;
262
+ element.classList.add(_this._params.classes.alertModal);
263
+
264
+ let $body = Selectors.find('.vg-modal-body', element);
265
+ if ($body) $body.append(_this.setDataRelationStatus(element, status, data, 'modal'));
266
+
267
+ self.toggle();
268
+ });
269
+ }
270
+
271
+ _alertCollapse(data, status) {
272
+ const _this = this;
273
+
274
+ let $collapse = Selectors.find('.' + _this._params.classes.alertCollapse);
275
+ if (!$collapse) {
276
+ $collapse = document.createElement('div');
277
+ $collapse.classList.add(_this._params.classes.alertCollapse);
278
+ $collapse.classList.add('vg-collapse');
279
+ $collapse.id = _this._params.classes.general + '-' + makeRandomString();
280
+ $collapse.append(_this.setDataRelationStatus($collapse, status, data, 'collapse'));
281
+
282
+ _this._element.prepend($collapse);
283
+ }
284
+
285
+ VGCollapse.getOrCreateInstance($collapse, {toggle: false}).toggle();
286
+ }
287
+
288
+ setDataRelationStatus($element, status, data, type) {
289
+ let $alert = Selectors.find('.vg-alert-' + status, $element);
290
+
291
+ if (typeof data === 'object') {
292
+ if ('view' in data && typeof data.view === 'object') {
293
+ let txt = '';
294
+
295
+ if ('title' in data.view) {
296
+ txt += '<h4 class="vg-alert-content--title">' + data.view.title + '</h4>'
297
+ }
298
+
299
+ if ('message' in data.view) {
300
+ txt += '<div class="vg-alert-content--message">' + data.view.message + '</div>'
301
+ }
302
+
303
+ data = txt;
304
+ } else if ('view' in data && typeof data.view === "string") {
305
+ data = data.view;
306
+ }
307
+ }
308
+
309
+ if (!$alert) {
310
+ $alert = document.createElement('div');
311
+ $alert.classList.add('vg-alert', 'vg-alert-' + status, 'vg-alert-' + type);
312
+
313
+ let content = document.createElement('div');
314
+ content.classList.add('vg-alert-content');
315
+
316
+ let icon = document.createElement('div');
317
+ icon.classList.add('vg-alert-content--icon');
318
+
319
+ let i = document.createElement('i');
320
+ i.innerHTML = getSVG(status);
321
+
322
+ icon.append(i);
323
+ content.append(icon);
324
+
325
+ let text = document.createElement('div');
326
+ text.classList.add('vg-alert-content--text');
327
+ text.innerHTML = data;
328
+
329
+ content.append(text);
330
+ $alert.append(content);
331
+ } else {
332
+ let text = Selectors.find('.vg-alert-content--text', $alert);
333
+ text.innerHTML = data;
334
+ }
335
+
336
+ return $alert;
337
+ }
338
+
339
+ /**
340
+ * Инициализация
341
+ * @param element
342
+ * @param params
343
+ */
344
+ static init(element, params = {}) {
345
+ const instance = VGFormSender.getOrCreateInstance(element, params);
346
+ instance.build();
347
+ }
348
+ }
349
+
350
+ EventHandler.on(document, EVENT_SUBMIT_DATA_API, function (event) {
351
+ if (!Manipulator.has(event.target, 'data-vgformsender')) {
352
+ return;
353
+ }
354
+
355
+ const instance = VGFormSender.getOrCreateInstance(event.target, {});
356
+ if (!instance) {
357
+ return;
358
+ }
359
+
360
+ if (instance._params.validate) {
361
+ if (!instance._element.checkValidity()) {
362
+ event.preventDefault();
363
+ event.stopPropagation();
364
+
365
+ instance._element.classList.add(instance._params.classes.wasValidate);
366
+
367
+ return false;
368
+ }
369
+ }
370
+
371
+ const collectData = function(data, fields) {
372
+ for (let name in fields) {
373
+ if (typeof fields[name] === 'object') {
374
+ for (let key in fields[name]) {
375
+ let arr = Object.keys(fields[name][key]).map(function (i) {
376
+ return fields[name][key][i];
377
+ });
378
+ data.append(name, arr);
379
+ }
380
+ } else {
381
+ data.append(name, fields[name]);
382
+ }
383
+ }
384
+
385
+ return data;
386
+ }
387
+
388
+ if (!instance._params.submit) {
389
+ event.preventDefault();
390
+
391
+ let data = new FormData(instance._element);
392
+ if (typeof instance._params.ajax.fields === 'object') {
393
+ data = collectData(data, instance._params.ajax.fields);
394
+ }
395
+
396
+ return instance.request(data, event);
397
+ }
398
+ })
399
+
400
+ export default VGFormSender;
@@ -0,0 +1,19 @@
1
+ /**
2
+ *--------------------------------------------------------------------------
3
+ * Модуль: VGFormSender
4
+ * Автор: Vegas DEV
5
+ * Лицензия: смотри LICENSE
6
+ *--------------------------------------------------------------------------
7
+ **/
8
+
9
+ @import "../../../utils/scss/functions";
10
+ @import "../../../utils/scss/mixin";
11
+ @import "../../../utils/scss/variables";
12
+
13
+ .vg-form-sender {
14
+ &-modal {
15
+ .vg-modal-content {
16
+ padding: 0;
17
+ }
18
+ }
19
+ }