-
Notifications
You must be signed in to change notification settings - Fork 1
/
liwra.js
106 lines (88 loc) · 3 KB
/
liwra.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
((global, factory) => {
if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = factory();
else global.liwra = factory();
})(this, () => { 'use strict';
// to update with future `Array.prototype`'s methods that return new arrays
const WRAPPED_ARRAY_METHODS = [
'concat',
'filter',
'flat',
'map',
'slice',
];
const isArrayLike = v => (
typeof v !== 'string' &&
(typeof Node === 'undefined' || !(v instanceof Node)) &&
typeof v[Symbol.iterator] === 'function'
);
const isIndex = (_, prop) => {
try { return !isNaN(Number(prop)) }
catch { return false }
}
const isFromArray = (target, prop) => {
return typeof target[prop] !== 'undefined';
}
const isMethod = (target, prop) => {
return typeof target[0][prop] === 'function';
}
const wrap = lst => {
const unwrap = target => (idx, end) => {
if (typeof idx === 'undefined') return target
if (typeof end === 'undefined') {
const nextItem = idx === -1 ? target.length : idx + 1;
return target.slice(idx, nextItem)[0];
}
return target.slice(idx, end);
}
const get = (target, prop) => {
if (prop === 'isWrapped') return true;
if (prop === 'exists') return target.length !== 0;
if (prop === 'unwrap') return unwrap(target);
if (target.length === 0) return wrap(target);
if (isIndex(target, prop)) return target[prop];
if (isFromArray(target, prop)) {
if (WRAPPED_ARRAY_METHODS.includes(prop)) {
return (...args) => wrap(target[prop](...args));
}
if (typeof target[prop] === 'function') {
return (...args) => target[prop](...args);
}
return target[prop];
}
if (isMethod(target, prop)) {
return (...args) => wrap(target.map(v => {
if (typeof v[prop] !== 'function') return undefined;
return v[prop].apply(v, args);
}));
}
// if is value
return wrap(target.map(v => v[prop]));
}
const has = (target, prop) => {
if (['isWrapped', 'exists', 'unwrap'].includes(prop)) return true;
if (isIndex(target, prop) && prop in target) return true;
if (isFromArray(target, prop)) return true;
if (isMethod(target, prop)) return true;
return prop in target[0];
}
const set = (target, prop, value) => {
target.forEach(v => v[prop] = value);
return true;
}
if (lst.isWrapped) return lst;
return new Proxy(
(isArrayLike(lst) ? [...lst] : [lst]).filter(v => v !== undefined),
{ get, set, has }
)
}
const querySelect = (root, selector) => {
if (typeof root === 'string' && typeof selector === 'undefined') {
selector = root;
root = document;
}
const res = wrap(root).querySelectorAll(selector)
.reduce((r, nl) => [...r, ...nl], []);
return wrap(res);
}
return Object.assign(wrap, {querySelect});
});