Skip to content

Commit

Permalink
DOM updates
Browse files Browse the repository at this point in the history
Animations, loops and delays
- interval and timeout
- loop
- let()
- DOM.transition
  • Loading branch information
lenincompres committed Oct 26, 2024
1 parent 18e0570 commit adfc386
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 64 deletions.
70 changes: 58 additions & 12 deletions DOM.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/**
* Creates DOM structures from a JS object (structure)
* @author Lenin Compres <lenincompres@gmail.com>
* @version 1.2.1
* @version 1.2.2
* @repository https://github.com/lenincompres/DOM.js
*/

Element.prototype.get = function (station) {
Element.prototype.get = function (station) {
let output;
if (!station && this.tagName.toLocaleLowerCase() === "input") output = this.value;
else if (!station || ["content", "inner", "innerhtml", "html"].includes(station)) output = this.innerHTML;
Expand All @@ -22,6 +22,10 @@
if (output.length) return output;
}

Element.prototype.let = function (station, be = () => undefined, ...args) {
return this.set(typeof be === "function" ? be(this.get(station)) : be, station, ...args);
}

Element.prototype.set = function (model, ...args) {
if ([null, undefined].includes(model)) return this;
let contentType = DOM.typify(model.content);
Expand Down Expand Up @@ -83,17 +87,31 @@ Element.prototype.set = function (model, ...args) {
else this[STATION] = e => model(e, this);
return this;
}
if (argsType.boolean === true && this.intervals && this.intervals[STATION]) {
DOM.transition(this, `${DOM.unCamelize(STATION)} 0s`);
clearInterval(this.intervals[STATION]);
}
if (model.duration) {
model.duration = parseInt(model.duration);
if (model.transition) DOM.transition(this, `${DOM.unCamelize(STATION)} ${model.duration}ms ${model.transition}`);
if (model.loop) {
this.set(model.loop[0], STATION);
let i = 1;
DOM.interval(this, () => {
this.set(model.loop[i], STATION);
i += 1;
if (i >= model.loop.length) i = 0;
}, model.duration, model.end, STATION);
return this;
}
if (model.to !== undefined && model.from !== undefined) model.through = [model.from, model.to];
this.set(model.through[0], STATION);
model.through.forEach((val, i) => setTimeout(() => this.set(val, STATION), i * model.duration));
if (model.transition) this.set(`${this.get('transition')}, ${DOM.unCamelize(STATION)} ${model.duration}ms ${model.transition}`, 'transition');
return this;
}
if (model._bonds) model = model.bind();
else {
if (model.with && typeof model.with !== 'function') model.bind = model.with;
if (model.with && typeof model.with !== "function") model.bind = model.with;
if (model.bind) {
if (Array.isArray(model.bind)) model = DOM.bind(model.bind, model.as);
else model = model.as ? model.bind.bind(model.as) : model.bind;
Expand Down Expand Up @@ -286,6 +304,16 @@ Element.prototype.set = function (model, ...args) {
if (!model[f]) return this;
model[f](elem);
});
["timeout"].forEach(f => {
if (!model[f]) return this;
let [func, t] = Array.isArray(model[f]) ? model[f] : [model[f], 1];
setTimeout(() => func(elem), t);
});
["interval"].forEach(f => {
if (!model[f]) return this;
let [func, t, end] = Array.isArray(model[f]) ? model[f] : [model[f], 1];
DOM.interval(this, func, t, end);
});
if (argsType.functions) argsType.functions.forEach(f => f(elem));
return elem;
};
Expand Down Expand Up @@ -518,14 +546,13 @@ Object.prototype.binderSet = function (name, value) {
// global static methods to handle the DOM
class DOM {
// returns value based on
static get(station, ...args) {
// checks if meant to get from an element
let argsType = DOM.typify(...args);
let elt = argsType.element ? argsType.element : argsType.p5Element;
if (elt) return elt.get(model);
// checks if the station belongs to the head
static get(station) {
DOM.headTags.includes(station.toLowerCase()) ? document.head.get(station) : document.body.get(station);
}
static
let (station, be) {
DOM.headTags.includes(station.toLowerCase()) ? document.head.let(station, be) : document.body.let(station, be);
}
// create elements based on an object model
static set(model = "", ...args) {
if (!args.includes("css") && !window.DOM_RESETTED) {
Expand Down Expand Up @@ -583,7 +610,7 @@ class DOM {
tag = model.tag;
delete model.tag;
}
return document.createElement(tag).set(model);
return document.createElement(tag).set(model);
}
// returns a new binder
static binder(value, ...args) {
Expand Down Expand Up @@ -678,6 +705,25 @@ class DOM {
}
return qs.split("/");
}
static interval(elem, func, t, end, station) {
if (!elem.intervals) elem.intervals = {};
else if (station && elem.intervals[station]) clearInterval(elem.intervals[station]);
let iId = setInterval(() => {
let go = typeof end === "function" ? end() : end || end === undefined;
if (!go) return clearInterval(iId);
func(elem);
isNaN(end) ? null : end -= 1;
}, t);
if (station) elem.intervals[station] = iId;
}
static transition(elem, trn) { // for animations (loop, duration)
let prop = trn.split(' ')[0].trim();
let trns = elem.get("transition");
if(trns) trns = trns.split(",").map(t => t.trim()).filter(t => t !== "NaN")
.map(t => t.startsWith(prop) ? trn : t);
else trns = [trn];
elem.set(trns.join(", "), "transition");
}
static addID = (id, elt) => {
if (!isNaN(id)) return console.error("ID's should not be numeric. id: " + id);
if (elt.tagName) elt.setAttribute("id", id);
Expand Down Expand Up @@ -743,7 +789,7 @@ class DOM {
static metaNames = ["viewport", "keywords", "description", "author", "refresh", "application-name", "generator"];
static htmlEquivs = ["contentSecurityPolicy", "contentType", "defaultStyle", "content-security-policy", "content-type", "default-style", "refresh"];
static headTags = ["meta", "link", "title", "font", "icon", "image", ...DOM.metaNames, ...DOM.htmlEquivs];
static reserveStations = ["tag", "id", "onready", "ready", "done", "ondone"];
static reserveStations = ["tag", "id", "bind", "with", "as", "binders", "_bonds"];
static listeners = ["addevent", "addeventlistener", "eventlistener", "listener", "on"];
static getDocType = str => typeof str === "string" ? ({
css: "stylesheet",
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
gtag('js', new Date());
gtag('config', 'G-9S3H2NXER5');
</script>
<script src="index.js" type="module" defer></script>
</head>

<body>
<script src="index.js" type="module"></script>
</body>

</html>
101 changes: 50 additions & 51 deletions src/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import CardScroll from "./CardScroll.js";
import news from "./news.js";

const projects = allProjects.filter(p => !p.hidden);
const activeProject = new Binder();
const allTags = new Binder([]);
const NONE = "∅";
const activeTag = new Binder(NONE);
const showTag = (tag = NONE) => activeTag.value = activeTag.value === tag ? NONE : tag;
const _activeProject = new Binder();
const _allTags = new Binder([]);
const _activeTag = new Binder(NONE);
const showTag = (tag = NONE) => _activeTag.value = tag;
const addTag = (tag) => !_allTags.value.includes(tag) ? (_allTags.value = [..._allTags.value, tag].sort(sortWords)) : null;
const sortWords = (a, b) => a < b ? -1 : 1;

Copy.add({
Expand Down Expand Up @@ -67,39 +68,39 @@ export const PAGES = {
justifyContent: "center",
display: "flex",
flexWrap: "wrap",
content: allTags.bind(val => {
showTag();
return {
a: [NONE, ...val].map(tag => ({
backgroundColor: activeTag.bind({
[tag]: STYLE.COLOR.LINK_DARK,
default: STYLE.COLOR.PALE
}),
color: activeTag.bind(val => val === tag ? STYLE.COLOR.PAGE : STYLE.COLOR.LINK),
boxShadow: STYLE.SHADOW.NORMAL,
borderRadius: "0.25em",
padding: "0.2em 0.68em",
margin: "0.3em 0.3em 0 0",
display: "inline-block",
text: tag,
onclick: e => showTag(tag)
}))
}
}),
content: _allTags.as(val => ({
a: [NONE, ...val].map(tag => ({
backgroundColor: _activeTag.as({
[tag]: STYLE.COLOR.LINK_DARK,
default: STYLE.COLOR.PALE
}),
color: _activeTag.as(val => val === tag ? STYLE.COLOR.PAGE : STYLE.COLOR.LINK),
boxShadow: STYLE.SHADOW.NORMAL,
borderRadius: "0.25em",
padding: "0.2em 0.68em",
margin: "0.3em 0.3em 0 0",
display: "inline-block",
text: tag,
onclick: e => showTag(tag),
}))
})),
span: {
color: STYLE.COLOR.PALE,
textShadow: STYLE.SHADOW.TEXT,
text: activeTag.bind(val => val !== NONE ? projects.filter(p => p.tags.includes(val)).length : projects.length),
text: _activeTag.as(val => val !== NONE ? projects.filter(p => p.tags.includes(val)).length : projects.length),
},
onready: queueDown,
onready: elt => queueDown(elt, {
left: ['-30px', '10px', 0],
opacity: [0, 1],
}),
},
section: projects.map((project, i) => ({
model: STYLE.PAGE,
fontSize: "1em",
width: "23em",
cursor: "pointer",
boxShadow: DOM.bind(activeProject, val => val === i ? STYLE.SHADOW.HIGHLIGHT : STYLE.SHADOW.NORMAL),
display: activeTag.bind(val => val === NONE || project.tags.includes(val) ? "block" : "none"),
boxShadow: _activeProject.as(val => val === i ? STYLE.SHADOW.HIGHLIGHT : STYLE.SHADOW.NORMAL),
display: _activeTag.as(val => val === NONE || project.tags.includes(val) ? "block" : "none"),
main: {
minHeight: "6.5em",
div: {
Expand All @@ -120,30 +121,28 @@ export const PAGES = {
},
ul: {
marginTop: "0.2em",
li: project.tags.sort(sortWords).map(tag => {
if (!allTags.value.includes(tag)) allTags.value = [...allTags.value, tag].sort(sortWords);
return {
borderRadius: "0.25em",
padding: "0.2em 0.4em",
marginRight: "0.2em",
backgroundColor: STYLE.COLOR.PALE,
color: STYLE.COLOR.LINK,
border: "solid 1px",
borderColor: activeTag.bind({
[tag]: STYLE.COLOR.LINK,
default: STYLE.COLOR.PALE,
}),
display: "inline-block",
text: tag,
click: e => {
activeTag.value = activeTag.value === tag ? NONE : tag;
e.stopPropagation();
}
}
})
li: project.tags.sort(sortWords).map(tag => ({
borderRadius: "0.25em",
padding: "0.2em 0.4em",
marginRight: "0.2em",
backgroundColor: STYLE.COLOR.PALE,
color: STYLE.COLOR.LINK,
border: "solid 1px",
borderColor: _activeTag.as({
[tag]: STYLE.COLOR.LINK,
default: STYLE.COLOR.PALE,
}),
display: "inline-block",
text: tag,
click: e => {
_activeTag.value = _activeTag.value === tag ? NONE : tag;
e.stopPropagation();
},
ready: elt => addTag(tag),
}))
},
mouseover: e => activeProject.value = i,
mouseout: e => activeProject.value = false,
mouseover: e => _activeProject.value = i,
mouseout: e => _activeProject.value = false,
click: e => {
let link = project.link ? project.link : project.folder
window.open(link, "_blank")
Expand All @@ -152,7 +151,7 @@ export const PAGES = {
})),
onready: () => {
showTag();
activeTag.value = false;
_activeTag.value = false;
}
},
[Copy.KEY.contact]: {
Expand Down

0 comments on commit adfc386

Please sign in to comment.