jizy-dom 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 +2 -0
- package/index.js +60 -0
- package/lib/Core.js +63 -0
- package/lib/Selector.js +18 -0
- package/lib/Utils.js +50 -0
- package/lib/access.js +72 -0
- package/lib/animations.js +53 -0
- package/lib/attributes.js +148 -0
- package/lib/contents.js +23 -0
- package/lib/events.js +40 -0
- package/lib/manipulation.js +52 -0
- package/lib/misc.js +59 -0
- package/lib/swipe.js +52 -0
- package/lib/traversal.js +38 -0
- package/package.json +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Joffrey Demetz
|
|
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
package/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Selector } from './lib/Selector.js';
|
|
2
|
+
import { DOM } from './lib/Core.js';
|
|
3
|
+
import { domUtils } from './lib/Utils.js';
|
|
4
|
+
import { extendDOMAttributes } from './lib/attributes.js';
|
|
5
|
+
import { extendDOMManipulation } from './lib/manipulation.js';
|
|
6
|
+
import { extendDOMAccess } from './lib/access.js';
|
|
7
|
+
import { extendDOMTraversal } from './lib/traversal.js';
|
|
8
|
+
import { extendDOMContents } from './lib/contents.js';
|
|
9
|
+
import { extendDOMEvents } from './lib/events.js';
|
|
10
|
+
import { extendDOMAnimations } from './lib/animations.js';
|
|
11
|
+
import { extendDOMSwipe } from './lib/swipe.js';
|
|
12
|
+
import { extendDOMMisc } from './lib/misc.js';
|
|
13
|
+
|
|
14
|
+
const jDOM = function(selector, context) {
|
|
15
|
+
return new DOM(selector, context);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const jDOMplugin = function(name, fn) {
|
|
19
|
+
DOM.prototype[name] = fn;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const jDOMcreate = function(tag, attrs = {}) {
|
|
23
|
+
const el = document.createElement(tag);
|
|
24
|
+
const wrapped = new DOM([el]);
|
|
25
|
+
|
|
26
|
+
if (attrs.className) {
|
|
27
|
+
wrapped.addClass(attrs.className);
|
|
28
|
+
delete attrs.className;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (attrs.text) {
|
|
32
|
+
wrapped.text(attrs.text);
|
|
33
|
+
delete attrs.text;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (attrs.html) {
|
|
37
|
+
wrapped.html(attrs.html);
|
|
38
|
+
delete attrs.html;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const [key, val] of Object.entries(attrs)) {
|
|
42
|
+
wrapped.attr(key, val);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return wrapped;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
jDOM,
|
|
50
|
+
Selector,
|
|
51
|
+
domUtils,
|
|
52
|
+
DOM,
|
|
53
|
+
jDOM,
|
|
54
|
+
jDOMplugin,
|
|
55
|
+
jDOMcreate,
|
|
56
|
+
extendDOMAttributes, extendDOMManipulation, extendDOMAccess,
|
|
57
|
+
extendDOMTraversal, extendDOMContents, extendDOMEvents,
|
|
58
|
+
extendDOMAnimations, extendDOMSwipe, extendDOMMisc
|
|
59
|
+
};
|
|
60
|
+
|
package/lib/Core.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { domUtils } from './Utils.js';
|
|
2
|
+
import { Selector } from './Selector.js';
|
|
3
|
+
|
|
4
|
+
export class DOM {
|
|
5
|
+
constructor(selector, context = document) {
|
|
6
|
+
this.elems = Selector(selector, context);
|
|
7
|
+
this.elems.forEach(el => this._patchElement(el));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
_patchElement(el) {
|
|
11
|
+
el.data = (key, val) => {
|
|
12
|
+
if (!key) return this._getAllData(el);
|
|
13
|
+
return arguments.length === 2 ? this._setData(el, key, val) : this._getData(el, key);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
el.css = (prop, val, important = false) =>
|
|
17
|
+
arguments.length === 1 ? this._getCss(el, prop) : this._setCss(el, prop, val, important);
|
|
18
|
+
|
|
19
|
+
el.addClass = cls => this._class(el, 'add', cls);
|
|
20
|
+
el.removeClass = cls => this._class(el, 'remove', cls);
|
|
21
|
+
el.hasClass = cls => el.classList.contains(cls);
|
|
22
|
+
el.hasClasses = clsList => clsList.some(cls => el.classList.contains(cls));
|
|
23
|
+
el.hasAllClasses = clsList => clsList.every(cls => el.classList.contains(cls));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_getCss(el, prop) {
|
|
27
|
+
return el.style[domUtils.camelize(prop)] || getComputedStyle(el).getPropertyValue(domUtils.dasherize(prop));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_setCss(el, prop, val, important) {
|
|
31
|
+
if (val === null) el.style.removeProperty(domUtils.dasherize(prop));
|
|
32
|
+
else if (important) el.style.setProperty(domUtils.dasherize(prop), domUtils.maybeAddPx(prop, val), 'important');
|
|
33
|
+
else el.style[domUtils.camelize(prop)] = domUtils.maybeAddPx(prop, val);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
_getData(el, key) {
|
|
37
|
+
const attr = el.getAttribute(`data-${domUtils.dasherize(key)}`);
|
|
38
|
+
return attr !== null ? domUtils.deserializeValue(attr) : undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_setData(el, key, val) {
|
|
42
|
+
if (typeof val === 'object') {
|
|
43
|
+
for (const k in val) this._setData(el, `${key}-${k}`, val[k]);
|
|
44
|
+
} else {
|
|
45
|
+
domUtils.setAttr(el, `data-${domUtils.dasherize(key)}`, val);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_getAllData(el) {
|
|
50
|
+
const data = {};
|
|
51
|
+
for (const key in el.dataset) data[key] = this._getData(el, key);
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_class(el, action, cls) {
|
|
56
|
+
cls.split(' ').forEach(c => c && el.classList[action](c));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
each(callback) {
|
|
60
|
+
this.elems.forEach((el, i) => callback.call(this, el, i));
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
}
|
package/lib/Selector.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function Selector(selector, context = document) {
|
|
2
|
+
if (!selector) return [];
|
|
3
|
+
|
|
4
|
+
if (selector instanceof Element || selector === window || selector.nodeType) {
|
|
5
|
+
return [selector];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (selector instanceof NodeList || Array.isArray(selector)) {
|
|
9
|
+
return Array.from(selector);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (typeof selector === 'string') {
|
|
13
|
+
return Array.from((context || document).querySelectorAll(selector));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
|
package/lib/Utils.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const domUtils = {
|
|
2
|
+
cssNumber: {
|
|
3
|
+
'column-count': 1, 'columns': 1, 'font-weight': 1,
|
|
4
|
+
'line-height': 1, 'opacity': 1, 'z-index': 1, 'zoom': 1
|
|
5
|
+
},
|
|
6
|
+
|
|
7
|
+
propMap: {
|
|
8
|
+
tabindex: 'tabIndex', readonly: 'readOnly', for: 'htmlFor', class: 'className',
|
|
9
|
+
maxlength: 'maxLength', cellspacing: 'cellSpacing', cellpadding: 'cellPadding',
|
|
10
|
+
rowspan: 'rowSpan', colspan: 'colSpan', usemap: 'useMap',
|
|
11
|
+
frameborder: 'frameBorder', contenteditable: 'contentEditable'
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
dasherize: str => str.replace(/([A-Z])/g, '-$1').toLowerCase(),
|
|
15
|
+
camelize: str => str.replace(/-([a-z])/g, (_, c) => c.toUpperCase()),
|
|
16
|
+
matches: (el, selector) =>
|
|
17
|
+
el?.matches?.(selector) || el?.webkitMatchesSelector?.(selector) ||
|
|
18
|
+
el?.mozMatchesSelector?.(selector) || false,
|
|
19
|
+
maybeAddPx: (prop, value) =>
|
|
20
|
+
(typeof value === 'number' && !domUtils.cssNumber[prop]) ? `${value}px` : value,
|
|
21
|
+
setAttr: (el, name, value) => {
|
|
22
|
+
value == null ? el.removeAttribute(name) : el.setAttribute(name, value);
|
|
23
|
+
},
|
|
24
|
+
deserializeValue: value => {
|
|
25
|
+
try {
|
|
26
|
+
if (value === 'true') return true;
|
|
27
|
+
if (value === 'false') return false;
|
|
28
|
+
if (value === 'null') return null;
|
|
29
|
+
if (+value + '' === value) return +value;
|
|
30
|
+
if (/^[\[{]/.test(value)) return JSON.parse(value);
|
|
31
|
+
return value;
|
|
32
|
+
} catch {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
guessDefaultDisplay : el => {
|
|
37
|
+
const tag = el.tagName.toLowerCase();
|
|
38
|
+
switch (tag) {
|
|
39
|
+
case 'table': return 'table';
|
|
40
|
+
case 'thead': return 'table-header-group';
|
|
41
|
+
case 'tfoot': return 'table-footer-group';
|
|
42
|
+
case 'tr': return 'table-row';
|
|
43
|
+
case 'th':
|
|
44
|
+
case 'td': return 'table-cell';
|
|
45
|
+
case 'span': return 'inline';
|
|
46
|
+
case 'li': return 'list-item';
|
|
47
|
+
}
|
|
48
|
+
return 'block';
|
|
49
|
+
}
|
|
50
|
+
};
|
package/lib/access.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export function extendDOMAccess(DOM) {
|
|
2
|
+
|
|
3
|
+
DOM.prototype.toArray = function() {
|
|
4
|
+
return this.elems;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
DOM.prototype.exists = function() {
|
|
8
|
+
return this.elems.length > 0;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
DOM.prototype.size = function() {
|
|
12
|
+
return this.elems.length;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
DOM.prototype.each = function(callback) {
|
|
16
|
+
this.elems.forEach((el, i) => callback.call(this, el, i));
|
|
17
|
+
return this;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
DOM.prototype.map = function(callback) {
|
|
21
|
+
const results = [];
|
|
22
|
+
this.elems.forEach((el, i) => {
|
|
23
|
+
const result = callback.call(this, el, i);
|
|
24
|
+
if (result !== false) results.push(result);
|
|
25
|
+
});
|
|
26
|
+
return results;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
DOM.prototype.filter = function(callback) {
|
|
30
|
+
if (typeof callback !== 'function') {
|
|
31
|
+
const selector = callback;
|
|
32
|
+
callback = el => el.matches(selector);
|
|
33
|
+
}
|
|
34
|
+
const filtered = this.elems.filter((el, i) => callback.call(this, el, i) !== false);
|
|
35
|
+
return new DOM(filtered);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
DOM.prototype.not = function(selector) {
|
|
39
|
+
let exclude = [];
|
|
40
|
+
if (typeof selector === 'function') {
|
|
41
|
+
this.each((el, i) => {
|
|
42
|
+
if (!selector.call(el, i)) exclude.push(el);
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
exclude = new DOM(selector).toArray();
|
|
46
|
+
}
|
|
47
|
+
const result = this.elems.filter(el => !exclude.includes(el));
|
|
48
|
+
return new DOM(result);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
DOM.prototype.get = function(index = 0) {
|
|
52
|
+
const idx = index >= 0 ? index : this.elems.length + index;
|
|
53
|
+
return this.elems[idx] ? new DOM(this.elems[idx]) : this;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
DOM.prototype.getElement = function(tag = 'div') {
|
|
57
|
+
return this.elems[0] || document.createElement(tag);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
DOM.prototype.is = function(selector) {
|
|
61
|
+
const el = this.elems[0];
|
|
62
|
+
if (!el) return false;
|
|
63
|
+
if (selector instanceof HTMLElement) return el === selector;
|
|
64
|
+
if (selector instanceof DOM) return el === selector.getElement();
|
|
65
|
+
if (typeof selector === 'string') {
|
|
66
|
+
if (selector === ':visible') return getComputedStyle(el).display !== 'none';
|
|
67
|
+
if (selector === ':hidden') return getComputedStyle(el).display === 'none';
|
|
68
|
+
return el.matches(selector);
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function slide(el, direction, speed = 300, easing = 'ease', delay = 0, display = 'block') {
|
|
2
|
+
return new Promise(resolve => {
|
|
3
|
+
if (el.dataset.sliding) return resolve(el);
|
|
4
|
+
el.dataset.sliding = true;
|
|
5
|
+
|
|
6
|
+
const isDown = direction === 'down';
|
|
7
|
+
if (isDown && getComputedStyle(el).display !== 'none') {
|
|
8
|
+
delete el.dataset.sliding;
|
|
9
|
+
return resolve(el);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const fullHeight = el.scrollHeight;
|
|
13
|
+
|
|
14
|
+
if (isDown) {
|
|
15
|
+
el.style.display = display;
|
|
16
|
+
el.style.overflow = 'hidden';
|
|
17
|
+
el.style.height = '0px';
|
|
18
|
+
el.offsetHeight;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
requestAnimationFrame(() => {
|
|
22
|
+
el.style.transition = `height ${speed}ms ${easing}`;
|
|
23
|
+
el.style.height = isDown ? `${fullHeight}px` : '0px';
|
|
24
|
+
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
el.style.removeProperty('transition');
|
|
27
|
+
el.style.removeProperty('height');
|
|
28
|
+
el.style.removeProperty('overflow');
|
|
29
|
+
if (!isDown) el.style.display = 'none';
|
|
30
|
+
delete el.dataset.sliding;
|
|
31
|
+
resolve(el);
|
|
32
|
+
}, speed + delay);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function extendDOMAnimations(DOM) {
|
|
38
|
+
DOM.prototype.slideDown = function(speed = 300, easing = 'ease', delay = 0, display = 'block') {
|
|
39
|
+
return this.each(el => slide(el, 'down', speed, easing, delay, display));
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
DOM.prototype.slideUp = function(speed = 300, easing = 'ease', delay = 0) {
|
|
43
|
+
return this.each(el => slide(el, 'up', speed, easing, delay));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
DOM.prototype.slideToggle = function(speed = 300, easing = 'ease', delay = 0, display = 'block') {
|
|
47
|
+
return this.each(el => {
|
|
48
|
+
const isHidden = getComputedStyle(el).display === 'none';
|
|
49
|
+
return slide(el, isHidden ? 'down' : 'up', speed, easing, delay, display);
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { domUtils } from './Utils.js';
|
|
2
|
+
|
|
3
|
+
export function extendDOMAttributes(DOM) {
|
|
4
|
+
const { dasherize, camelize, deserializeValue, setAttr, propMap } = domUtils;
|
|
5
|
+
|
|
6
|
+
const css = (el, key, value, important = false) => {
|
|
7
|
+
if (arguments.length >= 3) {
|
|
8
|
+
if (value === null) {
|
|
9
|
+
el.style.removeProperty(dasherize(key));
|
|
10
|
+
} else {
|
|
11
|
+
value = domUtils.maybeAddPx(dasherize(key), value);
|
|
12
|
+
if (important) {
|
|
13
|
+
el.style.setProperty(dasherize(key), value, 'important');
|
|
14
|
+
} else {
|
|
15
|
+
el.style[camelize(key)] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
return el.style[camelize(key)] || getComputedStyle(el).getPropertyValue(dasherize(key));
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
DOM.prototype.css = function(prop, value, important) {
|
|
24
|
+
if (arguments.length >= 2) {
|
|
25
|
+
return this.each(el => css(el, prop, value, important));
|
|
26
|
+
}
|
|
27
|
+
if (!this.elems.length) return null;
|
|
28
|
+
|
|
29
|
+
if (typeof prop === 'string') {
|
|
30
|
+
return css(this.elems[0], prop);
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(prop)) {
|
|
33
|
+
const result = {};
|
|
34
|
+
prop.forEach(key => {
|
|
35
|
+
result[key] = css(this.elems[0], key);
|
|
36
|
+
});
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
DOM.prototype.data = function(key, value) {
|
|
43
|
+
if (arguments.length >= 1 && key) {
|
|
44
|
+
if (arguments.length === 2) {
|
|
45
|
+
return this.each(el => {
|
|
46
|
+
if (typeof value === 'object' && value !== null) {
|
|
47
|
+
Object.entries(value).forEach(([subKey, subVal]) => {
|
|
48
|
+
el.setAttribute(`data-${dasherize(key + '-' + subKey)}`, subVal);
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
el.setAttribute(`data-${dasherize(key)}`, value);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const val = this.elems[0]?.getAttribute?.(`data-${dasherize(key)}`);
|
|
56
|
+
return val !== null ? deserializeValue(val) : undefined;
|
|
57
|
+
}
|
|
58
|
+
const dataset = {};
|
|
59
|
+
const el = this.elems[0];
|
|
60
|
+
if (el && el.dataset) {
|
|
61
|
+
for (const k in el.dataset) {
|
|
62
|
+
dataset[k] = deserializeValue(el.dataset[k]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return dataset;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
DOM.prototype.attr = function(name, value) {
|
|
69
|
+
if (arguments.length === 2) {
|
|
70
|
+
return this.each(el => {
|
|
71
|
+
if (el.nodeType === 1) setAttr(el, name, value);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const el = this.elems[0];
|
|
75
|
+
if (el?.nodeType === 1) {
|
|
76
|
+
return el.getAttribute(name);
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
DOM.prototype.prop = function(name, value) {
|
|
82
|
+
const propName = propMap[name] || name;
|
|
83
|
+
if (arguments.length === 2) {
|
|
84
|
+
return this.each(el => {
|
|
85
|
+
el[propName] = value;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const el = this.elems[0];
|
|
89
|
+
return el ? el[propName] : undefined;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
DOM.prototype.tagName = function() {
|
|
93
|
+
return this.elems.length > 0 ? this.elems[0].tagName : null;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
DOM.prototype.val = function(value) {
|
|
97
|
+
if (arguments.length > 0) {
|
|
98
|
+
return this.each(el => el.value = value ?? '');
|
|
99
|
+
}
|
|
100
|
+
return this.elems.length > 0 ? this.elems[0].value : null;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
DOM.prototype.outerHeight = function() {
|
|
104
|
+
const el = this.elems[0];
|
|
105
|
+
if (!el) return 0;
|
|
106
|
+
const style = getComputedStyle(el);
|
|
107
|
+
return el.offsetHeight +
|
|
108
|
+
parseInt(style.marginTop) +
|
|
109
|
+
parseInt(style.marginBottom);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
DOM.prototype.outerWidth = function() {
|
|
113
|
+
const el = this.elems[0];
|
|
114
|
+
if (!el) return 0;
|
|
115
|
+
const style = getComputedStyle(el);
|
|
116
|
+
return el.offsetWidth +
|
|
117
|
+
parseInt(style.marginLeft) +
|
|
118
|
+
parseInt(style.marginRight);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
DOM.prototype.addClass = function(className) {
|
|
122
|
+
return this.each(el => el.classList.add(className));
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
DOM.prototype.removeClass = function(className) {
|
|
126
|
+
return this.each(el => el.classList.remove(className));
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
DOM.prototype.toggleClass = function(className) {
|
|
130
|
+
return this.each(el => el.classList.toggle(className));
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
DOM.prototype.replaceClass = function(oldClass, newClass) {
|
|
134
|
+
return this.each(el => el.classList.replace(oldClass, newClass));
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
DOM.prototype.hasClass = function(className) {
|
|
138
|
+
return this.elems.length > 0 ? this.elems[0].classList.contains(className) : false;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
DOM.prototype.hasClasses = function(classNames) {
|
|
142
|
+
return this.elems.length > 0 ? classNames.every(className => this.elems[0].classList.contains(className)) : false;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
DOM.prototype.containsClass = function(search) {
|
|
146
|
+
return this.elems.length > 0 ? Array.from(this.elems[0].classList).some(className => className.includes(search)) : false;
|
|
147
|
+
};
|
|
148
|
+
}
|
package/lib/contents.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function extendDOMContents(DOM) {
|
|
2
|
+
|
|
3
|
+
DOM.prototype.text = function(value) {
|
|
4
|
+
if (arguments.length > 0) {
|
|
5
|
+
return this.each(el => el.innerText = value);
|
|
6
|
+
}
|
|
7
|
+
return this.elems.length > 0 ? this.elems[0].innerText : null;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
DOM.prototype.html = function(value) {
|
|
11
|
+
if (arguments.length > 0) {
|
|
12
|
+
return this.each(el => el.innerHTML = value);
|
|
13
|
+
}
|
|
14
|
+
return this.elems.length > 0 ? this.elems[0].innerHTML : null;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
DOM.prototype.content = function(value) {
|
|
18
|
+
if (arguments.length > 0) {
|
|
19
|
+
return this.each(el => el.textContent = value);
|
|
20
|
+
}
|
|
21
|
+
return this.elems.length > 0 ? this.elems[0].textContent : null;
|
|
22
|
+
};
|
|
23
|
+
}
|
package/lib/events.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { domUtils } from './Utils.js';
|
|
2
|
+
|
|
3
|
+
export function extendDOMEvents(DOM) {
|
|
4
|
+
DOM.prototype.on = function(events, callback, options = false) {
|
|
5
|
+
const list = events.split(/\s+/);
|
|
6
|
+
return this.each(el => list.forEach(e => el.addEventListener(e, callback, options)));
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
DOM.prototype.off = function(events, callback) {
|
|
10
|
+
const list = events.split(/\s+/);
|
|
11
|
+
return this.each(el => list.forEach(e => el.removeEventListener(e, callback)));
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
DOM.prototype.delegate = function(events, selector, callback, options = false) {
|
|
15
|
+
return this.on(events, function(event) {
|
|
16
|
+
if (event.target && domUtils.matches(event.target, selector)) {
|
|
17
|
+
callback.call(event.target, event);
|
|
18
|
+
}
|
|
19
|
+
}, options);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
DOM.prototype.trigger = function(type, detail = null, bubbles = true, cancelable = true) {
|
|
23
|
+
const evt = detail
|
|
24
|
+
? new CustomEvent(type, { detail, bubbles, cancelable })
|
|
25
|
+
: new Event(type, { bubbles, cancelable });
|
|
26
|
+
return this.each(el => el.dispatchEvent(evt));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
DOM.prototype.submit = function() {
|
|
30
|
+
const el = this.elems[0];
|
|
31
|
+
if (el?.tagName === 'FORM') el.submit();
|
|
32
|
+
return this;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
DOM.prototype.focus = function() {
|
|
36
|
+
this.elems[0]?.focus?.();
|
|
37
|
+
return this;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function extendDOMManipulation(DOM, Selector) {
|
|
2
|
+
DOM.prototype.insert = function(newEl, position) {
|
|
3
|
+
const map = {
|
|
4
|
+
before: 'beforebegin',
|
|
5
|
+
after: 'afterend',
|
|
6
|
+
prepend: 'afterbegin',
|
|
7
|
+
append: 'beforeend'
|
|
8
|
+
};
|
|
9
|
+
position = map[position] || position;
|
|
10
|
+
|
|
11
|
+
return this.each(el => {
|
|
12
|
+
if (newEl instanceof DOM) {
|
|
13
|
+
newEl.each(child => el.insertAdjacentElement(position, child));
|
|
14
|
+
} else if (newEl instanceof Element) {
|
|
15
|
+
el.insertAdjacentElement(position, newEl);
|
|
16
|
+
} else {
|
|
17
|
+
el.insertAdjacentHTML(position, newEl);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
DOM.prototype.before = function(newEl) { return this.insert(newEl, 'before'); };
|
|
23
|
+
DOM.prototype.after = function(newEl) { return this.insert(newEl, 'after'); };
|
|
24
|
+
DOM.prototype.append = function(newEl) { return this.insert(newEl, 'append'); };
|
|
25
|
+
DOM.prototype.prepend = function(newEl) { return this.insert(newEl, 'prepend'); };
|
|
26
|
+
|
|
27
|
+
DOM.prototype.replaceWith = function(newEl) {
|
|
28
|
+
this.insert(newEl, 'before');
|
|
29
|
+
this.remove();
|
|
30
|
+
return this;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
DOM.prototype.remove = function() {
|
|
34
|
+
return this.each(el => el.parentNode?.removeChild(el));
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
DOM.prototype.wrap = function(wrapper) {
|
|
38
|
+
return this.each(el => {
|
|
39
|
+
el.parentNode.insertBefore(wrapper, el);
|
|
40
|
+
wrapper.appendChild(el);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
DOM.prototype.find = function(selector) {
|
|
45
|
+
let elems = [];
|
|
46
|
+
this.each(el => {
|
|
47
|
+
let found = Selector(selector, el);
|
|
48
|
+
if (found && found.length) elems.push(...found);
|
|
49
|
+
});
|
|
50
|
+
return new DOM(elems);
|
|
51
|
+
};
|
|
52
|
+
}
|
package/lib/misc.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { domUtils } from './Utils.js';
|
|
2
|
+
|
|
3
|
+
export function extendDOMMisc(DOM) {
|
|
4
|
+
DOM.prototype.toggle = function() {
|
|
5
|
+
return this.each(el => {
|
|
6
|
+
const display = domUtils.guessDefaultDisplay(el);
|
|
7
|
+
if (!el.dataset.cssInitialDisplay) {
|
|
8
|
+
el.dataset.cssInitialDisplay = display;
|
|
9
|
+
}
|
|
10
|
+
el.style.display = (el.style.display === 'none' || getComputedStyle(el).display === 'none')
|
|
11
|
+
? el.dataset.cssInitialDisplay
|
|
12
|
+
: 'none';
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
DOM.prototype.show = function() {
|
|
17
|
+
return this.each(el => {
|
|
18
|
+
const display = domUtils.guessDefaultDisplay(el);
|
|
19
|
+
if (!el.dataset.cssInitialDisplay) {
|
|
20
|
+
el.dataset.cssInitialDisplay = display;
|
|
21
|
+
}
|
|
22
|
+
el.style.display = el.dataset.cssInitialDisplay;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
DOM.prototype.hide = function() {
|
|
27
|
+
return this.each(el => {
|
|
28
|
+
if (!el.dataset.cssInitialDisplay) {
|
|
29
|
+
el.dataset.cssInitialDisplay = domUtils.guessDefaultDisplay(el);
|
|
30
|
+
}
|
|
31
|
+
el.style.display = 'none';
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
DOM.prototype.offset = function() {
|
|
36
|
+
if (!this.elems.length) return { top: 0, left: 0 };
|
|
37
|
+
const rect = this.elems[0].getBoundingClientRect();
|
|
38
|
+
return {
|
|
39
|
+
top: rect.top + window.pageYOffset,
|
|
40
|
+
left: rect.left + window.pageXOffset
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
DOM.prototype.scrollTop = function(position) {
|
|
45
|
+
if (arguments.length > 0) {
|
|
46
|
+
return this.each(el => {
|
|
47
|
+
el.style.scrollBehavior = 'smooth';
|
|
48
|
+
el.scrollTop = position || 0;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return this.elems[0]?.scrollTop || 0;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
DOM.prototype.serialize = function() {
|
|
55
|
+
if (!this.elems.length || !(this.elems[0] instanceof HTMLFormElement)) return '';
|
|
56
|
+
const formData = new FormData(this.elems[0]);
|
|
57
|
+
return new URLSearchParams(formData).toString();
|
|
58
|
+
};
|
|
59
|
+
}
|
package/lib/swipe.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function extendDOMSwipe(DOM) {
|
|
2
|
+
DOM.prototype.swipe = function(callback, ignore = () => false, opts = {}) {
|
|
3
|
+
const config = {
|
|
4
|
+
threshold: 20,
|
|
5
|
+
restraint: 100,
|
|
6
|
+
allowedTime: 300,
|
|
7
|
+
scrolling: false,
|
|
8
|
+
...opts
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return this.each(el => {
|
|
12
|
+
let startX, startY, startTime;
|
|
13
|
+
|
|
14
|
+
const handleStart = e => {
|
|
15
|
+
if (ignore(e)) return;
|
|
16
|
+
const touch = e.changedTouches[0];
|
|
17
|
+
startX = touch.pageX;
|
|
18
|
+
startY = touch.pageY;
|
|
19
|
+
startTime = Date.now();
|
|
20
|
+
if (!config.scrolling) e.preventDefault();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const handleMove = e => {
|
|
24
|
+
if (!config.scrolling) e.preventDefault();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const handleEnd = e => {
|
|
28
|
+
if (ignore(e)) return;
|
|
29
|
+
const touch = e.changedTouches[0];
|
|
30
|
+
const distX = touch.pageX - startX;
|
|
31
|
+
const distY = touch.pageY - startY;
|
|
32
|
+
const elapsed = Date.now() - startTime;
|
|
33
|
+
|
|
34
|
+
let swipedir = 'none';
|
|
35
|
+
|
|
36
|
+
if (elapsed <= config.allowedTime) {
|
|
37
|
+
if (Math.abs(distX) >= config.threshold && Math.abs(distY) <= config.restraint) {
|
|
38
|
+
swipedir = distX < 0 ? 'left' : 'right';
|
|
39
|
+
} else if (Math.abs(distY) >= config.threshold && Math.abs(distX) <= config.restraint) {
|
|
40
|
+
swipedir = distY < 0 ? 'up' : 'down';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (swipedir !== 'none') callback(e, swipedir);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
el.addEventListener('touchstart', handleStart, { passive: true });
|
|
48
|
+
el.addEventListener('touchmove', handleMove, { passive: true });
|
|
49
|
+
el.addEventListener('touchend', handleEnd, { passive: true });
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
}
|
package/lib/traversal.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function extendDOMTraversal(DOM) {
|
|
2
|
+
DOM.prototype.parent = function(selector) {
|
|
3
|
+
const parents = this.elems.map(el => el.parentNode).filter(Boolean);
|
|
4
|
+
return selector ? new DOM(parents).filter(selector) : new DOM(parents);
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
DOM.prototype.children = function(selector) {
|
|
8
|
+
const all = [];
|
|
9
|
+
this.each(el => all.push(...el.children));
|
|
10
|
+
return selector ? new DOM(all).filter(selector) : new DOM(all);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
DOM.prototype.closest = function(selector) {
|
|
14
|
+
const found = this.elems.map(el => el.closest(selector)).filter(Boolean);
|
|
15
|
+
return new DOM(found);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
DOM.prototype.prev = function(selector) {
|
|
19
|
+
const prev = this.elems.map(el => el.previousElementSibling).filter(Boolean);
|
|
20
|
+
return selector ? new DOM(prev).filter(selector) : new DOM(prev);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
DOM.prototype.next = function(selector) {
|
|
24
|
+
const next = this.elems.map(el => el.nextElementSibling).filter(Boolean);
|
|
25
|
+
return selector ? new DOM(next).filter(selector) : new DOM(next);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
DOM.prototype.first = function(selector) {
|
|
29
|
+
const first = this.elems.map(el => el.firstElementChild).filter(Boolean);
|
|
30
|
+
return selector ? new DOM(first).filter(selector) : new DOM(first);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
DOM.prototype.last = function(selector) {
|
|
34
|
+
const last = this.elems.map(el => el.lastElementChild).filter(Boolean);
|
|
35
|
+
return selector ? new DOM(last).filter(selector) : new DOM(last);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jizy-dom",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "My own DOM utility",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/joffreydemetz/jizy-dom.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"DOM",
|
|
15
|
+
"Jizy"
|
|
16
|
+
],
|
|
17
|
+
"author": "Joffrey Demetz",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/joffreydemetz/jizy-dom/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/joffreydemetz/jizy-dom#readme"
|
|
23
|
+
}
|