objs-core 1.0.0

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.
package/objs.1.0.js ADDED
@@ -0,0 +1,1150 @@
1
+ /**
2
+ * @function Objs
3
+ * DOM Modify and state control
4
+ *
5
+ * @version 1.0 02 2023
6
+ * @author Roman Torshin
7
+ * @copyright
8
+ * Apache-2.0 license *
9
+ *
10
+ * @param {any} query Selector, DOM element to use, an array of elements, inited ID or nothing for creating an element
11
+ * @return {object} Objs
12
+ */
13
+
14
+ const o = (query) => {
15
+ let result = {els: [], ie: {}},
16
+ ZERO = 0,
17
+ ONE = 1,
18
+ TWO = 2,
19
+ THREE = 3,
20
+ objectType = 'object',
21
+ functionType = 'function',
22
+ u = undefined,
23
+ D = document;
24
+ let start = -1,
25
+ finish = 0,
26
+ select = 0,
27
+ initedStates = [],
28
+ i = 0, j = 0;
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+ // shorten typeof
38
+ const type = obj => typeof obj;
39
+ // cycle from object
40
+ const cycleObj = (obj, func) => {for (const item in obj) if (Object.hasOwnProperty.call(obj, item)) func(item, obj)};
41
+ // error function
42
+ const error = o.onError || (() => {return});
43
+ // values returner
44
+ const returner = (f) => {
45
+ return (...a) => {
46
+ try {
47
+ return f(a[ZERO], a[ONE], a[TWO], a[THREE]) || result
48
+ } catch (err) {
49
+ error(err)
50
+ }
51
+ };
52
+ };
53
+ // running for each element
54
+ const iterator = (f) => {for (i = finish; i <= start; i++) f()};
55
+ // getting element from string
56
+ const toEl = (el) => {
57
+ if (type(el) !== objectType)
58
+ el = o.first(el).el;
59
+ return el;
60
+ };
61
+ // setting properties
62
+ const setResultVals = (clearStates = true, els = result.els) => {
63
+ const ln = els.length;
64
+ result.length = ln;
65
+ start = ln - ONE;
66
+ finish = ZERO;
67
+ result.el = ln ? els[ZERO] : u;
68
+ result.last = ln ? els[start] : u;
69
+ if (clearStates) {
70
+ cycleObj(initedStates, (i, state) => {
71
+ delete result[state[i]];
72
+ });
73
+ initedStates = [];
74
+ result.ie = {};
75
+ }
76
+ };
77
+ // getting element by query
78
+ const getObjs = (innerQuery = '') => {return Array.from(D.querySelectorAll(innerQuery))};
79
+ // sets new objects to operate
80
+ result.reset = o;
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+ /**
89
+ * Transformation of DOM elements
90
+ *
91
+ * @param {object} el DOM element for transformation
92
+ * @param {object} state States data
93
+ * @param {object} props additional props and dynamic content
94
+ */
95
+
96
+ const transform = (el, state, props) => {
97
+ cycleObj(state, (s) => {
98
+ let value = state[s];
99
+
100
+ if (type(value) === functionType) {
101
+ value = value(props);
102
+ }
103
+
104
+ if (value !== u) {
105
+ ['tag','sample','state'].includes(s) ? '' :
106
+ ['html','innerHTML'].includes(s) ? el.innerHTML = value :
107
+ s === 'dataset' && type(value) === objectType ?
108
+ cycleObj(value, (data) => {
109
+ el.dataset[data] = value[data];
110
+ }) :
111
+ s === 'toggleClass' ? el.classList.toggle(value) :
112
+ s === 'addClass' ? (type(value) === objectType ? el.classList.add(...value) : el.classList.add(value)) :
113
+ s === 'removeClass' ? el.classList.remove(value) :
114
+ s === 'style' && type(value) === objectType ?
115
+ cycleObj(value, (data) => {
116
+ el.style[data] = value[data];
117
+ }) :
118
+ s === 'append' && type(value) === objectType ?
119
+ cycleObj(value.length ? value : [value], (j) => {
120
+ el.appendChild(value[j]);
121
+ }) :
122
+ el.setAttribute(s, value);
123
+ }
124
+ });
125
+
126
+ el.dataset['oState'] = state.state;
127
+ };
128
+
129
+ /**
130
+ * Creates states functions
131
+ *
132
+ * @param {object} states States object
133
+ */
134
+ result.init = returner((states) => {
135
+ const initN = result.initID || o.inits.length || ZERO;
136
+ result.initID = initN;
137
+ setResultVals();
138
+ o.inits[result.initID] = result;
139
+
140
+ // fast initialisation
141
+ if (type(states) !== objectType || states.render === u) {
142
+ states = {
143
+ render: states,
144
+ };
145
+ }
146
+
147
+ // cycle threw states
148
+ cycleObj(states, (state) => {
149
+ // save state name to clear object by reset();
150
+ initedStates.push(state);
151
+ // add method named as state
152
+ result[state] = returner((props = [{}]) => {
153
+ let data = states[state] || {tag: 'div'};
154
+ const els = result.els.slice(finish, start + ONE);
155
+
156
+ if (type(data) === objectType) {
157
+ data.state = state;
158
+ data['data-o-init'] = initN;
159
+ }
160
+
161
+ // creation elements for prop in props
162
+ const newEl = (n, prop = {}) => {
163
+ if (type(data) === objectType) {
164
+ return D.createElement(data.tag || 'div');
165
+ } else {
166
+ i = D.createElement('div');
167
+ i.innerHTML = type(data) === functionType ? data(prop) : data;
168
+ if (i.children.length > ONE || !i.firstElementChild) {
169
+ i.dataset.oInit = n;
170
+ return i;
171
+ } else {
172
+ i.firstElementChild.dataset.oInit = n;
173
+ return i.firstElementChild;
174
+ }
175
+ }
176
+ };
177
+
178
+ // properties creation
179
+ !props.length ? props = [props] : '';
180
+
181
+ // creating elements if no one was selected
182
+ const creation = !els[ZERO] && state === 'render';
183
+ props = props.map((prop, i) => {
184
+ prop.self = result;
185
+ prop.o = o;
186
+ prop.i = prop.i === u ? i : prop.i;
187
+ if (creation) {
188
+ els.push(newEl(initN, prop));
189
+ }
190
+ return prop;
191
+ });
192
+ if (creation) {
193
+ result.els = els;
194
+ setResultVals(false);
195
+ }
196
+
197
+ // changing element if there is data object
198
+ if (els) {
199
+ j = els.length === props.length;
200
+ els.map((el, i) => {
201
+ props[j ? i : ZERO].i = i + finish;
202
+ const buff = type(data) === functionType ? data(props[j ? i : ZERO]) : data;
203
+ if (type(buff) === objectType) {
204
+ transform(
205
+ el,
206
+ buff,
207
+ props[j ? i : ZERO]
208
+ );
209
+ }
210
+ });
211
+ }
212
+ });
213
+ });
214
+ });
215
+
216
+ result.initState = returner((state, props) => {
217
+ result.init(state).render(props);
218
+ });
219
+
220
+ /**
221
+ * Gets state object from existing DOM element
222
+ *
223
+ * @param {string} state title, optional
224
+ *
225
+ * @return {object} state
226
+ */
227
+ result.sample = returner((state = 'render') => {
228
+ const attrs = result.els[finish].attributes,
229
+ ds = result.els[finish].dataset,
230
+ res = {
231
+ tag: result.els[finish].tagName,
232
+ html: result.els[finish].innerHTML,
233
+ dataset: {},
234
+ };
235
+
236
+ for (const attr of attrs) {
237
+ if (attr.nodeName.substring(ZERO, 5) !== 'data-') {
238
+ res[attr.nodeName] = attr.value;
239
+ }
240
+ }
241
+
242
+ cycleObj(ds, (data) => {
243
+ res.dataset[data] = ds[data];
244
+ });
245
+
246
+ return {[state]: res};
247
+ });
248
+
249
+ /**
250
+ * Select element to control
251
+ *
252
+ * @param {number} i index, last one if undefined
253
+ */
254
+ result.select = returner((i) => {
255
+ if (i === u) {
256
+ i = result.length - ONE;
257
+ }
258
+ start = i;
259
+ finish = i;
260
+ result.el = result.els[i];
261
+ select = ONE;
262
+ });
263
+
264
+ /**
265
+ * Select all elements to control
266
+ */
267
+ result.all = returner(() => {
268
+ start = result.length - ONE;
269
+ finish = ZERO;
270
+ result.el = result.els[ZERO];
271
+ select = ZERO;
272
+ });
273
+
274
+ /**
275
+ * Remove selected element or all from DOM
276
+ *
277
+ * @param {number} j index, removes all if undefined
278
+ */
279
+ result.remove = returner((j) => {
280
+ if (j === u && select) {
281
+ j = finish;
282
+ }
283
+
284
+ if (j !== u) {
285
+ result.els[j].parentNode.removeChild(result.els[j]);
286
+ } else {
287
+ iterator(() => {
288
+ result.els[i].parentNode.removeChild(result.els[i]);
289
+ });
290
+ }
291
+ setResultVals(false);
292
+ });
293
+
294
+ /**
295
+ * Delete j, selected or the first element from control list
296
+ */
297
+ result.skip = returner((j) => {
298
+ if (j === u) {
299
+ j = finish;
300
+ }
301
+
302
+ result.els.splice(i, ONE);
303
+ setResultVals();
304
+ });
305
+
306
+ /**
307
+ * Add element to control list
308
+ */
309
+ result.add = returner((el,l) => {
310
+ if (type(el) === 'string' && el !== '') {
311
+ result.els.push(...getObjs(el));
312
+ } else if (type(el) === objectType) {
313
+ if (el.tagName) {
314
+ result.els.push(el);
315
+ } else if (el.els) {
316
+ result.els.push(...el.els);
317
+ } else if (el.length && el[ZERO].tagName) {
318
+ result.els.push(...el);
319
+ }
320
+ } else if (type(el) === 'number' && o.inits[el]) {
321
+ result = o.inits[el];
322
+ }
323
+
324
+ setResultVals(false);
325
+
326
+ if (result.initID !== u) {
327
+ result.dataset({'oInit': result.initID});
328
+ }
329
+ });
330
+
331
+ /**
332
+ * Functions to insert elements into DOM
333
+ */
334
+ result.appendInside = returner((el) => {
335
+ iterator(() => {
336
+ toEl(el).appendChild(result.els[i]);
337
+ });
338
+ });
339
+ result.appendBefore = returner((el) => {
340
+ iterator(() => {
341
+ toEl(el).parentNode.insertBefore(result.els[i], toEl(el));
342
+ });
343
+ });
344
+ result.appendAfter= returner((el) => {
345
+ iterator(() => {
346
+ toEl(el).after(...result.els);
347
+ });
348
+ });
349
+
350
+ /**
351
+ * Find child elements
352
+ */
353
+ result.find = returner((innerQuery = '') => {
354
+ const newEls = [];
355
+
356
+ iterator(() => {
357
+ newEls.push(...Array.from(result.els[i].querySelectorAll(':scope ' + innerQuery)));
358
+ });
359
+
360
+ result.els = newEls;
361
+ setResultVals();
362
+ });
363
+
364
+ /**
365
+ * Find the first child element by query
366
+ */
367
+ result.first = returner((innerQuery = '') => {
368
+ let buff = u;
369
+ const newEls = [];
370
+
371
+ iterator(() => {
372
+ buff = result.els[i].querySelector(innerQuery);
373
+ if (buff) {
374
+ newEls.push(buff);
375
+ }
376
+ });
377
+
378
+ result.els = newEls;
379
+ setResultVals();
380
+ });
381
+
382
+ /**
383
+ * Set, delete or get attribute
384
+ */
385
+ result.attr = returner((attr, val) => {
386
+ if (attr) {
387
+ if (val === u) {
388
+ const attrs = [];
389
+ iterator(() => {
390
+ attrs[i] = result.els[i].getAttribute(attr);
391
+ });
392
+ return select ? attrs[ZERO] : attrs;
393
+ } else if (val !== '') {
394
+ iterator(() => {
395
+ result.els[i].setAttribute(attr, val);
396
+ });
397
+ } else {
398
+ iterator(() => {
399
+ result.els[i].removeAttribute(attr);
400
+ });
401
+ }
402
+ }
403
+ });
404
+ /**
405
+ * Get all attributes
406
+ */
407
+ result.attrs = returner(() => {
408
+ const res = [];
409
+ iterator(() => {
410
+ const obj = {};
411
+ [...result.els[i].attributes].forEach((attr) => {
412
+ obj[attr.nodeName] = attr.nodeValue;
413
+ });
414
+ res.push(obj);
415
+ });
416
+ return select ? res[ZERO] : res;
417
+ });
418
+ /**
419
+ * Dataset control
420
+ */
421
+ result.dataset = returner((values) => {
422
+ if (typeof values === objectType) {
423
+ iterator(() => {
424
+ cycleObj(values, (data) => {
425
+ result.els[i].dataset[data] = values[data];
426
+ });
427
+ });
428
+ } else {
429
+ const res = [];
430
+ iterator(() => {
431
+ res.push({...result.els[i].dataset});
432
+ });
433
+ return select ? res[ZERO] : res;
434
+ }
435
+ });
436
+ /**
437
+ * Style attribute
438
+ */
439
+ result.style = returner((val) => {
440
+ result.attr('style', val);
441
+ });
442
+ /**
443
+ * CSS as object to create style attribute
444
+ */
445
+ result.css = returner((styles = {}) => {
446
+ let val = '';
447
+
448
+ cycleObj(styles, (style) => {
449
+ val += style + ':' + styles[style].replace('"', "'") + ';'
450
+ });
451
+
452
+ result.style(val)
453
+ });
454
+ /**
455
+ * Class control
456
+ */
457
+ result.setClass = returner((cl) => {
458
+ iterator(() => {
459
+ result.els[i].setAttribute('class', cl)
460
+ })
461
+ });
462
+ result.addClass = returner((cl) => {
463
+ iterator(() => {
464
+ result.els[i].classList.add(cl)
465
+ })
466
+ });
467
+ result.removeClass = returner((cl) => {
468
+ iterator(() => {
469
+ result.els[i].classList.remove(cl)
470
+ })
471
+ });
472
+ result.toggleClass = returner((cl, check) => {
473
+ iterator(() => {
474
+ result.els[i].classList.toggle(cl, check)
475
+ })
476
+ });
477
+ result.haveClass = (cl) => {
478
+ let res = true;
479
+ iterator(() => {
480
+ if (!result.els[i].classList.contains(cl)) {
481
+ res = false;
482
+ }
483
+ });
484
+ return res;
485
+ };
486
+ /**
487
+ * Inner content control
488
+ */
489
+ result.innerHTML = returner((html) => {
490
+ if (html !== u) {
491
+ iterator(() => {
492
+ result.els[i].innerHTML = html;
493
+ });
494
+ } else {
495
+ let res = '';
496
+ iterator(() => {
497
+ res += result.els[i].innerHTML;
498
+ });
499
+ return res;
500
+ }
501
+ });
502
+ result.innerText = returner((text = '') => {
503
+ iterator(() => {
504
+ result.els[i].innerText = text;
505
+ });
506
+ });
507
+ result.textContent = returner((text = '') => {
508
+ iterator(() => {
509
+ result.els[i].textContent = text;
510
+ });
511
+ });
512
+
513
+ /**
514
+ * Gets HTML of DOM operated elements
515
+ *
516
+ * @returns {string}
517
+ */
518
+ result.html = returner((value) => {
519
+ if (value) {
520
+ result.innerHTML(value);
521
+ } else {
522
+ let html = '';
523
+
524
+ iterator(() => {
525
+ html += result.els[i].outerHTML;
526
+ });
527
+
528
+ return html;
529
+ }
530
+ });
531
+
532
+ result.forEach = returner((f) => {
533
+ result.initState(f);
534
+ });
535
+
536
+
537
+
538
+
539
+
540
+ /**
541
+ * Event functions
542
+ */
543
+ result.on = returner((a, b, c, d) => {
544
+ a.split(', ').forEach((ev) => {
545
+ iterator(() => {
546
+ result.els[i].addEventListener(ev, b, c, d);
547
+ });
548
+ if (!result.ie[ev]) {
549
+ result.ie[ev] = [];
550
+ }
551
+ result.ie[ev].push([b, c, d]);
552
+ });
553
+ });
554
+ result.off = returner((a, b, c) => {
555
+ a.split(', ').forEach((ev) => {
556
+ iterator(() => {
557
+ result.els[i].removeEventListener(ev, b, c);
558
+ });
559
+ if (result.ie[ev]) {
560
+ result.ie[ev] = result.ie[ev].filter(f => f[ZERO] !== b);
561
+ }
562
+ });
563
+ });
564
+ /**
565
+ * On and off listeners
566
+ */
567
+ result.onAll = returner((type, off) => {
568
+ cycleObj(result.ie, (ev, events) => {
569
+ if (!type || type === ev) {
570
+ events[ev].forEach((data) => {
571
+ iterator(() => {
572
+ if (off) {
573
+ result.els[i].removeEventListener(ev, data[ZERO]);
574
+ } else {
575
+ result.els[i].addEventListener(ev, data[ZERO], data[ONE], data[TWO]);
576
+ }
577
+ });
578
+ });
579
+ }
580
+ });
581
+ });
582
+ result.offAll = returner((type) => {
583
+ result.onAll(type, ONE);
584
+ });
585
+
586
+ /**
587
+ * Making result object
588
+ */
589
+ if (query)
590
+ result.add(query);
591
+
592
+ result.take = (innerQuery) => {
593
+ result.add(innerQuery);
594
+
595
+ if (result.el) {
596
+ const initID = result.el.dataset['oInit'];
597
+
598
+ if (initID !== u && o.inits[initID]) {
599
+ if (result.length === ONE) {
600
+ j = result.els[ZERO];
601
+ Object.assign(result, o.inits[initID]);
602
+ result.els = [j];
603
+ } else {
604
+ result = o.inits[initID];
605
+ }
606
+ setResultVals(false, result.els);
607
+ return result;
608
+ }
609
+ }
610
+ };
611
+
612
+ return result;
613
+ };
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+
633
+ o.first = (query) => {
634
+ return o(document.querySelector(query) || '');
635
+ };
636
+
637
+ o.inits = [];
638
+ o.onError = false;
639
+ // o.onError = (e) => console.log(e);
640
+
641
+ /**
642
+ * Creating elements from state
643
+ *
644
+ * @param {object} states State, states or function/string
645
+ */
646
+ o.init = (states) => {
647
+ return o().init(states);
648
+ };
649
+ o.initState = (state, props) => {
650
+ return o().init(state).render(props);
651
+ };
652
+ o.take = (query) => {
653
+ return o().take(query);
654
+ };
655
+
656
+ // Short values
657
+ o.Z = 0; o.N = 1; o.W = 2; o.H = 100; o.F = false;
658
+ o.C = (a, b) => {
659
+ return Object.hasOwnProperty.call(a, b);
660
+ };
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+
678
+
679
+ /**
680
+ * GET and POST
681
+ *
682
+ * @argument {string} url link
683
+ * @argument {object} props parameters
684
+ *
685
+ * @returns {promise}
686
+ */
687
+ o.ajax = (url, props = {}) => {
688
+ let row = new URLSearchParams();
689
+ if (props.data && typeof props.data === 'object') {
690
+ for (const param in props.data) {
691
+ if (o.C(props.data, param)) {
692
+ if (typeof props.data[param] === 'object') {
693
+ row.set(param, encodeURIComponent(JSON.stringify(props.data[param])));
694
+ } else {
695
+ row.set(param, props.data[param]);
696
+ }
697
+ }
698
+ }
699
+ if (props.method === 'GET' || props.method === 'get') {
700
+ url += '?' + row.toString();
701
+ } else if (!props.body) {
702
+ props.body = row;
703
+ }
704
+ delete props.data;
705
+ }
706
+
707
+ return fetch(url, props);
708
+ };
709
+ o.get = (url, props = {}) => {
710
+ return o.ajax(url, {...props, method: 'GET'});
711
+ };
712
+ o.post = (url, props = {}) => {
713
+ return o.ajax(url, {...props, method: 'POST'});
714
+ };
715
+ o.getParams = () => {
716
+ const params = {};
717
+ const paramsRaw = new URLSearchParams(window.location.search).entries();
718
+
719
+ for (const entry of paramsRaw) {
720
+ params[entry[o.Z]] = entry[o.N];
721
+ }
722
+
723
+ return params;
724
+ };
725
+
726
+
727
+
728
+
729
+
730
+
731
+
732
+
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+
742
+
743
+ /**
744
+ * Include functions
745
+ *
746
+ * @param {object} sources array of name:src values
747
+ * @param {function} callBack function for success
748
+ * @param {function} callBad function for error
749
+ *
750
+ * @returns {bool}
751
+ */
752
+
753
+ /* parameters */
754
+ o.incCache = true;// cache in localStorage
755
+ o.incCacheExp = 1000 * 60 * 60 * 24;// cache time
756
+ o.incTimeout = 6000;// ms for timing to load function
757
+ o.incSource = '';// link to source folder
758
+ o.incForce = o.F;// reload loaded files or not
759
+ o.incAsync = true;// async or in order loading
760
+ o.incCors = o.F;// allow loading from other domains
761
+
762
+ /* service values */
763
+ o.incFns = {};// array of name:status for all functions
764
+ o.incSet = [o.Z];// saving callbacks and change them for 1 value if executed
765
+ o.incReady = [o.Z];// array of all included sets and statuses
766
+ o.incN = o.Z;// index of the next set
767
+
768
+ /**
769
+ * Check the state status or a function in it, also checks its status to true
770
+ *
771
+ * @param {number} set index
772
+ * @param {number} fnId index
773
+ * @returns {boolean}
774
+ */
775
+ o.incCheck = (set = 0, fnId, loaded = 0) => {
776
+ if (!loaded && set && fnId === o.U && o.incReady[set]) {
777
+ return o.incSet[set] === o.N;
778
+ }
779
+
780
+ if (o.incReady[set] === o.U || o.incReady[set][fnId] === o.U) {
781
+ return o.F;
782
+ }
783
+
784
+ o.incReady[set][fnId].loaded = loaded;
785
+ o.incFns[o.incReady[set][fnId].name] = loaded;
786
+ o.incReady[set][o.Z] += loaded;
787
+
788
+ if (set && o.incReady[set].length === o.incReady[set][o.Z]) {
789
+ if (typeof o.incSet[set] === 'function') {
790
+ o.incSet[set](set);
791
+ }
792
+ o.incSet[set] = o.N;
793
+ }
794
+
795
+ return o.incSet[set] === o.N;
796
+ };
797
+ /* Clear all cache and all loaded sets info */
798
+ o.incCacheClear = (all = o.F) => {
799
+ for (const name in o.incFns) {
800
+ if (o.C(o.incFns, name)) {
801
+ localStorage.removeItem('inc-' + name);
802
+ localStorage.removeItem('inc-' + name + 'Expires');
803
+ }
804
+ }
805
+ if (all) {
806
+ o.incReady.forEach((val, i) => {
807
+ if (i) {
808
+ val.forEach((a, j) => {
809
+ if (j) {
810
+ o('#oInc-' + i + '-' + j).remove();
811
+ }
812
+ });
813
+ }
814
+ });
815
+
816
+ o.incN = o.Z
817
+ o.incFns = {};
818
+ o.incSet = [o.Z];
819
+ o.incReady = [o.Z];
820
+ }
821
+ return true;
822
+ };
823
+ /* Main function to include */
824
+ o.inc = (sources, callBack, callBad) => {
825
+ let sourcesN = o.Z,
826
+ sourcesReady = o.Z;
827
+ const f = 'function',
828
+ FOUR = 4,
829
+ no = -1;
830
+
831
+ if (typeof sources !== 'object' || !sources) {
832
+ return o.incSet[o.Z];
833
+ }
834
+
835
+ o.incSet[o.Z]++;
836
+ const setN = o.incSet[o.Z];
837
+ o.incSet[setN] = callBack || o.Z;
838
+ o.incReady[setN] = [];
839
+ const fnsStatus = o.incReady[setN];
840
+ fnsStatus[o.Z] = o.N;
841
+ const fnId = {};
842
+
843
+ for (let name in sources) {
844
+ if (o.C(sources, name)) {
845
+ sourcesN++;
846
+ o.incN++;
847
+
848
+ let tag = sources[name].indexOf('.css') > no ? 'style' : 'script';
849
+ sources[name] = (o.incSource ? o.incSource + '/' : '') + sources[name];
850
+ // skip loading if already loaded and not forced
851
+ if (isNaN(name) && o.C(o.incFns, name) && o.incFns[name] && !o.incForce) {
852
+ fnsStatus[sourcesN] = {
853
+ name,
854
+ loaded: o.N,
855
+ };
856
+ sourcesReady++;
857
+ continue;
858
+ }
859
+
860
+ // fixing if loaded needed
861
+ fnsStatus[sourcesN] = {
862
+ name,
863
+ loaded: o.Z,
864
+ };
865
+
866
+ if (isNaN(name)) {
867
+ o.incFns[name] = o.Z;
868
+ }
869
+
870
+ if (
871
+ isNaN(name) &&
872
+ o.incCache &&
873
+ sources[name].substring(o.Z, FOUR) !== 'http' &&
874
+ window.location.protocol !== 'file:' &&
875
+ (sources[name].indexOf('.css') > no || sources[name].indexOf('.js') > no)
876
+ ) {
877
+ // if cache is enabled
878
+ const ls = localStorage,
879
+ script = ls.getItem('inc-' + name),
880
+ cacheSavedTill = ls.getItem('inc-' + name + 'Expires');
881
+
882
+ if (
883
+ script &&
884
+ cacheSavedTill &&
885
+ new Date().getTime() < cacheSavedTill
886
+ ) {
887
+ // load from cache
888
+ o.initState({
889
+ tag,
890
+ id: 'oInc-' + setN + '-' + sourcesN,
891
+ innerHTML: script,
892
+ 'data-o-inc': setN,
893
+ }).appendInside('head');
894
+ fnsStatus[sourcesN].loaded = o.N;
895
+ o.incFns[name] = o.N;
896
+ sourcesReady++;
897
+ } else {
898
+ // loading and caching new files
899
+ fnId[name] = sourcesN;
900
+ o.get(sources[name], {mode: o.incCors ? 'cors' : 'same-origin'}).then((response) => {
901
+ if (response.status !== 200) {
902
+ o.onError ? o.onError({message: o.incSource + sources[name] + ' was not loaded'}) : '';
903
+ return;
904
+ }
905
+ response.text().then((script) => {
906
+ ls.setItem('inc-' + name, script);
907
+ ls.setItem('inc-' + name + 'Expires', new Date().getTime() + o.incCacheExp);
908
+ o.initState({
909
+ tag,
910
+ id: 'oInc-' + setN + '-' + fnId[name],
911
+ innerHTML: script,
912
+ 'data-o-inc': setN,
913
+ }).appendInside('head');
914
+ o.incCheck(setN, fnId[name], o.N);
915
+ });
916
+ });
917
+ }
918
+ } else {
919
+ // standart loading without caching
920
+ const state = {
921
+ tag,
922
+ id: 'oInc-' + setN + '-' + sourcesN,
923
+ 'data-o-inc': setN,
924
+ async: o.incAsync,
925
+ onload: 'o.incCheck(' + setN + ',' + sourcesN + ',1)',
926
+ };
927
+ if (sources[name].indexOf('.css') > no) {
928
+ state.tag = 'link';
929
+ state.rel = 'stylesheet';
930
+ state.href = sources[name];
931
+ } else if (sources[name].indexOf('.js') > no) {
932
+ state.src = sources[name];
933
+ } else {
934
+ state.tag = 'img';
935
+ state.style = 'display:none;';
936
+ state.src = sources[name];
937
+ }
938
+ o.initState(state).appendInside(state.style ? 'body' : 'head');
939
+ }
940
+ }
941
+ }
942
+
943
+ fnsStatus[o.Z] += sourcesReady;
944
+
945
+ if (sourcesN !== o.Z) {
946
+ if (sourcesReady === sourcesN) {
947
+ // if everything included
948
+ if (typeof callBack === f) {
949
+ callBack(setN);
950
+ }
951
+ } else {
952
+ // starting timeout for loading
953
+ setTimeout((set) => {
954
+ if (o.incReady[set] && o.incReady[set].length < o.incReady[set][o.Z]) {
955
+ o.incSet[set] = o.Z;
956
+ if (typeof callBad === f) {
957
+ callBad(setN);
958
+ }
959
+ }
960
+ }, o.incTimeout, setN);
961
+ }
962
+ }
963
+
964
+ return o.incSet[o.Z];
965
+ };
966
+
967
+
968
+
969
+
970
+
971
+
972
+
973
+
974
+
975
+
976
+
977
+
978
+
979
+
980
+
981
+
982
+
983
+
984
+
985
+
986
+
987
+
988
+ /**
989
+ * Test function
990
+ *
991
+ * @param {string} title
992
+ * @param {array} tests array with name:function to test - true is success, false/string for failure
993
+ *
994
+ * @returns {number} test session number in o.tLog
995
+ */
996
+
997
+ /* parameters */
998
+ o.tLog = [];// test sessions and results
999
+ o.tRes = [];// test results
1000
+ o.tStatus = [];// test statuses
1001
+ o.tFns = [];// callbacks
1002
+ o.tShowOk = o.F;// show success tests or only errors
1003
+ o.tStyled = o.F;// styled HTML results or plain style
1004
+ o.tTime = 2000;// timeout for async tests
1005
+
1006
+ // service
1007
+ o.tPre = '<div style="font-family:monospace;text-align:left;">';
1008
+ o.tOk = '<span style="background:#cfc;padding: 0 15px;">OK</span> ';
1009
+ o.tXx = '<div style="background:#fcc;padding:3px;">';
1010
+ o.tDc = '</div>';
1011
+
1012
+ /* Main function for testing */
1013
+ o.test = (title = '', ...tests) => {
1014
+ const testN = o.tLog.length;
1015
+ let waits = 0,
1016
+ preOk = '├ OK: ',
1017
+ preXx = '├ ✘ ',
1018
+ posOk = '\n',
1019
+ posXx = '\n',
1020
+ num = tests.length,
1021
+ done = o.Z;
1022
+
1023
+ if (typeof tests[num - o.N] === 'function') {
1024
+ o.tFns[testN] = tests[num - o.N];
1025
+ num--;
1026
+ }
1027
+
1028
+ if (o.tStyled) {
1029
+ o.tLog[testN] = '<div><b>' + title + ' #' + testN + '</b></div>';
1030
+ preOk = o.tPre + o.tOk;
1031
+ preXx = o.tPre + o.tXx;
1032
+ posOk = o.tDc;
1033
+ posXx = posOk + posOk;
1034
+ } else {
1035
+ o.tLog[testN] = title + ' #' + testN + '\n';
1036
+ }
1037
+
1038
+ o.tRes[testN] = o.F;
1039
+ o.tStatus[testN] = [];
1040
+
1041
+ for (let i = o.Z; i < num; i++) {
1042
+ const testInfo = {
1043
+ n: testN,
1044
+ i,
1045
+ title: tests[i][o.Z],
1046
+ tShowOk: o.tShowOk,
1047
+ tStyled: o.tStyled,
1048
+ };
1049
+ let res = tests[i][o.N];
1050
+ if (typeof res === 'function') {
1051
+ try {
1052
+ res = res(testInfo);
1053
+ } catch (error) {
1054
+ res = error.message;
1055
+ if (o.onError) {
1056
+ o.onError(error);
1057
+ }
1058
+ }
1059
+ }
1060
+ o.tStatus[testN][i] = typeof res === 'string' ? o.F : res;
1061
+ if (res === true) {
1062
+ done++;
1063
+ if (o.tShowOk) {
1064
+ o.tLog[testN] += preOk + tests[i][o.Z] + posOk;
1065
+ }
1066
+ } else if (res !== o.U) {
1067
+ o.tLog[testN] += preXx + tests[i][o.Z] + (res !== o.F ? ': <i>' + res + '</i>' : '') + posXx;
1068
+ } else {
1069
+ waits++;
1070
+ setTimeout((info) => {
1071
+ info.title += ' (timeout)';
1072
+ o.testUpdate(info);
1073
+ }, o.tTime, testInfo);
1074
+ }
1075
+ }
1076
+
1077
+ o.tRes[testN] = done === num;
1078
+
1079
+ if (o.tStyled) {
1080
+ o.tLog[testN] += o.tPre + '<div style="color:' + (done + waits !== num ? 'red' : 'green') + ';"><b>';
1081
+ } else {
1082
+ o.tLog[testN] += waits ? '├' : '└ ';
1083
+ }
1084
+
1085
+ o.tLog[testN] += 'DONE ' + done + '/' + (num - waits);
1086
+
1087
+ if (waits) {
1088
+ o.tLog[testN] += ', waiting: ' + waits;
1089
+ }
1090
+
1091
+ if (o.tStyled) {
1092
+ o.tLog[testN] += '</b>' + o.tDc + o.tDc;
1093
+ } else {
1094
+ o.tLog[testN] += '\n';
1095
+ }
1096
+
1097
+ if (!waits && typeof o.tFns[testN] === 'function') {
1098
+ o.tFns[testN](testN);
1099
+ }
1100
+
1101
+ return testN;
1102
+ };
1103
+
1104
+ /* Function to update test state for async tests */
1105
+ o.testUpdate = (info, res = o.F, suff = '') => {
1106
+ if (o.tStatus[info.n][info.i] === o.U) {
1107
+ o.tStatus[info.n][info.i] = res === true;
1108
+ if (res === true) {
1109
+ if (info.tShowOk) {
1110
+ if (info.tStyled) {
1111
+ o.tLog[info.n] += o.tPre + o.tOk + info.title + suff + o.tDc;
1112
+ } else {
1113
+ o.tLog[info.n] += '└ OK: ' + info.title + suff + '\n';
1114
+ }
1115
+ }
1116
+ } else {
1117
+ o.tRes[info.n] = o.F;
1118
+ if (info.tStyled) {
1119
+ o.tLog[info.n] += o.tPre + o.tXx + info.title + suff + (res ? ': ' + res : '') + o.tDc + o.tDc;
1120
+ } else {
1121
+ o.tLog[info.n] += '└ ✘ ' + info.title + (res ? ': ' + res : '') + suff + '\n';
1122
+ }
1123
+ }
1124
+
1125
+ let fails = o.Z,
1126
+ n = fails;
1127
+
1128
+ for (let s of o.tStatus[info.n]) {
1129
+ if (s === o.U) {
1130
+ return;
1131
+ }
1132
+ if (!s) {
1133
+ fails++;
1134
+ }
1135
+ n++;
1136
+ }
1137
+
1138
+ o.tRes[info.n] = !fails;
1139
+ const text = fails ? 'FAILED ' + fails + '/' + n : 'DONE ' + n + '/' + n;
1140
+ if (info.tStyled) {
1141
+ o.tLog[info.n] += o.tPre + '<b style="color:' + (!fails ? 'green' : 'red') + ';">' + text + '</b>' + o.tDc;
1142
+ } else {
1143
+ o.tLog[info.n] += '└ ' + text;
1144
+ }
1145
+
1146
+ if (typeof o.tFns[info.n] === 'function') {
1147
+ o.tFns[info.n](info.n);
1148
+ }
1149
+ }
1150
+ };