add basic functionality to the website
This commit is contained in:
parent
efb6d56ab8
commit
fe9a62edd2
5 changed files with 200 additions and 9 deletions
18
index.html
18
index.html
|
@ -7,22 +7,23 @@
|
|||
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500&display=swap" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="/res/style.css">
|
||||
|
||||
<script src="https://git.hippoz.xyz/personalprojects/bloom/raw/branch/master/js/lib.js"></script>
|
||||
<script src="/res/lib/A.js"></script>
|
||||
<script src="/res/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card navigation-card">
|
||||
<div class="navigation-buttons">
|
||||
<button class="button-default">home</button>
|
||||
<button class="button-default">file server</button>
|
||||
<button class="button-default">git server</button>
|
||||
<button class="button-default">about me</button>
|
||||
<button class="button-default">contact me</button>
|
||||
<button id='button-home' class="button-default">home</button>
|
||||
<button id='button-file-server' class="button-default">file server</button>
|
||||
<button id='button-git-server' class="button-default">git server</button>
|
||||
<button id='button-about-me' class="button-default">about me</button>
|
||||
<button id='button-contact-me' class="button-default">contact me</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card" id="content-container">
|
||||
<p>idididi</p>
|
||||
<p>idididi</p>
|
||||
<p>idididi</p>
|
||||
|
@ -31,7 +32,6 @@
|
|||
<p>idididi</p>
|
||||
<p>idididi</p>
|
||||
<p>idididi</p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
1
pages/home.html
Normal file
1
pages/home.html
Normal file
|
@ -0,0 +1 @@
|
|||
Hello!
|
24
res/index.js
Normal file
24
res/index.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
const onButtonClick = (buttonId) => {
|
||||
switch (buttonId) {
|
||||
case 'button-home': {
|
||||
A('#content-container').load('/pages/home.html');
|
||||
break;
|
||||
}
|
||||
case 'button-file-server': {
|
||||
A('#content-container').load('https://files.hippoz.xyz/');
|
||||
break;
|
||||
}
|
||||
case 'button-git-server': {
|
||||
window.location.href = 'https://git.hippoz.xyz/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
A(() => {
|
||||
A('.navigation-buttons .button-default').each((el) => {
|
||||
A(el).on('click', () => {
|
||||
onButtonClick(el.id);
|
||||
});
|
||||
})
|
||||
});
|
166
res/lib/A.js
Normal file
166
res/lib/A.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
const A = (...args) => {
|
||||
const classname = args[0].constructor.name;
|
||||
|
||||
if (classname === 'String') {
|
||||
const c = document.querySelectorAll(args[0]);
|
||||
return new A._Collection(c);
|
||||
}
|
||||
if (classname === 'NodeList') {
|
||||
return new A._Collection(args[0]);
|
||||
}
|
||||
// TODO: lol this is such a hack
|
||||
if (classname.startsWith('HTML')) {
|
||||
return new A._Collection([args[0]]);
|
||||
}
|
||||
if (classname === 'Function') {
|
||||
return A.on('DOMContentLoaded', args[0]);
|
||||
}
|
||||
|
||||
throw new Error(`Function "A" does not accept first argument of type ${typeof args[0]}`);
|
||||
};
|
||||
|
||||
A.on = (event, handler) => {
|
||||
document.addEventListener(event, handler);
|
||||
};
|
||||
|
||||
// --- Collection class ---
|
||||
|
||||
A._Collection = class {
|
||||
constructor(list) {
|
||||
this._list = list;
|
||||
this.reactors = [];
|
||||
}
|
||||
};
|
||||
|
||||
A._Collection.prototype._forCollection = function (f) {
|
||||
for (let i = 0; i < this._list.length; i++) {
|
||||
f(this._list[i], i);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
A._Collection.prototype.html = function (html) {
|
||||
return this._forCollection((el, _) => {
|
||||
el.innerHTML = html;
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.load = async function (url) {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
console.error(`load(${url}) failed with code ${res.status}`);
|
||||
return;
|
||||
}
|
||||
const html = await res.text();
|
||||
|
||||
return this._forCollection((el, _) => {
|
||||
el.innerHTML = html;
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.on = function (event, handler) {
|
||||
return this._forCollection((el, _) => {
|
||||
el.addEventListener(event, handler);
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.each = function (handler) {
|
||||
return this._forCollection((el, i) => {
|
||||
handler(el, i);
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.hide = function () {
|
||||
return this._forCollection((el, _) => {
|
||||
el.style.display = 'none';
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.show = function () {
|
||||
return this._forCollection((el, _) => {
|
||||
el.style.display = 'inline';
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.remove = function () {
|
||||
return this._forCollection((el, _) => {
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
};
|
||||
|
||||
A._Collection.prototype.css = function (...args) {
|
||||
if (typeof args[0] === 'string' && typeof args[1] === 'string') {
|
||||
return this._forCollection((el, _) => {
|
||||
el.style[args[0]] = args[1];
|
||||
});
|
||||
} else if (typeof args[0] === 'object') {
|
||||
return this._forCollection((el, _) => {
|
||||
for (const [prop, value] of Object.entries(args[0])) {
|
||||
el.style[prop] = value;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error(`Method "css" does not accept first argument of type ${typeof handler}`);
|
||||
}
|
||||
};
|
||||
|
||||
A._Collection.prototype.createReactor = function (values, watchData=undefined, elementIndex=undefined) {
|
||||
const el = this._list[elementIndex];
|
||||
|
||||
const reactor = new A._Reactor(values, el, watchData);
|
||||
this.reactors.push(reactor);
|
||||
return reactor;
|
||||
};
|
||||
|
||||
// --- Reactor class ---
|
||||
|
||||
A._Reactor = class {
|
||||
constructor(values, element=undefined, watchData=undefined) {
|
||||
this.values = values;
|
||||
this._data = {};
|
||||
this.element = element;
|
||||
|
||||
if (watchData) {
|
||||
this.watch(watchData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
A._Reactor.prototype.watch = function (value) {
|
||||
if (typeof value === 'object') {
|
||||
// Format of config object { valueThatChanged: 'propertytoupdate' }
|
||||
if (!this.element) {
|
||||
throw new Error(`Method "watch" requires that "element" argument must exist in its class when being passed an object as an argument`);
|
||||
}
|
||||
|
||||
for (const [i, v] of Object.entries(value)) {
|
||||
Object.defineProperty(this.values, i, {
|
||||
set: (x) => {
|
||||
this._data[value] = x;
|
||||
|
||||
if (typeof v === 'function') {
|
||||
v(x);
|
||||
} else if (typeof v === 'string') {
|
||||
if (v.startsWith('!')) {
|
||||
// Property
|
||||
|
||||
this.element[v.substring(1)] = x;
|
||||
return;
|
||||
}
|
||||
if (v.startsWith('.')) {
|
||||
// Attribute
|
||||
|
||||
this.element.setAttribute(v.substring(1), x);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Don't blindly trust that the property exists.
|
||||
this.element.setAttribute(v, x);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Method "watch" does not accept value argument of type ${typeof value}`);
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue