@microdom/mode 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 +21 -0
- package/README.md +135 -0
- package/dist/mode.js +455 -0
- package/dist/mode.min.js +2 -0
- package/package.json +25 -0
- package/src/index.js +1 -0
- package/src/mode.js +455 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Silvio Corigliano
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
|
|
2
|
+
# Mode JS
|
|
3
|
+
|
|
4
|
+
**Mode JS** is a low-level interaction engine for the web.
|
|
5
|
+
It belongs to the **Microdom** ecosystem.
|
|
6
|
+
|
|
7
|
+
It does not provide widgets, components, or behaviors.
|
|
8
|
+
It provides a way to reason about **movement**, **intent**, and **structure**.
|
|
9
|
+
|
|
10
|
+
Mode JS is designed for developers who want to *build* interactions,
|
|
11
|
+
not configure them.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What Mode JS is
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
- A low-level interaction primitive
|
|
19
|
+
- Pointer- and touch-aware
|
|
20
|
+
- Minimal by design
|
|
21
|
+
- Framework-agnostic
|
|
22
|
+
- DOM-friendly
|
|
23
|
+
- Data-binding ready
|
|
24
|
+
|
|
25
|
+
Mode JS helps you express *how things move* — not *what they are*.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What Mode JS is not
|
|
30
|
+
|
|
31
|
+
- ❌ A WebComponents library
|
|
32
|
+
- ❌ A UI framework
|
|
33
|
+
- ❌ A state machine
|
|
34
|
+
- ❌ A collection of ready-made behaviors
|
|
35
|
+
|
|
36
|
+
Those things can be **built with Mode JS**, but they do not belong inside it.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
### Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @microdom/mode
|
|
43
|
+
```
|
|
44
|
+
**Usage**
|
|
45
|
+
```bash
|
|
46
|
+
import µ from "@microdom/mode"
|
|
47
|
+
// or: import { µ } from "@microdom/mode"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**CDN**
|
|
51
|
+
```html
|
|
52
|
+
<script src="https://cdn.jsdelivr.net/gh/microdom/mode.js/dist/mode.min.js"></script>
|
|
53
|
+
<script>
|
|
54
|
+
µ("body", { /* ... */ })
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Why Mode JS exists
|
|
60
|
+
|
|
61
|
+
Most interaction libraries:
|
|
62
|
+
- abstract too early
|
|
63
|
+
- hide intent behind state
|
|
64
|
+
- grow uncontrollably
|
|
65
|
+
- break at the edges (touch, empty states, nested structures)
|
|
66
|
+
|
|
67
|
+
Mode JS takes a different approach:
|
|
68
|
+
|
|
69
|
+
> **Movement first.
|
|
70
|
+
> Intent is explicit.
|
|
71
|
+
> Structure matters more than features.**
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Why not X?
|
|
76
|
+
|
|
77
|
+
Modern UI stacks often require tens of kilobytes of code
|
|
78
|
+
to express a simple interaction.
|
|
79
|
+
|
|
80
|
+
Mode JS asks a different question:
|
|
81
|
+
|
|
82
|
+
> *How much code do you actually need
|
|
83
|
+
> to make something feel right?*
|
|
84
|
+
|
|
85
|
+
```md
|
|
86
|
+
A complete multi-list sortable with touch support
|
|
87
|
+
can be built in **~6 KB total**.
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Read the full comparison in
|
|
91
|
+
[`docs/why-not-x.md`](docs/why-not-x.md).
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### Code weight in perspective
|
|
96
|
+
>Characters © Team Cherry
|
|
97
|
+
|
|
98
|
+

