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/LICENSE.md +201 -0
- package/README.md +69 -0
- package/objs.1.0.js +1150 -0
- package/objs.1.0.min.js +2 -0
- package/objs.npm.1.0.js +13 -0
- package/package.json +31 -0
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
|
+
};
|