Compare commits

..

2 commits

Author SHA1 Message Date
0c16b43ec7 feat: Update app and windows
- Move setAttributesAccordingToPosition to HippieTaskbar
- Use TimeDisplay inside HippieTaskbar
- Add readJsonFile and loadJson to app
- Initialize taskbar with config from data/windows.json
- Update jshint globals
2026-04-05 14:20:14 +02:00
b67a8a893a feat: Change file structure
- Move return object to named export for 11ty config
- screens is now view
- 11ty data files moved to view/_data
- templates is now view/_includes
- Both are the default directories
- data is now used as intended, for user data
- Update index to reflect filenames and structure
2026-04-05 14:13:32 +02:00
82 changed files with 123 additions and 67 deletions

View file

@ -32,7 +32,7 @@ export default async function (eleventyConfig) {
}); });
// TODO: Demo entfernen // TODO: Demo entfernen
const permalinkPath = await hasFiles('source/screens') ? '/demo/' : '/'; const permalinkPath = await hasFiles('source/view') ? '/demo/' : '/';
eleventyConfig.addGlobalData('hippie', { eleventyConfig.addGlobalData('hippie', {
brand: 'hippie', brand: 'hippie',
@ -130,14 +130,13 @@ export default async function (eleventyConfig) {
eleventyConfig.addPassthroughCopy({'node_modules/hippie-script/index.js': 'vendor/hippie-script.js'}); eleventyConfig.addPassthroughCopy({'node_modules/hippie-script/index.js': 'vendor/hippie-script.js'});
eleventyConfig.addWatchTarget('./source/style/'); eleventyConfig.addWatchTarget('./source/style/');
return {
dir: {
input: 'source/screens',
output: 'build',
includes: '../templates',
data: '../data'
},
templateFormats: ['html', 'liquid', 'md', 'njk']
};
} }
// noinspection JSUnusedGlobalSymbols
export const config = {
dir: {
input: 'source/view',
output: 'build'
},
templateFormats: ['html', 'liquid', 'md', 'njk']
};

View file

@ -14,20 +14,20 @@
"unused": false, "unused": false,
"browser": true, "browser": true,
"globals": { "globals": {
"HIPPIE": false,
"hippie": true,
"viewHover": true,
"basicEase": true,
"debugOn": true,
"TimeDisplay": true,
"DateDisplay": true, "DateDisplay": true,
"HIPPIE": false,
"HippieTaskBar": true,
"TimeDisplay": true,
"basicEase": true,
"centerElementUnderCursor": false,
"checkButtonAndTarget": false, "checkButtonAndTarget": false,
"debugOn": true,
"getClosestEdgeToElement": false, "getClosestEdgeToElement": false,
"getClosestEdgeToMouse": false, "getClosestEdgeToMouse": false,
"centerElementUnderCursor": false, "hippie": true,
"setAttributesAccordingToPosition": false,
"randomIntFrom": false, "randomIntFrom": false,
"readJsonFile": false,
"replaceLineBreaks": false, "replaceLineBreaks": false,
"HippieTaskBar": true "viewHover": true
} }
} }

View file

@ -1,6 +1,5 @@
# General # General
- Remove gulp and legacy files
- Better README with more info for the content section - Better README with more info for the content section
- Explain eleventy usage - Explain eleventy usage
- Complete CHANGELOG - Complete CHANGELOG
@ -8,6 +7,10 @@
- Add dynamic content to robots.txt during build process - Add dynamic content to robots.txt during build process
- Add dynamic content to sitemap.xml - Add dynamic content to sitemap.xml
# 11ty
- Look into teh difference of layouts and templates
# CSS # CSS
- Check style for every basic element - Check style for every basic element

View file

@ -394,20 +394,6 @@ function centerElementUnderCursor(event, element) {
element.style.top = `${y}px`; element.style.top = `${y}px`;
} }
function setAttributesAccordingToPosition(element, position, attributes) {
'use strict';
element.classList.remove(...Object.values(attributes).map(pos => pos.className));
Object.keys(attributes[position].styles).forEach(key => {
element.style[key] = '';
});
element.classList.add(attributes[position].className);
Object.entries(attributes[position].styles).forEach(([key, value]) => {
element.style[key] = value;
});
}
/** /**
* Gibt eine Zahl zwischen <min> und <max> aus. * Gibt eine Zahl zwischen <min> und <max> aus.
* Die Werte <min> und <max> sind dabei mit eingeschlossen. * Die Werte <min> und <max> sind dabei mit eingeschlossen.
@ -556,9 +542,37 @@ function zeroFill(number, width) {
// Retrieved 2026-03-08, License - CC BY-SA 4.0 // Retrieved 2026-03-08, License - CC BY-SA 4.0
const delay = ms => new Promise(res => setTimeout(res, ms)); const delay = ms => new Promise(res => setTimeout(res, ms));
class RandomPixelCanvas { async function readJsonFile(file) {
constructor(containerElement, options = {}) { return new Promise((resolve, reject) => {
this.container = containerElement; const reader = new FileReader();
reader.readAsText(file);
reader.onload = function () {
try {
resolve(JSON.parse(reader.result));
} catch (error) {
reject(error);
}
};
reader.onerror = function () {
reject(reader.error);
};
});
}
async function loadJson(filePath) {
try {
const response = await fetch(filePath);
if (!response.ok) throw new Error(`Failed to load file: ${response.status}`);
return await response.json();
} catch (error) {
console.error('Error loading file:', error);
throw error;
}
}
class RandomPixelPlaceholder { class RandomPixelPlaceholder {
constructor(parent, options = {}) { constructor(parent, options = {}) {
this.container = parent; this.container = parent;

View file

@ -3,9 +3,10 @@ class HippieTaskBar {
this.element = element; this.element = element;
this.placeholder = placeholder; this.placeholder = placeholder;
this.date = null; this.date = null;
this.time = null;
this.isDragging = false; this.isDragging = false;
this.barSize = ''; this.barSize = '';
// TODO: Erweitern auf allgemeine Möglichkeiten und dann aus JSON-Datei laden // TODO: Ergänzen und nicht ersetzen
this.options = options || { this.options = options || {
direction: 0, direction: 0,
position: 'bottom', position: 'bottom',
@ -13,7 +14,8 @@ class HippieTaskBar {
year: 'numeric', year: 'numeric',
month: '2-digit', month: '2-digit',
day: '2-digit' day: '2-digit'
} },
time: {hour: '2-digit', minute: '2-digit'}
}; };
this.init(); this.init();
@ -25,11 +27,20 @@ class HippieTaskBar {
document.addEventListener('pointermove', this.onMove.bind(this)); document.addEventListener('pointermove', this.onMove.bind(this));
document.addEventListener('pointerup', this.onUp.bind(this)); document.addEventListener('pointerup', this.onUp.bind(this));
const clock = this.element.querySelector('.clock');
const dateElement = document.createElement('span'); const dateElement = document.createElement('span');
const timeElement = document.createElement('span');
const br = document.createElement('br');
dateElement.id = 'date'; dateElement.id = 'date';
this.element.querySelector('.clock').appendChild(dateElement); timeElement.id = 'time';
this.date = new DateDisplay(dateElement, this.options.date); this.date = new DateDisplay(dateElement, this.options.date);
this.time = new TimeDisplay(timeElement, this.options.time);
// TODO: Reihenfolge anpassbar machen
clock.appendChild(timeElement);
clock.appendChild(br);
clock.appendChild(dateElement);
this.setOptions(this.options.position); this.setOptions(this.options.position);
} }
@ -111,7 +122,7 @@ class HippieTaskBar {
} }
}; };
setAttributesAccordingToPosition(this.placeholder, this.options.position, attributes); this.setAttributesAccordingToPosition(this.placeholder, this.options.position, attributes);
centerElementUnderCursor(event, this.placeholder); centerElementUnderCursor(event, this.placeholder);
} }
} }
@ -142,6 +153,18 @@ class HippieTaskBar {
this.date.changeFormat(this.options.date, this.options.direction); this.date.changeFormat(this.options.date, this.options.direction);
} }
setAttributesAccordingToPosition(element, position, attributes) {
element.classList.remove(...Object.values(attributes).map(pos => pos.className));
Object.keys(attributes[position].styles).forEach(key => {
element.style[key] = '';
});
element.classList.add(attributes[position].className);
Object.entries(attributes[position].styles).forEach(([key, value]) => {
element.style[key] = value;
});
}
setOptions(position) { setOptions(position) {
const attributes = { const attributes = {
top: { top: {
@ -182,7 +205,7 @@ class HippieTaskBar {
} }
}; };
setAttributesAccordingToPosition(this.element, position, attributes); this.setAttributesAccordingToPosition(this.element, position, attributes);
switch (position) { switch (position) {
case 'right': case 'right':

13
source/data/windows.json Normal file
View file

@ -0,0 +1,13 @@
{
"taskbar": {
"position": "top",
"color": "white",
"hover": {
"active": true,
"color": "#52bed1"
}
},
"window": {
"name": "Custom"
}
}

View file

@ -42,7 +42,7 @@
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script> <script>
// Setup global things for all screens // Setup global things
setup(); setup();
// Create instances of objects made by constructor functions // Create instances of objects made by constructor functions

View file

@ -29,10 +29,7 @@ tags:
<button><i class="bi bi-mic"></i></button> <button><i class="bi bi-mic"></i></button>
<button><i class="bi bi-volume-down"></i></button> <button><i class="bi bi-volume-down"></i></button>
</nav> </nav>
<div class="clock"> <div class="clock"></div>
<span id="time">##:##</span>
<br>
</div>
<nav> <nav>
<button data-action="notification"><i class="bi bi-bell-fill"></i></button> <button data-action="notification"><i class="bi bi-bell-fill"></i></button>
</nav> </nav>
@ -63,20 +60,27 @@ tags:
const start = document.querySelector('[data-action=start]'); const start = document.querySelector('[data-action=start]');
const draggableElement = document.getElementById('task-bar'); const draggableElement = document.getElementById('task-bar');
const placeholderElement = document.getElementById('placeholder'); const placeholderElement = document.getElementById('placeholder');
// TODO: TimeDisplay in HippieTaskbar aufnehmen
const timeElement = document.getElementById('time');
const taskBar = new HippieTaskBar(draggableElement, placeholderElement); initializeApp();
const timeFormat = {hour: '2-digit', minute: '2-digit'};
const timeDisplay = new TimeDisplay(timeElement, timeFormat);
document.getElementById('setPause').addEventListener('click', () => { async function initializeApp() {
timeDisplay.pause(); try {
console.info('Pause time'); const config = await loadJson('/json/windows.json');
}); // TODO: Elemente in der Klasse selbst erzeugen
document.getElementById('setPlay').addEventListener('click', () => { const taskBar = new HippieTaskBar(draggableElement, placeholderElement, config.taskbar);
timeDisplay.resume();
console.info('Resume time'); // TODO: In HippieTaskbar aufnehmen
}); document.getElementById('setPause').addEventListener('click', () => {
taskBar.time.pause();
console.info('Pause time');
});
document.getElementById('setPlay').addEventListener('click', () => {
taskBar.time.resume();
console.info('Resume time');
});
} catch (error) {
console.error('Failed to initialize app:', error);
}
}
</script> </script>
{% endblock %} {% endblock %}

View file

@ -12,17 +12,17 @@ title: Index
<h2>This is {{ hippie.brand | upcase }}</h2> <h2>This is {{ hippie.brand | upcase }}</h2>
<p>You can start using it by replacing this file with your own index page.</p> <p>You can start using it by replacing this file with your own index page.</p>
<p>To do this you need to create a file <p>To do this you need to create a file
<code>/index.njk</code> <code>index.liquid|njk</code>
inside the inside the
<i>source/screens</i> <i>source/view</i>
folder. You can also create a folder. You can also create a
<code>data.json</code> <code>data.json</code>
file inside the file inside the
<i>source/templates</i> <i>source/view</i>
folder as a data source for your nunjucks files.</p> folder as a global data source for your template files.</p>
<p>For a very basic start you can make a copy of the demo page <p>For a very basic start you can make a copy of the demo page
<code>blank.njk</code>. You can find it at <code>blank.liquid|njk</code>. You can find it at
<i>/source/screens/demo</i>.</p> <i>/source/view/demo/pages</i>.</p>
<p>The <p>The
<i>source/demo</i> <i>source/demo</i>
folder contains an overview of all HTML elements and also examples for CSS style combinations and even whole folder contains an overview of all HTML elements and also examples for CSS style combinations and even whole