|
|
99
|
+
|
|
100
|
+
> The little one can rule the town.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Repository structure
|
|
105
|
+
|
|
106
|
+
If you’re looking for examples, start in **/demos**.
|
|
107
|
+
If you’re looking for ideas, start in **/docs**.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Demos
|
|
112
|
+
|
|
113
|
+
- **Sortable (multi-list + touch)**
|
|
114
|
+
A complete sortable interaction built with ~6 KB of code.
|
|
115
|
+
Demonstrates intent gating, empty container handling, and cross-list movement.
|
|
116
|
+
|
|
117
|
+
Each demo is intentionally **self-contained**.
|
|
118
|
+
They are not plugins — they are *proofs of thought*.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Philosophy
|
|
123
|
+
|
|
124
|
+
Mode JS is opinionated:
|
|
125
|
+
|
|
126
|
+
> “If an interaction cannot be expressed simply,
|
|
127
|
+
> the abstraction is probably wrong.”
|
|
128
|
+
|
|
129
|
+
Read more in [`docs/philosophy.md`](docs/philosophy.md).
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|
package/dist/mode.js
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
|
|
2
|
+
function µ(el, fns) {
|
|
3
|
+
const _ = null
|
|
4
|
+
const roneTag = (/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i)
|
|
5
|
+
const rhtml = /<|&#?\w+;/
|
|
6
|
+
const rtagName = (/<([a-z][^\/\0>\x20\t\r\n\f]*)/i)
|
|
7
|
+
const whitespace = "[\\x20\\t\\r\\n\\f]"
|
|
8
|
+
const rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g")
|
|
9
|
+
const tr = (s) => s.replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/(\r\n|\n|\r)/gm, "").replace(/>\s+</g, '><')
|
|
10
|
+
const arr = ( b , n=null) => n? n=='array'? Array.from(b) : Object[n](b) : Object.entries(b)
|
|
11
|
+
const __ = {
|
|
12
|
+
html,
|
|
13
|
+
text,
|
|
14
|
+
insert,
|
|
15
|
+
on,
|
|
16
|
+
each,
|
|
17
|
+
proceed,
|
|
18
|
+
find,
|
|
19
|
+
css,
|
|
20
|
+
classes,
|
|
21
|
+
clss,
|
|
22
|
+
attr,
|
|
23
|
+
prev,
|
|
24
|
+
next,
|
|
25
|
+
parents,
|
|
26
|
+
childs,
|
|
27
|
+
after,
|
|
28
|
+
children,
|
|
29
|
+
last,
|
|
30
|
+
first,
|
|
31
|
+
siblingsAll,
|
|
32
|
+
siblings,
|
|
33
|
+
filter,
|
|
34
|
+
wrap
|
|
35
|
+
}
|
|
36
|
+
function el_(s) {
|
|
37
|
+
s.forEach(e => e.setAttribute(`µicro`, "µ"))
|
|
38
|
+
_el = getEl(`/[µicro]/`)
|
|
39
|
+
_el.forEach(e => e.removeAttribute(`µicro`))
|
|
40
|
+
}
|
|
41
|
+
const nodeDom = (t, att, tx, ch) => {
|
|
42
|
+
let o = document.createElement(t)
|
|
43
|
+
function val(v) {
|
|
44
|
+
return typeof v !== 'object' ? v : Object.keys(v).map((e) => `${e}:${v[e]}`).join(';')
|
|
45
|
+
}
|
|
46
|
+
for (const key in att) o.setAttribute(key, val(att[key]))
|
|
47
|
+
if (tx) {
|
|
48
|
+
let newtext = document.createTextNode(tx)
|
|
49
|
+
o.appendChild(newtext)
|
|
50
|
+
}
|
|
51
|
+
for (const key in childs) o.appendChild(childs[key])
|
|
52
|
+
return o
|
|
53
|
+
}
|
|
54
|
+
let _el = el !== _ ? getEl(el) : el
|
|
55
|
+
if (!!fns) {
|
|
56
|
+
for (let [fn, p] of Object.entries(fns)) {
|
|
57
|
+
fn = fn.replace(/_/g, '')
|
|
58
|
+
_el && typeof __[fn] === 'function' ? __[fn](p) : null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function getEl(e) {
|
|
62
|
+
e = isStr(e) ? tr(e) : e
|
|
63
|
+
const sel = (s, c) => s.at(0) == '/' && s.at(-1) == '/' ? c.querySelectorAll(s.replace(/^\/|\/$/g, '')) : c.querySelector(s)
|
|
64
|
+
if (isEl(e) || isList(e)) {
|
|
65
|
+
return e
|
|
66
|
+
} else if (isArr(e)) {
|
|
67
|
+
let s, c
|
|
68
|
+
if (isStr(e[1])) {
|
|
69
|
+
c = document.querySelector(e[1])
|
|
70
|
+
} else if (isEl(e[1])) {
|
|
71
|
+
c = e[1]
|
|
72
|
+
}
|
|
73
|
+
if (isStr(e[0])) {
|
|
74
|
+
s = e[0]
|
|
75
|
+
return sel(s, c)
|
|
76
|
+
}
|
|
77
|
+
if (isEl(e[0])) {
|
|
78
|
+
return e
|
|
79
|
+
}
|
|
80
|
+
return console.error('Array error')
|
|
81
|
+
} else if (isHtml(e)) {
|
|
82
|
+
return parseHTML(e)
|
|
83
|
+
} else if (isStr(e)) {
|
|
84
|
+
return sel(e, document)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function isArr(e) { return Array.isArray(e) }
|
|
88
|
+
function isEl(e) { return e instanceof HTMLElement /* || e.nodeType */ }
|
|
89
|
+
function isList(e) { return NodeList.prototype.isPrototypeOf(e) }
|
|
90
|
+
function isStr(e) { return typeof e === 'string' || e instanceof String }
|
|
91
|
+
function isColl(e) { return HTMLCollection.prototype.isPrototypeOf(e) }
|
|
92
|
+
function isHtml(e) { return e[0] === "<" && e[e.length - 1] === ">" }
|
|
93
|
+
// Helpers
|
|
94
|
+
function html(p) {
|
|
95
|
+
if (!isStr(p)) return false
|
|
96
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => el.innerHTML = p) : _el.innerHTML = p
|
|
97
|
+
}
|
|
98
|
+
function text(p) {
|
|
99
|
+
if (!isStr(p)) return false
|
|
100
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => el.textContent = p) : _el.textContent = p
|
|
101
|
+
}
|
|
102
|
+
function parseHTML(p) {
|
|
103
|
+
let o = nodeDom('div', {}, '', '')
|
|
104
|
+
o.insertAdjacentHTML("beforeend", p.replace(/\s+/g, ' '))
|
|
105
|
+
return o.firstChild
|
|
106
|
+
}
|
|
107
|
+
function insert(p) {
|
|
108
|
+
if ( isHtml(p)) _el.insertAdjacentHTML("beforeend", p.replace(/\s+/g, ' '))
|
|
109
|
+
else if( isEl(p)) _el.appendChild(p)
|
|
110
|
+
}
|
|
111
|
+
function on(p) {
|
|
112
|
+
const add = (e, fn, el = null) => {
|
|
113
|
+
el = !!el ? el : _el
|
|
114
|
+
console.log(el, "····")
|
|
115
|
+
isList(el) || isArr(el) ? el.forEach(l => l.addEventListener(e, fn, false)) :
|
|
116
|
+
el.addEventListener(e, fn, false)
|
|
117
|
+
}
|
|
118
|
+
const ctm = (c, t, fn) => {
|
|
119
|
+
_el.addEventListener(e, fn, false)
|
|
120
|
+
}
|
|
121
|
+
const on = (o) => {
|
|
122
|
+
if (o.e)
|
|
123
|
+
isArr(o.e) ? o.e.forEach(n => add(n, o.fn)) : add(o.e, o.fn)
|
|
124
|
+
if (o.l) {
|
|
125
|
+
isArr(o.l) ? o.l.forEach(n => add(o.e, n.fn, n.tg)) : add(o.e, o.l.fn, o.l.tg)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
isArr(p) ? p.forEach(e => on(e)) : on(p)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function each(p) {
|
|
132
|
+
isList(_el) || isArr(_el) ? _el.forEach(p) : p(_el)
|
|
133
|
+
}
|
|
134
|
+
function proceed(p) {
|
|
135
|
+
_el = p(_el)
|
|
136
|
+
}
|
|
137
|
+
function find(p) {
|
|
138
|
+
const xel = (s, c) => s.at(0) == '/' && s.at(-1) == '/' ? c.querySelectorAll(s.replace(/^\/|\/$/g, '')) : c.querySelector(s)
|
|
139
|
+
let n, found = document.createElement('div')
|
|
140
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => {
|
|
141
|
+
n = xel(p, el)
|
|
142
|
+
if (n != null) found.append(n)
|
|
143
|
+
}) : _el = getEl([p, _el])
|
|
144
|
+
if (found.childNodes.length > 0) _el = found.childNodes
|
|
145
|
+
}
|
|
146
|
+
function css(p) {
|
|
147
|
+
const add = (s, v) => {
|
|
148
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => el.style[s] = v) : _el.style[s] = v
|
|
149
|
+
}
|
|
150
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
151
|
+
}
|
|
152
|
+
function classes(p) {
|
|
153
|
+
const add = (s, v) => {
|
|
154
|
+
const set = (el, s, v) => { isArr(v) ? v.forEach(i => el.classList[s](i)) : el.classList[s](v) }
|
|
155
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => set(el, s, v)) : set(_el, s, v)
|
|
156
|
+
}
|
|
157
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
158
|
+
}
|
|
159
|
+
function clss(p) {
|
|
160
|
+
const add = (s, v) => {
|
|
161
|
+
const set = (el, s, v) => { isArr(v) ? v.forEach(i => el.classList[s](i)) : el.classList[s](v) }
|
|
162
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => set(el, s, v)) : set(_el, s, v)
|
|
163
|
+
}
|
|
164
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
165
|
+
}
|
|
166
|
+
function attr(p) {
|
|
167
|
+
const bin =(el,s,v) => {
|
|
168
|
+
switch (s) {
|
|
169
|
+
case "set": el.setAttribute(arr(v)[0][0],arr(v)[0][1]);break
|
|
170
|
+
case "get": el.getAttribute(v);break
|
|
171
|
+
case "del": el.removeAttribute(v);break
|
|
172
|
+
case "has": el.hasAttribute(v);break
|
|
173
|
+
case "tog": el.toggleAttribute(v);break
|
|
174
|
+
case "list": el.getAttributeNames()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const add = (s, v) => {
|
|
178
|
+
const set = (el, s, v) => { isArr(v) ? v.forEach(i => bin(el,s,i)) : bin(el,s,v) }
|
|
179
|
+
isList(_el) || isArr(_el) ? _el.forEach( el => set(el, s, v)) : set(_el, s, v)
|
|
180
|
+
}
|
|
181
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
182
|
+
}
|
|
183
|
+
function prev(p) {
|
|
184
|
+
if (isList(_el)) return false
|
|
185
|
+
if (p) {
|
|
186
|
+
let prev = _el.previousElementSibling
|
|
187
|
+
while (prev && !prev.matches(p)) prev = prev.previousElementSibling
|
|
188
|
+
_el = prev
|
|
189
|
+
} else {
|
|
190
|
+
_el = _el.previousElementSibling
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function next(p) {
|
|
194
|
+
if (isList(_el)) return false
|
|
195
|
+
if (p) {
|
|
196
|
+
let next = _el.nextElementSibling
|
|
197
|
+
while (next && !next.matches(p)) next = next.nextElementSibling
|
|
198
|
+
_el = next;
|
|
199
|
+
} else {
|
|
200
|
+
_el = _el.nextElementSibling
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function parents(p) {
|
|
205
|
+
if (!isEl(_el)) return false
|
|
206
|
+
const parents = []
|
|
207
|
+
el = _el
|
|
208
|
+
while ((el = el.parentNode) && el !== document) {
|
|
209
|
+
(!p || el.matches(p)) ? parents.push(el) : _
|
|
210
|
+
}
|
|
211
|
+
_el = parents
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function childs(p) {
|
|
215
|
+
if (!isEl(_el)) return false
|
|
216
|
+
let el = []
|
|
217
|
+
for (const e of _el.childNodes) {
|
|
218
|
+
isEl(e) && (!p || e.matches(p)) ? el.push(e) : _
|
|
219
|
+
}
|
|
220
|
+
el_(el)
|
|
221
|
+
}
|
|
222
|
+
function after(p) {
|
|
223
|
+
if (!isEl(_el)) return false
|
|
224
|
+
_el.parentNode.insertBefore(p, _el.nextSibling);
|
|
225
|
+
}
|
|
226
|
+
function children(p) {
|
|
227
|
+
if (!isEl(_el)) return false
|
|
228
|
+
el = [..._el.children].filter((child) => p ? child.matches(p) : child)
|
|
229
|
+
el_(el)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function last(p) {
|
|
233
|
+
if (!isList(_el) && !isArr(_el)) return null
|
|
234
|
+
let child
|
|
235
|
+
isStr(p) ?
|
|
236
|
+
_el.forEach(e => e.matches(p) ? child = e : _)
|
|
237
|
+
: _el.forEach(e => child = e)
|
|
238
|
+
_el = child
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function first(p) {
|
|
242
|
+
if (!isList(_el) && !isArr(_el)) return null
|
|
243
|
+
if (isStr(p)) {
|
|
244
|
+
try {
|
|
245
|
+
_el.forEach(r => { if (r.matches(p)) throw _el = r, "break" })
|
|
246
|
+
} catch (r) { if ("break" !== r) throw r }
|
|
247
|
+
} else {
|
|
248
|
+
try {
|
|
249
|
+
_el.forEach((r, i) => { if (i === 0) throw _el = r, "break" })
|
|
250
|
+
} catch (r) { if ("break" !== r) throw r }
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function siblingsAll(p) {
|
|
254
|
+
if (!isEl(_el)) return false
|
|
255
|
+
el = [..._el.parentNode.children].filter((child) => p ? child.matches(p) : child)
|
|
256
|
+
el_(el)
|
|
257
|
+
}
|
|
258
|
+
function siblings(p) {
|
|
259
|
+
if (!isEl(_el)) return false
|
|
260
|
+
el = [..._el.parentNode.children].filter((child) => p ? child.matches(p) && child !== _el : child !== _el)
|
|
261
|
+
el_(el)
|
|
262
|
+
}
|
|
263
|
+
function filter(p) {
|
|
264
|
+
if (!isList(_el) || !p) return false
|
|
265
|
+
el = [..._el].filter((item) => item.matches(p))
|
|
266
|
+
el_(el)
|
|
267
|
+
}
|
|
268
|
+
function wrap(p) {
|
|
269
|
+
const add = (e, w) => {
|
|
270
|
+
e.parentElement.insertBefore(w, e)
|
|
271
|
+
w.appendChild(e)
|
|
272
|
+
}
|
|
273
|
+
(isList(_el) || isArr(_el)) ? _el.forEach(e => add(e, p.cloneNode())) : add(_el, p.cloneNode())
|
|
274
|
+
}
|
|
275
|
+
return isArr(_el) && _el.length === 0 ? _ : _el
|
|
276
|
+
}
|
|
277
|
+
function moveDOM(fns) {
|
|
278
|
+
const _ = null
|
|
279
|
+
let _return
|
|
280
|
+
if (fns) {
|
|
281
|
+
for (let [fn, params] of Object.entries(fns)) {
|
|
282
|
+
fn = fn.replace(/_/g, '')
|
|
283
|
+
typeof eval(fn) === 'function' ? eval(fn)(params) : null
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function isArr(e) { return Array.isArray(e) }
|
|
287
|
+
function isEl(e) { return e instanceof HTMLElement }
|
|
288
|
+
function isList(e) { return NodeList.prototype.isPrototypeOf(e) }
|
|
289
|
+
function isStr(e) { return typeof e === 'string' || e instanceof String }
|
|
290
|
+
function wrap(p) {
|
|
291
|
+
const add = (e, w) => {
|
|
292
|
+
e.parentElement.insertBefore(w, e)
|
|
293
|
+
w.appendChild(e)
|
|
294
|
+
}
|
|
295
|
+
isList(p.el) ? p.el.forEach(e => add(e, p.wrp.cloneNode())) : add(p.el, p.wrp.cloneNode())
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function slideUp(p) {
|
|
299
|
+
let css = {
|
|
300
|
+
transitionProperty: 'height, margin, padding',
|
|
301
|
+
transitionDuration: p.t + 'ms',
|
|
302
|
+
boxSizing: 'border-box',
|
|
303
|
+
height: p.el.offsetHeight + 'px'
|
|
304
|
+
}
|
|
305
|
+
let css2 = {
|
|
306
|
+
overflow: 'hidden',
|
|
307
|
+
height: 0,
|
|
308
|
+
paddingTop: 0,
|
|
309
|
+
paddingBottom: 0,
|
|
310
|
+
marginTop: 0,
|
|
311
|
+
marginBottom: 0
|
|
312
|
+
}
|
|
313
|
+
µ(p.el, { css: css })
|
|
314
|
+
p.el.offsetHeight
|
|
315
|
+
µ(p.el, { css: css2 })
|
|
316
|
+
setTimeout(() => {
|
|
317
|
+
['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'overflow', 'transition-duration', 'transition-property']
|
|
318
|
+
.forEach(i => p.el.style.removeProperty(i))
|
|
319
|
+
p.el.style.display = 'none'
|
|
320
|
+
p.fn ? p.fn() : _
|
|
321
|
+
}, p.t)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function slideDown(p) {
|
|
325
|
+
let display = getComputedStyle(p.el).display
|
|
326
|
+
if (display === 'none') display = 'block'
|
|
327
|
+
p.el.style.display = display
|
|
328
|
+
let height = p.el.offsetHeight
|
|
329
|
+
const time = Math.ceil(p.t * (height / 200))
|
|
330
|
+
console.log("time >>", time)
|
|
331
|
+
let css = {
|
|
332
|
+
overflow: 'hidden',
|
|
333
|
+
height: 0,
|
|
334
|
+
paddingTop: 0,
|
|
335
|
+
paddingBottom: 0,
|
|
336
|
+
marginTop: 0,
|
|
337
|
+
marginBottom: 0,
|
|
338
|
+
}
|
|
339
|
+
let css2 = {
|
|
340
|
+
boxSizing: 'border-box',
|
|
341
|
+
transitionProperty: "height, margin, padding",
|
|
342
|
+
transitionDuration: time + 'ms',
|
|
343
|
+
height: height + 'px'
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
µ(p.el, {
|
|
347
|
+
css: css
|
|
348
|
+
})
|
|
349
|
+
p.el.offsetHeight
|
|
350
|
+
µ(p.el, { css: css2 })
|
|
351
|
+
let a = ['padding-top', 'padding-bottom', 'margin-top', 'margin-bottom']
|
|
352
|
+
.forEach(i => p.el.style.removeProperty(i))
|
|
353
|
+
setTimeout(() => {
|
|
354
|
+
['height', 'overflow', 'transition-duration', 'transition-property']
|
|
355
|
+
.forEach(i => p.el.style.removeProperty(i))
|
|
356
|
+
// (↓)callback
|
|
357
|
+
p.fn ? p.fn() : _
|
|
358
|
+
}, time);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function slideToggle(p) {
|
|
362
|
+
getComputedStyle(p.el).display === 'none' ? slideDown(p) : slideUp(p)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function offset(p) {
|
|
366
|
+
let rect = p.getBoundingClientRect(), _body = document.body
|
|
367
|
+
_return = {
|
|
368
|
+
top: rect.top + _body.scrollTop,
|
|
369
|
+
left: rect.left + _body.scrollLeft
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function pos(p) {
|
|
373
|
+
let rect = p.getBoundingClientRect(), _body = document.body
|
|
374
|
+
_return = {
|
|
375
|
+
top: rect.top + _body.scrollTop,
|
|
376
|
+
left: rect.left + _body.scrollLeft
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function last(p) {
|
|
381
|
+
_return = p.length ? p[p.length - 1] : _
|
|
382
|
+
}
|
|
383
|
+
function first(p) {
|
|
384
|
+
_return = p.length ? p[0] : _
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (!!_return) return _return
|
|
388
|
+
}
|
|
389
|
+
//////// HELPERS
|
|
390
|
+
µ.e = ( e , d=null , b = !0 )=> b? new CustomEvent( e, { detail: d, bubbles: b }):new Event(e)
|
|
391
|
+
µ.l = ( n , e , fn) => n.addEventListener(e,(fn))
|
|
392
|
+
µ.d = ( e, n=null )=> n ? n.dispatchEvent(e) : null
|
|
393
|
+
µ.t = ( e, o=null) => ( e.preventDefault(), e.stopPropagation(), o)? µ(e.target.closest(o)): e.target
|
|
394
|
+
µ.a = ( b , t=null) => t? t=='array'? Array.from(b) : Object[t](b) : Object.entries(b) // t= Object types ( keys, values)
|
|
395
|
+
µ.ar =µ.a
|
|
396
|
+
µ.ax = ( options ) =>{
|
|
397
|
+
return new Promise((resolve, reject) => {
|
|
398
|
+
const xhr = new XMLHttpRequest();
|
|
399
|
+
const method = options.method ? options.method.toUpperCase() : 'GET';
|
|
400
|
+
let url = options.url || '';
|
|
401
|
+
const isGet = method === 'GET';
|
|
402
|
+
const headers = options.headers || {};
|
|
403
|
+
if (isGet && options.data) {
|
|
404
|
+
const queryString = new URLSearchParams(options.data).toString();
|
|
405
|
+
url += (url.includes('?') ? '&' : '?') + queryString;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
xhr.open(method, url, true);
|
|
409
|
+
for (let key in headers) {
|
|
410
|
+
xhr.setRequestHeader(key, headers[key]);
|
|
411
|
+
}
|
|
412
|
+
if (!headers['Content-Type'] && !(options.data instanceof FormData) && method !== 'GET') {
|
|
413
|
+
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (options.timeout) {
|
|
417
|
+
xhr.timeout = options.timeout;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
xhr.onload = () => {
|
|
421
|
+
const isSuccess = xhr.status >= 200 && xhr.status < 300;
|
|
422
|
+
let response = xhr.responseText;
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
response = JSON.parse(response);
|
|
426
|
+
} catch (e) { /* Not JSON */ }
|
|
427
|
+
|
|
428
|
+
if (isSuccess) {
|
|
429
|
+
resolve({ response, status: xhr.status, xhr });
|
|
430
|
+
} else {
|
|
431
|
+
reject({ error: xhr.statusText, status: xhr.status, xhr });
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
xhr.onerror = () => {
|
|
436
|
+
reject({ error: xhr.statusText, status: xhr.status, xhr });
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
let payload = null;
|
|
440
|
+
if (!isGet && options.data) {
|
|
441
|
+
if (options.data instanceof FormData) {
|
|
442
|
+
payload = options.data;
|
|
443
|
+
} else {
|
|
444
|
+
payload = JSON.stringify(options.data);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
xhr.send(payload);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
if (typeof window !== 'undefined') {
|
|
451
|
+
window._ = null
|
|
452
|
+
window.html = String.raw
|
|
453
|
+
window.µ = µ
|
|
454
|
+
window._µ = moveDOM
|
|
455
|
+
}
|
package/dist/mode.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/* MIT License Copyright (c) 2025 Silvio Corigliano https://github.com/microdom/mode.js */
|
|
2
|
+
function µ(a,b){function c(a){a.forEach(a=>a.setAttribute(`µicro`,"\xB5")),K=d(`/[µicro]/`),K.forEach(a=>a.removeAttribute(`µicro`))}function d(a){a=i(a)?G(a):a;const b=(a,b)=>"/"==a.at(0)&&"/"==a.at(-1)?b.querySelectorAll(a.replace(/^\/|\/$/g,"")):b.querySelector(a);if(g(a)||h(a))return a;if(f(a)){let d,e;return i(a[1])?e=document.querySelector(a[1]):g(a[1])&&(e=a[1]),i(a[0])?(d=a[0],b(d,e)):g(a[0])?a:console.error("Array error")}return j(a)?m(a):i(a)?b(a,document):void 0}function f(a){return Array.isArray(a)}function g(a){return a instanceof HTMLElement}function h(a){return NodeList.prototype.isPrototypeOf(a)}function i(a){return"string"==typeof a||a instanceof String}function j(a){return"<"===a[0]&&">"===a[a.length-1]}function k(a){return!!i(a)&&void(h(K)||f(K)?K.forEach(b=>b.innerHTML=a):K.innerHTML=a)}function l(a){return!!i(a)&&void(h(K)||f(K)?K.forEach(b=>b.textContent=a):K.textContent=a)}function m(a){let b=J("div",{},"","");return b.insertAdjacentHTML("beforeend",a.replace(/\s+/g," ")),b.firstChild}function n(a){j(a)?K.insertAdjacentHTML("beforeend",a.replace(/\s+/g," ")):g(a)&&K.appendChild(a)}function o(a){const b=(a,b,c=null)=>{c=!c?K:c,console.log(c,"\xB7\xB7\xB7\xB7"),h(c)||f(c)?c.forEach(c=>c.addEventListener(a,b,!1)):c.addEventListener(a,b,!1)},c=a=>{a.e&&(f(a.e)?a.e.forEach(c=>b(c,a.fn)):b(a.e,a.fn)),a.l&&(f(a.l)?a.l.forEach(c=>b(a.e,c.fn,c.tg)):b(a.e,a.l.fn,a.l.tg))};f(a)?a.forEach(a=>c(a)):c(a)}function e(a){h(K)||f(K)?K.forEach(a):a(K)}function p(a){K=a(K)}function q(a){const b=(a,b)=>"/"==a.at(0)&&"/"==a.at(-1)?b.querySelectorAll(a.replace(/^\/|\/$/g,"")):b.querySelector(a);let c,e=document.createElement("div");h(K)||f(K)?K.forEach(d=>{c=b(a,d),null!=c&&e.append(c)}):K=d([a,K]),0<e.childNodes.length&&(K=e.childNodes)}function r(a){if(h(K))return!1;if(a){let b=K.previousElementSibling;for(;b&&!b.matches(a);)b=b.previousElementSibling;K=b}else K=K.previousElementSibling}function s(a){if(h(K))return!1;if(a){let b=K.nextElementSibling;for(;b&&!b.matches(a);)b=b.nextElementSibling;K=b}else K=K.nextElementSibling}function t(b){if(!g(K))return!1;const c=[];for(a=K;(a=a.parentNode)&&a!==document;)!b||a.matches(b)?c.push(a):D;K=c}function u(a){if(!g(K))return!1;let b=[];for(const c of K.childNodes)g(c)&&(!a||c.matches(a))?b.push(c):D;c(b)}function v(a){return!!g(K)&&void K.parentNode.insertBefore(a,K.nextSibling)}function w(b){return!!g(K)&&void(a=[...K.children].filter(a=>b?a.matches(b):a),c(a))}function x(a){if(!h(K)&&!f(K))return null;let b;i(a)?K.forEach(c=>c.matches(a)?b=c:D):K.forEach(a=>b=a),K=b}function y(a){if(!h(K)&&!f(K))return null;if(i(a))try{K.forEach(b=>{if(b.matches(a))throw K=b,"break"})}catch(a){if("break"!==a)throw a}else try{K.forEach((a,b)=>{if(0===b)throw K=a,"break"})}catch(a){if("break"!==a)throw a}}function z(b){return!!g(K)&&void(a=[...K.parentNode.children].filter(a=>b?a.matches(b):a),c(a))}function A(b){return!!g(K)&&void(a=[...K.parentNode.children].filter(a=>b?a.matches(b)&&a!==K:a!==K),c(a))}function B(b){return!!(h(K)&&b)&&void(a=[...K].filter(a=>a.matches(b)),c(a))}function C(a){const b=(a,b)=>{a.parentElement.insertBefore(b,a),b.appendChild(a)};h(K)||f(K)?K.forEach(c=>b(c,a.cloneNode())):b(K,a.cloneNode())}const D=null,E="[\\x20\\t\\r\\n\\f]",F=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),G=a=>a.replace(/^\s\s*/,"").replace(/\s\s*$/,"").replace(/(\r\n|\n|\r)/gm,"").replace(/>\s+</g,"><"),H=(a,b=null)=>b?"array"==b?Array.from(a):Object[b](a):Object.entries(a),I={html:k,text:l,insert:n,on:o,each:e,proceed:p,find:q,css:function(a){const b=(a,b)=>{h(K)||f(K)?K.forEach(c=>c.style[a]=b):K.style[a]=b};Object.keys(a).map(c=>b(c,a[c]))},classes:function(a){const b=(a,b)=>{const c=(a,b,c)=>{f(c)?c.forEach(c=>a.classList[b](c)):a.classList[b](c)};h(K)||f(K)?K.forEach(d=>c(d,a,b)):c(K,a,b)};Object.keys(a).map(c=>b(c,a[c]))},clss:function(a){const b=(a,b)=>{const c=(a,b,c)=>{f(c)?c.forEach(c=>a.classList[b](c)):a.classList[b](c)};h(K)||f(K)?K.forEach(d=>c(d,a,b)):c(K,a,b)};Object.keys(a).map(c=>b(c,a[c]))},attr:function(a){const b=(a,b,c)=>{"set"===b?a.setAttribute(H(c)[0][0],H(c)[0][1]):"get"===b?a.getAttribute(c):"del"===b?a.removeAttribute(c):"has"===b?a.hasAttribute(c):"tog"===b?a.toggleAttribute(c):"list"===b?a.getAttributeNames():void 0},c=(a,c)=>{const d=(a,c,d)=>{f(d)?d.forEach(d=>b(a,c,d)):b(a,c,d)};h(K)||f(K)?K.forEach(b=>d(b,a,c)):d(K,a,c)};Object.keys(a).map(b=>c(b,a[b]))},prev:r,next:s,parents:t,childs:u,after:v,children:w,last:x,first:y,siblingsAll:z,siblings:A,filter:B,wrap:C},J=(a,b,c)=>{function d(a){return"object"==typeof a?Object.keys(a).map(b=>`${b}:${a[b]}`).join(";"):a}let e=document.createElement(a);for(const f in b)e.setAttribute(f,d(b[f]));if(c){let a=document.createTextNode(c);e.appendChild(a)}for(const d in u)e.appendChild(u[d]);return e};let K=a===D?a:d(a);if(!!b)for(let[a,c]of Object.entries(b))a=a.replace(/_/g,""),K&&"function"==typeof I[a]?I[a](c):null;return f(K)&&0===K.length?D:K}function moveDOM(fns){function isArr(a){return Array.isArray(a)}function isEl(a){return a instanceof HTMLElement}function isList(a){return NodeList.prototype.isPrototypeOf(a)}function isStr(a){return"string"==typeof a||a instanceof String}function wrap(a){const b=(a,b)=>{a.parentElement.insertBefore(b,a),b.appendChild(a)};isList(a.el)?a.el.forEach(c=>b(c,a.wrp.cloneNode())):b(a.el,a.wrp.cloneNode())}function slideUp(a){let b={transitionProperty:"height, margin, padding",transitionDuration:a.t+"ms",boxSizing:"border-box",height:a.el.offsetHeight+"px"};µ(a.el,{css:b}),a.el.offsetHeight,µ(a.el,{css:{overflow:"hidden",height:0,paddingTop:0,paddingBottom:0,marginTop:0,marginBottom:0}}),setTimeout(()=>{["height","padding-top","padding-bottom","margin-top","margin-bottom","overflow","transition-duration","transition-property"].forEach(b=>a.el.style.removeProperty(b)),a.el.style.display="none",a.fn?a.fn():_},a.t)}function slideDown(a){let b=getComputedStyle(a.el).display;"none"===b&&(b="block"),a.el.style.display=b;let c=a.el.offsetHeight;const d=Math.ceil(a.t*(c/200));console.log("time >>",d);µ(a.el,{css:{overflow:"hidden",height:0,paddingTop:0,paddingBottom:0,marginTop:0,marginBottom:0}}),a.el.offsetHeight,µ(a.el,{css:{boxSizing:"border-box",transitionProperty:"height, margin, padding",transitionDuration:d+"ms",height:c+"px"}});["padding-top","padding-bottom","margin-top","margin-bottom"].forEach(b=>a.el.style.removeProperty(b));setTimeout(()=>{["height","overflow","transition-duration","transition-property"].forEach(b=>a.el.style.removeProperty(b)),a.fn?a.fn():_},d)}function slideToggle(a){"none"===getComputedStyle(a.el).display?slideDown(a):slideUp(a)}function offset(a){let b=a.getBoundingClientRect(),c=document.body;_return={top:b.top+c.scrollTop,left:b.left+c.scrollLeft}}function pos(a){let b=a.getBoundingClientRect(),c=document.body;_return={top:b.top+c.scrollTop,left:b.left+c.scrollLeft}}function last(a){_return=a.length?a[a.length-1]:_}function first(a){_return=a.length?a[0]:_}const _=null;let _return;if(fns)for(let[fn,params]of Object.entries(fns))fn=fn.replace(/_/g,""),"function"==typeof eval(fn)?eval(fn)(params):null;return _return?_return:void 0}µ.e=(a,c=null,d=!0)=>d?new CustomEvent(a,{detail:c,bubbles:d}):new Event(a),µ.l=(a,b,c)=>a.addEventListener(b,c),µ.d=(a,b=null)=>b?b.dispatchEvent(a):null,µ.t=(a,b=null)=>(a.preventDefault(),a.stopPropagation(),b)?µ(a.target.closest(b)):a.target,µ.a=(a,b=null)=>b?"array"==b?Array.from(a):Object[b](a):Object.entries(a),µ.ar=µ.a,µ.ax=a=>new Promise((b,c)=>{const d=new XMLHttpRequest,e=a.method?a.method.toUpperCase():"GET";let f=a.url||"";const g="GET"===e,h=a.headers||{};if(g&&a.data){const b=new URLSearchParams(a.data).toString();f+=(f.includes("?")?"&":"?")+b}for(let a in d.open(e,f,!0),h)d.setRequestHeader(a,h[a]);h["Content-Type"]||a.data instanceof FormData||"GET"===e||d.setRequestHeader("Content-Type","application/json"),a.timeout&&(d.timeout=a.timeout),d.onload=()=>{const a=200<=d.status&&300>d.status;let e=d.responseText;try{e=JSON.parse(e)}catch(a){}a?b({response:e,status:d.status,xhr:d}):c({error:d.statusText,status:d.status,xhr:d})},d.onerror=()=>{c({error:d.statusText,status:d.status,xhr:d})};let i=null;!g&&a.data&&(a.data instanceof FormData?i=a.data:i=JSON.stringify(a.data)),d.send(i)}),"undefined"!=typeof window&&(window._=null,window.html=String.raw,window.µ=µ,window._µ=moveDOM);
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@microdom/mode",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Mode JS is a ~7kb semantic layer for modern vanilla JavaScript.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./src/mode.js",
|
|
9
|
+
"default": "./src/mode.js"
|
|
10
|
+
},
|
|
11
|
+
"./dist/mode.js": "./dist/mode.js",
|
|
12
|
+
"./dist/mode.min.js": "./dist/mode.min.js"
|
|
13
|
+
},
|
|
14
|
+
"files": ["src", "dist", "README.md", "LICENSE"],
|
|
15
|
+
"keywords": ["microdom", "dom", "vanilla", "tiny", "jquery-like"],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/microdom/mode.js.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/microdom/mode.js/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/microdom/mode.js#readme"
|
|
25
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { mode } from "./mode.js";
|
package/src/mode.js
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
|
|
2
|
+
function µ(el, fns) {
|
|
3
|
+
const _ = null
|
|
4
|
+
const roneTag = (/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i)
|
|
5
|
+
const rhtml = /<|&#?\w+;/
|
|
6
|
+
const rtagName = (/<([a-z][^\/\0>\x20\t\r\n\f]*)/i)
|
|
7
|
+
const whitespace = "[\\x20\\t\\r\\n\\f]"
|
|
8
|
+
const rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g")
|
|
9
|
+
const tr = (s) => s.replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/(\r\n|\n|\r)/gm, "").replace(/>\s+</g, '><')
|
|
10
|
+
const arr = ( b , n=null) => n? n=='array'? Array.from(b) : Object[n](b) : Object.entries(b)
|
|
11
|
+
const __ = {
|
|
12
|
+
html,
|
|
13
|
+
text,
|
|
14
|
+
insert,
|
|
15
|
+
on,
|
|
16
|
+
each,
|
|
17
|
+
proceed,
|
|
18
|
+
find,
|
|
19
|
+
css,
|
|
20
|
+
classes,
|
|
21
|
+
clss,
|
|
22
|
+
attr,
|
|
23
|
+
prev,
|
|
24
|
+
next,
|
|
25
|
+
parents,
|
|
26
|
+
childs,
|
|
27
|
+
after,
|
|
28
|
+
children,
|
|
29
|
+
last,
|
|
30
|
+
first,
|
|
31
|
+
siblingsAll,
|
|
32
|
+
siblings,
|
|
33
|
+
filter,
|
|
34
|
+
wrap
|
|
35
|
+
}
|
|
36
|
+
function el_(s) {
|
|
37
|
+
s.forEach(e => e.setAttribute(`µicro`, "µ"))
|
|
38
|
+
_el = getEl(`/[µicro]/`)
|
|
39
|
+
_el.forEach(e => e.removeAttribute(`µicro`))
|
|
40
|
+
}
|
|
41
|
+
const nodeDom = (t, att, tx, ch) => {
|
|
42
|
+
let o = document.createElement(t)
|
|
43
|
+
function val(v) {
|
|
44
|
+
return typeof v !== 'object' ? v : Object.keys(v).map((e) => `${e}:${v[e]}`).join(';')
|
|
45
|
+
}
|
|
46
|
+
for (const key in att) o.setAttribute(key, val(att[key]))
|
|
47
|
+
if (tx) {
|
|
48
|
+
let newtext = document.createTextNode(tx)
|
|
49
|
+
o.appendChild(newtext)
|
|
50
|
+
}
|
|
51
|
+
for (const key in childs) o.appendChild(childs[key])
|
|
52
|
+
return o
|
|
53
|
+
}
|
|
54
|
+
let _el = el !== _ ? getEl(el) : el
|
|
55
|
+
if (!!fns) {
|
|
56
|
+
for (let [fn, p] of Object.entries(fns)) {
|
|
57
|
+
fn = fn.replace(/_/g, '')
|
|
58
|
+
_el && typeof __[fn] === 'function' ? __[fn](p) : null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function getEl(e) {
|
|
62
|
+
e = isStr(e) ? tr(e) : e
|
|
63
|
+
const sel = (s, c) => s.at(0) == '/' && s.at(-1) == '/' ? c.querySelectorAll(s.replace(/^\/|\/$/g, '')) : c.querySelector(s)
|
|
64
|
+
if (isEl(e) || isList(e)) {
|
|
65
|
+
return e
|
|
66
|
+
} else if (isArr(e)) {
|
|
67
|
+
let s, c
|
|
68
|
+
if (isStr(e[1])) {
|
|
69
|
+
c = document.querySelector(e[1])
|
|
70
|
+
} else if (isEl(e[1])) {
|
|
71
|
+
c = e[1]
|
|
72
|
+
}
|
|
73
|
+
if (isStr(e[0])) {
|
|
74
|
+
s = e[0]
|
|
75
|
+
return sel(s, c)
|
|
76
|
+
}
|
|
77
|
+
if (isEl(e[0])) {
|
|
78
|
+
return e
|
|
79
|
+
}
|
|
80
|
+
return console.error('Array error')
|
|
81
|
+
} else if (isHtml(e)) {
|
|
82
|
+
return parseHTML(e)
|
|
83
|
+
} else if (isStr(e)) {
|
|
84
|
+
return sel(e, document)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function isArr(e) { return Array.isArray(e) }
|
|
88
|
+
function isEl(e) { return e instanceof HTMLElement /* || e.nodeType */ }
|
|
89
|
+
function isList(e) { return NodeList.prototype.isPrototypeOf(e) }
|
|
90
|
+
function isStr(e) { return typeof e === 'string' || e instanceof String }
|
|
91
|
+
function isColl(e) { return HTMLCollection.prototype.isPrototypeOf(e) }
|
|
92
|
+
function isHtml(e) { return e[0] === "<" && e[e.length - 1] === ">" }
|
|
93
|
+
// Helpers
|
|
94
|
+
function html(p) {
|
|
95
|
+
if (!isStr(p)) return false
|
|
96
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => el.innerHTML = p) : _el.innerHTML = p
|
|
97
|
+
}
|
|
98
|
+
function text(p) {
|
|
99
|
+
if (!isStr(p)) return false
|
|
100
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => el.textContent = p) : _el.textContent = p
|
|
101
|
+
}
|
|
102
|
+
function parseHTML(p) {
|
|
103
|
+
let o = nodeDom('div', {}, '', '')
|
|
104
|
+
o.insertAdjacentHTML("beforeend", p.replace(/\s+/g, ' '))
|
|
105
|
+
return o.firstChild
|
|
106
|
+
}
|
|
107
|
+
function insert(p) {
|
|
108
|
+
if ( isHtml(p)) _el.insertAdjacentHTML("beforeend", p.replace(/\s+/g, ' '))
|
|
109
|
+
else if( isEl(p)) _el.appendChild(p)
|
|
110
|
+
}
|
|
111
|
+
function on(p) {
|
|
112
|
+
const add = (e, fn, el = null) => {
|
|
113
|
+
el = !!el ? el : _el
|
|
114
|
+
console.log(el, "····")
|
|
115
|
+
isList(el) || isArr(el) ? el.forEach(l => l.addEventListener(e, fn, false)) :
|
|
116
|
+
el.addEventListener(e, fn, false)
|
|
117
|
+
}
|
|
118
|
+
const ctm = (c, t, fn) => {
|
|
119
|
+
_el.addEventListener(e, fn, false)
|
|
120
|
+
}
|
|
121
|
+
const on = (o) => {
|
|
122
|
+
if (o.e)
|
|
123
|
+
isArr(o.e) ? o.e.forEach(n => add(n, o.fn)) : add(o.e, o.fn)
|
|
124
|
+
if (o.l) {
|
|
125
|
+
isArr(o.l) ? o.l.forEach(n => add(o.e, n.fn, n.tg)) : add(o.e, o.l.fn, o.l.tg)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
isArr(p) ? p.forEach(e => on(e)) : on(p)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function each(p) {
|
|
132
|
+
isList(_el) || isArr(_el) ? _el.forEach(p) : p(_el)
|
|
133
|
+
}
|
|
134
|
+
function proceed(p) {
|
|
135
|
+
_el = p(_el)
|
|
136
|
+
}
|
|
137
|
+
function find(p) {
|
|
138
|
+
const xel = (s, c) => s.at(0) == '/' && s.at(-1) == '/' ? c.querySelectorAll(s.replace(/^\/|\/$/g, '')) : c.querySelector(s)
|
|
139
|
+
let n, found = document.createElement('div')
|
|
140
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => {
|
|
141
|
+
n = xel(p, el)
|
|
142
|
+
if (n != null) found.append(n)
|
|
143
|
+
}) : _el = getEl([p, _el])
|
|
144
|
+
if (found.childNodes.length > 0) _el = found.childNodes
|
|
145
|
+
}
|
|
146
|
+
function css(p) {
|
|
147
|
+
const add = (s, v) => {
|
|
148
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => el.style[s] = v) : _el.style[s] = v
|
|
149
|
+
}
|
|
150
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
151
|
+
}
|
|
152
|
+
function classes(p) {
|
|
153
|
+
const add = (s, v) => {
|
|
154
|
+
const set = (el, s, v) => { isArr(v) ? v.forEach(i => el.classList[s](i)) : el.classList[s](v) }
|
|
155
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => set(el, s, v)) : set(_el, s, v)
|
|
156
|
+
}
|
|
157
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
158
|
+
}
|
|
159
|
+
function clss(p) {
|
|
160
|
+
const add = (s, v) => {
|
|
161
|
+
const set = (el, s, v) => { isArr(v) ? v.forEach(i => el.classList[s](i)) : el.classList[s](v) }
|
|
162
|
+
isList(_el) || isArr(_el) ? _el.forEach(el => set(el, s, v)) : set(_el, s, v)
|
|
163
|
+
}
|
|
164
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
165
|
+
}
|
|
166
|
+
function attr(p) {
|
|
167
|
+
const bin =(el,s,v) => {
|
|
168
|
+
switch (s) {
|
|
169
|
+
case "set": el.setAttribute(arr(v)[0][0],arr(v)[0][1]);break
|
|
170
|
+
case "get": el.getAttribute(v);break
|
|
171
|
+
case "del": el.removeAttribute(v);break
|
|
172
|
+
case "has": el.hasAttribute(v);break
|
|
173
|
+
case "tog": el.toggleAttribute(v);break
|
|
174
|
+
case "list": el.getAttributeNames()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const add = (s, v) => {
|
|
178
|
+
const set = (el, s, v) => { isArr(v) ? v.forEach(i => bin(el,s,i)) : bin(el,s,v) }
|
|
179
|
+
isList(_el) || isArr(_el) ? _el.forEach( el => set(el, s, v)) : set(_el, s, v)
|
|
180
|
+
}
|
|
181
|
+
Object.keys(p).map((k) => add(k, p[k]))
|
|
182
|
+
}
|
|
183
|
+
function prev(p) {
|
|
184
|
+
if (isList(_el)) return false
|
|
185
|
+
if (p) {
|
|
186
|
+
let prev = _el.previousElementSibling
|
|
187
|
+
while (prev && !prev.matches(p)) prev = prev.previousElementSibling
|
|
188
|
+
_el = prev
|
|
189
|
+
} else {
|
|
190
|
+
_el = _el.previousElementSibling
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function next(p) {
|
|
194
|
+
if (isList(_el)) return false
|
|
195
|
+
if (p) {
|
|
196
|
+
let next = _el.nextElementSibling
|
|
197
|
+
while (next && !next.matches(p)) next = next.nextElementSibling
|
|
198
|
+
_el = next;
|
|
199
|
+
} else {
|
|
200
|
+
_el = _el.nextElementSibling
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function parents(p) {
|
|
205
|
+
if (!isEl(_el)) return false
|
|
206
|
+
const parents = []
|
|
207
|
+
el = _el
|
|
208
|
+
while ((el = el.parentNode) && el !== document) {
|
|
209
|
+
(!p || el.matches(p)) ? parents.push(el) : _
|
|
210
|
+
}
|
|
211
|
+
_el = parents
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function childs(p) {
|
|
215
|
+
if (!isEl(_el)) return false
|
|
216
|
+
let el = []
|
|
217
|
+
for (const e of _el.childNodes) {
|
|
218
|
+
isEl(e) && (!p || e.matches(p)) ? el.push(e) : _
|
|
219
|
+
}
|
|
220
|
+
el_(el)
|
|
221
|
+
}
|
|
222
|
+
function after(p) {
|
|
223
|
+
if (!isEl(_el)) return false
|
|
224
|
+
_el.parentNode.insertBefore(p, _el.nextSibling);
|
|
225
|
+
}
|
|
226
|
+
function children(p) {
|
|
227
|
+
if (!isEl(_el)) return false
|
|
228
|
+
el = [..._el.children].filter((child) => p ? child.matches(p) : child)
|
|
229
|
+
el_(el)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function last(p) {
|
|
233
|
+
if (!isList(_el) && !isArr(_el)) return null
|
|
234
|
+
let child
|
|
235
|
+
isStr(p) ?
|
|
236
|
+
_el.forEach(e => e.matches(p) ? child = e : _)
|
|
237
|
+
: _el.forEach(e => child = e)
|
|
238
|
+
_el = child
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function first(p) {
|
|
242
|
+
if (!isList(_el) && !isArr(_el)) return null
|
|
243
|
+
if (isStr(p)) {
|
|
244
|
+
try {
|
|
245
|
+
_el.forEach(r => { if (r.matches(p)) throw _el = r, "break" })
|
|
246
|
+
} catch (r) { if ("break" !== r) throw r }
|
|
247
|
+
} else {
|
|
248
|
+
try {
|
|
249
|
+
_el.forEach((r, i) => { if (i === 0) throw _el = r, "break" })
|
|
250
|
+
} catch (r) { if ("break" !== r) throw r }
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function siblingsAll(p) {
|
|
254
|
+
if (!isEl(_el)) return false
|
|
255
|
+
el = [..._el.parentNode.children].filter((child) => p ? child.matches(p) : child)
|
|
256
|
+
el_(el)
|
|
257
|
+
}
|
|
258
|
+
function siblings(p) {
|
|
259
|
+
if (!isEl(_el)) return false
|
|
260
|
+
el = [..._el.parentNode.children].filter((child) => p ? child.matches(p) && child !== _el : child !== _el)
|
|
261
|
+
el_(el)
|
|
262
|
+
}
|
|
263
|
+
function filter(p) {
|
|
264
|
+
if (!isList(_el) || !p) return false
|
|
265
|
+
el = [..._el].filter((item) => item.matches(p))
|
|
266
|
+
el_(el)
|
|
267
|
+
}
|
|
268
|
+
function wrap(p) {
|
|
269
|
+
const add = (e, w) => {
|
|
270
|
+
e.parentElement.insertBefore(w, e)
|
|
271
|
+
w.appendChild(e)
|
|
272
|
+
}
|
|
273
|
+
(isList(_el) || isArr(_el)) ? _el.forEach(e => add(e, p.cloneNode())) : add(_el, p.cloneNode())
|
|
274
|
+
}
|
|
275
|
+
return isArr(_el) && _el.length === 0 ? _ : _el
|
|
276
|
+
}
|
|
277
|
+
function moveDOM(fns) {
|
|
278
|
+
const _ = null
|
|
279
|
+
let _return
|
|
280
|
+
if (fns) {
|
|
281
|
+
for (let [fn, params] of Object.entries(fns)) {
|
|
282
|
+
fn = fn.replace(/_/g, '')
|
|
283
|
+
typeof eval(fn) === 'function' ? eval(fn)(params) : null
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function isArr(e) { return Array.isArray(e) }
|
|
287
|
+
function isEl(e) { return e instanceof HTMLElement }
|
|
288
|
+
function isList(e) { return NodeList.prototype.isPrototypeOf(e) }
|
|
289
|
+
function isStr(e) { return typeof e === 'string' || e instanceof String }
|
|
290
|
+
function wrap(p) {
|
|
291
|
+
const add = (e, w) => {
|
|
292
|
+
e.parentElement.insertBefore(w, e)
|
|
293
|
+
w.appendChild(e)
|
|
294
|
+
}
|
|
295
|
+
isList(p.el) ? p.el.forEach(e => add(e, p.wrp.cloneNode())) : add(p.el, p.wrp.cloneNode())
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function slideUp(p) {
|
|
299
|
+
let css = {
|
|
300
|
+
transitionProperty: 'height, margin, padding',
|
|
301
|
+
transitionDuration: p.t + 'ms',
|
|
302
|
+
boxSizing: 'border-box',
|
|
303
|
+
height: p.el.offsetHeight + 'px'
|
|
304
|
+
}
|
|
305
|
+
let css2 = {
|
|
306
|
+
overflow: 'hidden',
|
|
307
|
+
height: 0,
|
|
308
|
+
paddingTop: 0,
|
|
309
|
+
paddingBottom: 0,
|
|
310
|
+
marginTop: 0,
|
|
311
|
+
marginBottom: 0
|
|
312
|
+
}
|
|
313
|
+
µ(p.el, { css: css })
|
|
314
|
+
p.el.offsetHeight
|
|
315
|
+
µ(p.el, { css: css2 })
|
|
316
|
+
setTimeout(() => {
|
|
317
|
+
['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'overflow', 'transition-duration', 'transition-property']
|
|
318
|
+
.forEach(i => p.el.style.removeProperty(i))
|
|
319
|
+
p.el.style.display = 'none'
|
|
320
|
+
p.fn ? p.fn() : _
|
|
321
|
+
}, p.t)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function slideDown(p) {
|
|
325
|
+
let display = getComputedStyle(p.el).display
|
|
326
|
+
if (display === 'none') display = 'block'
|
|
327
|
+
p.el.style.display = display
|
|
328
|
+
let height = p.el.offsetHeight
|
|
329
|
+
const time = Math.ceil(p.t * (height / 200))
|
|
330
|
+
console.log("time >>", time)
|
|
331
|
+
let css = {
|
|
332
|
+
overflow: 'hidden',
|
|
333
|
+
height: 0,
|
|
334
|
+
paddingTop: 0,
|
|
335
|
+
paddingBottom: 0,
|
|
336
|
+
marginTop: 0,
|
|
337
|
+
marginBottom: 0,
|
|
338
|
+
}
|
|
339
|
+
let css2 = {
|
|
340
|
+
boxSizing: 'border-box',
|
|
341
|
+
transitionProperty: "height, margin, padding",
|
|
342
|
+
transitionDuration: time + 'ms',
|
|
343
|
+
height: height + 'px'
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
µ(p.el, {
|
|
347
|
+
css: css
|
|
348
|
+
})
|
|
349
|
+
p.el.offsetHeight
|
|
350
|
+
µ(p.el, { css: css2 })
|
|
351
|
+
let a = ['padding-top', 'padding-bottom', 'margin-top', 'margin-bottom']
|
|
352
|
+
.forEach(i => p.el.style.removeProperty(i))
|
|
353
|
+
setTimeout(() => {
|
|
354
|
+
['height', 'overflow', 'transition-duration', 'transition-property']
|
|
355
|
+
.forEach(i => p.el.style.removeProperty(i))
|
|
356
|
+
// (↓)callback
|
|
357
|
+
p.fn ? p.fn() : _
|
|
358
|
+
}, time);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function slideToggle(p) {
|
|
362
|
+
getComputedStyle(p.el).display === 'none' ? slideDown(p) : slideUp(p)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function offset(p) {
|
|
366
|
+
let rect = p.getBoundingClientRect(), _body = document.body
|
|
367
|
+
_return = {
|
|
368
|
+
top: rect.top + _body.scrollTop,
|
|
369
|
+
left: rect.left + _body.scrollLeft
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function pos(p) {
|
|
373
|
+
let rect = p.getBoundingClientRect(), _body = document.body
|
|
374
|
+
_return = {
|
|
375
|
+
top: rect.top + _body.scrollTop,
|
|
376
|
+
left: rect.left + _body.scrollLeft
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function last(p) {
|
|
381
|
+
_return = p.length ? p[p.length - 1] : _
|
|
382
|
+
}
|
|
383
|
+
function first(p) {
|
|
384
|
+
_return = p.length ? p[0] : _
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (!!_return) return _return
|
|
388
|
+
}
|
|
389
|
+
//////// HELPERS
|
|
390
|
+
µ.e = ( e , d=null , b = !0 )=> b? new CustomEvent( e, { detail: d, bubbles: b }):new Event(e)
|
|
391
|
+
µ.l = ( n , e , fn) => n.addEventListener(e,(fn))
|
|
392
|
+
µ.d = ( e, n=null )=> n ? n.dispatchEvent(e) : null
|
|
393
|
+
µ.t = ( e, o=null) => ( e.preventDefault(), e.stopPropagation(), o)? µ(e.target.closest(o)): e.target
|
|
394
|
+
µ.a = ( b , t=null) => t? t=='array'? Array.from(b) : Object[t](b) : Object.entries(b) // t= Object types ( keys, values)
|
|
395
|
+
µ.ar =µ.a
|
|
396
|
+
µ.ax = ( options ) =>{
|
|
397
|
+
return new Promise((resolve, reject) => {
|
|
398
|
+
const xhr = new XMLHttpRequest();
|
|
399
|
+
const method = options.method ? options.method.toUpperCase() : 'GET';
|
|
400
|
+
let url = options.url || '';
|
|
401
|
+
const isGet = method === 'GET';
|
|
402
|
+
const headers = options.headers || {};
|
|
403
|
+
if (isGet && options.data) {
|
|
404
|
+
const queryString = new URLSearchParams(options.data).toString();
|
|
405
|
+
url += (url.includes('?') ? '&' : '?') + queryString;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
xhr.open(method, url, true);
|
|
409
|
+
for (let key in headers) {
|
|
410
|
+
xhr.setRequestHeader(key, headers[key]);
|
|
411
|
+
}
|
|
412
|
+
if (!headers['Content-Type'] && !(options.data instanceof FormData) && method !== 'GET') {
|
|
413
|
+
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (options.timeout) {
|
|
417
|
+
xhr.timeout = options.timeout;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
xhr.onload = () => {
|
|
421
|
+
const isSuccess = xhr.status >= 200 && xhr.status < 300;
|
|
422
|
+
let response = xhr.responseText;
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
response = JSON.parse(response);
|
|
426
|
+
} catch (e) { /* Not JSON */ }
|
|
427
|
+
|
|
428
|
+
if (isSuccess) {
|
|
429
|
+
resolve({ response, status: xhr.status, xhr });
|
|
430
|
+
} else {
|
|
431
|
+
reject({ error: xhr.statusText, status: xhr.status, xhr });
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
xhr.onerror = () => {
|
|
436
|
+
reject({ error: xhr.statusText, status: xhr.status, xhr });
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
let payload = null;
|
|
440
|
+
if (!isGet && options.data) {
|
|
441
|
+
if (options.data instanceof FormData) {
|
|
442
|
+
payload = options.data;
|
|
443
|
+
} else {
|
|
444
|
+
payload = JSON.stringify(options.data);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
xhr.send(payload);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
if (typeof window !== 'undefined') {
|
|
451
|
+
window._ = null
|
|
452
|
+
window.html = String.raw
|
|
453
|
+
window.µ = µ
|
|
454
|
+
window._µ = moveDOM
|
|
455
|
+
}
|