blah
This commit is contained in:
7
test4/README.md
Normal file
7
test4/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
Frontend in Aktion (oder auch nicht) :⁾
|
||||
|
||||
https://dev.f0ck.space/misc/4
|
||||
|
||||
Benötigt wird:
|
||||
Chromium (ab Version 61)
|
||||
oder Firefox mit "dom.moduleScripts.enabled" auf true (about:config)
|
98
test4/css/style.css
Normal file
98
test4/css/style.css
Normal file
@ -0,0 +1,98 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #262626;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
body {
|
||||
margin-top: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
a {
|
||||
color: #9f0;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: #74c100;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.thumb {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin: 0 8px 8px 0;
|
||||
float: left;
|
||||
outline: none;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
box-shadow: inset 0 0 10px #4c4a4a;
|
||||
}
|
||||
a.thumb:hover {
|
||||
opacity: 0.5;
|
||||
box-shadow: inset 0 0 10px #9f0;
|
||||
}
|
||||
|
||||
div#page {
|
||||
position: absolute;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
top: 22px;
|
||||
bottom: 16px;
|
||||
}
|
||||
div#thumbs {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #040;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
font-weight: bold;
|
||||
position: fixed;
|
||||
overflow: visible;
|
||||
z-index: 999;
|
||||
background-color: #484747;
|
||||
border-bottom: 2px solid #9f0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.pscroll {
|
||||
opacity: 0.7;
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
left: 50%;
|
||||
cursor: pointer;
|
||||
margin-left: -36px;
|
||||
z-index: 999;
|
||||
}
|
||||
div.pscroll:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
div#up {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAANlBMVEUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyP///8iIiLm5uY3NzdKSkpAQEAqKipZf6aEAAAACnRSTlOxIfAAKvPn6quuQpaxIgAAAMZJREFUeF7t17uOwjAYROHjOMCuL0l4/5ddbQU0M4p/RIE8/flkyY1NTr/XNrjrT8qsSwtsWaGFBpcYcKEF9xFgAhMo9xIBytFrP8owUPb6v10JmN4K6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4LiN4LD2Cv53c8AaUPAL08AXVk9zeeoG3nhb69XuP5fdkLZQITmED840kMIP75zonbaH4j5T8NALtW477R3QAAAABJRU5ErkJggg==');
|
||||
top: 3.2em;
|
||||
}
|
||||
div#down {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAANlBMVEUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyMiIiLm5uY3NzcqKipAQED///9KSkpHtWFIAAAACnRSTlMqACGx8/Cu6uerGsmyTAAAAM9JREFUeF7t1zkOwzAMBVEt3kLK2/0vm3KQivhWigTQ7+dBpZhyeW3+cNtSckqzd2xOafGu1TT1AVPyzv0YMIABDMD0fQB7u9S1HcCNXhAM4CAQZl98gZ8PgNsB3G69NwAEqQdAUHoABKUHQNB6AAStB0DQegAErQdA0HoABK0HQNB6AAShBwgE+gBACHuAWKCPAIS4B4gEegFAoHcFQKBXAAR6BUCgVwAEehlAoNcBt7Nd7TTXAYjD/uKDMYAB9B+etQ+o/cd3Lsv6NF9ryW9/v8EFMSsbFgAAAABJRU5ErkJggg==');
|
||||
bottom: 56px;
|
||||
}
|
17
test4/index.html
Normal file
17
test4/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!doctype blah>
|
||||
<html>
|
||||
<head>
|
||||
<title>f0ckv2 dev</title>
|
||||
<link href="./css/style.css" rel="stylesheet" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> </div>
|
||||
<div id="page">
|
||||
<div id="thumbs" style="top: 0;"></div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="./js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
43
test4/js/api.js
Normal file
43
test4/js/api.js
Normal file
@ -0,0 +1,43 @@
|
||||
import rt from './runtimes.js';
|
||||
import { render } from './helper.js';
|
||||
|
||||
export const api = {
|
||||
items: new Map(),
|
||||
meta: [],
|
||||
getItems: function() {
|
||||
return fetch("//api.allorigins.win/raw?url=https://f0ck.me/api/p", {
|
||||
headers: {
|
||||
//'Accept': 'application/json',
|
||||
//'Content-Type': 'application/json'
|
||||
},
|
||||
method: 'GET'
|
||||
//method: 'POST',
|
||||
//body: JSON.stringify({ ...rt.events.hash, eps: rt.events.dims.eps })
|
||||
})
|
||||
.then(res => res.status === 200? res.json() : {error:true} )
|
||||
.then(data => {
|
||||
if(!data.error) {
|
||||
this.meta = data.meta;
|
||||
[...data.items.prev, ...data.items.next].forEach(e => this.items.set(e.stamp, e));
|
||||
}
|
||||
return {
|
||||
prev: data.items.prev.sort().reverse(),
|
||||
next: data.items.next.sort().reverse()
|
||||
};
|
||||
})
|
||||
.then(data => {
|
||||
this.items = new Map([...this.items.entries()].sort().reverse());
|
||||
console.log(data);
|
||||
});
|
||||
},
|
||||
get pos() {
|
||||
return {
|
||||
latest: [...this.items][0],
|
||||
first: [...this.items][this.items.size - 1]
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
api.getItems().then(() => {
|
||||
render(api.items);
|
||||
});
|
31
test4/js/cfg.js
Normal file
31
test4/js/cfg.js
Normal file
@ -0,0 +1,31 @@
|
||||
export default {
|
||||
layout: {
|
||||
items: {
|
||||
size: 128, // imgsize
|
||||
gutter: 8 // padding
|
||||
},
|
||||
min_margin: 16,
|
||||
min_rows: 2,
|
||||
min_cols: 3
|
||||
},
|
||||
misc: {
|
||||
scrollrows: 4
|
||||
},
|
||||
api: {
|
||||
uri: "//f0ck.me/api/",
|
||||
modes: [
|
||||
"user",
|
||||
"mime",
|
||||
"new"
|
||||
]
|
||||
},
|
||||
tpl: {
|
||||
row: ({ rowid, items }) => `<div class="row" data-row="${rowid}">${items}</div>`,
|
||||
item: ({ id, }) => `<a href="//f0ck.me/${id}" class="thumb" style="background-image:url('//f0ck.me/t/${id}.png')"></a>`
|
||||
},
|
||||
container: {
|
||||
debug: document.querySelector("div.navbar"),
|
||||
page: document.querySelector("div#page"),
|
||||
thumbs: document.querySelector("div#thumbs")
|
||||
}
|
||||
};
|
83
test4/js/events.js
Normal file
83
test4/js/events.js
Normal file
@ -0,0 +1,83 @@
|
||||
import cfg from './cfg.js';
|
||||
import { getposall } from './helper.js';
|
||||
|
||||
export const eventrt = {
|
||||
track: null,
|
||||
scroll: false,
|
||||
dims: null,
|
||||
hash: window.location.hash,
|
||||
};
|
||||
|
||||
// <track>
|
||||
const tracktopevent = new CustomEvent('top', { bubbles: true });
|
||||
Object.defineProperty(cfg.container.thumbs, 'top', {
|
||||
set: function(top) {
|
||||
this.style.top = top;
|
||||
this.dispatchEvent(tracktopevent);
|
||||
}
|
||||
});
|
||||
|
||||
export const tracktop = e => {
|
||||
eventrt.track = getposall(e.target.querySelectorAll("a.thumb"));
|
||||
//console.log(eventrt.track);
|
||||
};
|
||||
// </track>
|
||||
|
||||
// <scroll>
|
||||
export const scroll = e => {
|
||||
if(e.preventDefault)
|
||||
e.preventDefault();
|
||||
const deltaY = e.deltaY < 0?-1:1; // - up, + down
|
||||
|
||||
if(!eventrt.scroll) {
|
||||
eventrt.scroll = true;
|
||||
const dura = 500;
|
||||
const top = parseInt(cfg.container.thumbs.style.top.replace("px",""));
|
||||
const go = `${(top + (-deltaY * ((cfg.layout.items.size + cfg.layout.items.gutter) * cfg.misc.scrollrows)))}`;
|
||||
cfg.container.thumbs.animate( [{ top: `${top}px` }, { top: `${go}px` } ], { duration: dura } );
|
||||
setTimeout(() => { // after scroll
|
||||
cfg.container.thumbs.top = `${go}px`;
|
||||
eventrt.scroll = false;
|
||||
|
||||
console.log( [...new Set([...cfg.container.thumbs.querySelectorAll("a.thumb")].map(e => {
|
||||
return [e.children[0], e.parentNode].reduce((a,b) => a.offsetTop + b.offsetTop);
|
||||
}))] );
|
||||
|
||||
|
||||
}, dura);
|
||||
}
|
||||
};
|
||||
// </scroll>
|
||||
|
||||
// <resize>
|
||||
export const resize = e => {
|
||||
let rows = Math.max(~~((window.innerHeight - cfg.layout.min_margin + cfg.layout.items.size) / (cfg.layout.items.size + cfg.layout.items.gutter)), cfg.layout.min_rows);
|
||||
let cols = Math.max(~~((window.innerWidth - cfg.layout.min_margin) / (cfg.layout.items.size + cfg.layout.items.gutter)), cfg.layout.min_cols);
|
||||
let pageWidth = cols * (cfg.layout.items.size + cfg.layout.items.gutter);
|
||||
let margin = Math.max((window.innerWidth - pageWidth + cfg.layout.items.gutter) / cfg.layout.min_rows, 0);
|
||||
cfg.container.page.style.width = pageWidth;
|
||||
cfg.container.page.style.marginLeft = margin;
|
||||
eventrt.dims = {
|
||||
rows: rows,
|
||||
cols: cols,
|
||||
eps: rows * cols,
|
||||
pageWidth: pageWidth,
|
||||
margin: margin
|
||||
};
|
||||
};
|
||||
// <resize>
|
||||
|
||||
// <hash>
|
||||
export const hash = e => {
|
||||
eventrt.hash = window.location.hash;
|
||||
console.log(eventrt.hash);
|
||||
};
|
||||
// </hash>
|
||||
|
||||
|
||||
// bind events
|
||||
window.addEventListener("resize", resize);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
document.addEventListener("wheel", scroll);
|
||||
cfg.container.thumbs.addEventListener('top', tracktop);
|
||||
window.addEventListener("hashchange", hash);
|
55
test4/js/helper.js
Normal file
55
test4/js/helper.js
Normal file
@ -0,0 +1,55 @@
|
||||
import cfg from './cfg.js';
|
||||
import rt from './runtimes.js';
|
||||
|
||||
export const getpos = elems => [elems[0], elems[elems.length-1]].map(e => [e.children[0], e.parentNode].reduce((a, b) => a.offsetTop + b.offsetTop));
|
||||
export const getposall = elems => [...new Set([...elems].map(e => [e.children[0], e.parentNode].reduce((a,b) => a.offsetTop + b.offsetTop)))];
|
||||
|
||||
export const getlink = tmp => {
|
||||
const blah = {
|
||||
mode: "",
|
||||
user: "",
|
||||
mime: "",
|
||||
last: 0,
|
||||
post: 0
|
||||
};
|
||||
const api = "./api/";
|
||||
if(!tmp.match(/\,/))
|
||||
tmp = "#new";
|
||||
tmp = (tmp.match(/,/)?tmp:`${tmp},`).substr(1).split(",");
|
||||
const args = {
|
||||
l: tmp[0].split("/"),
|
||||
r: tmp[1].split("/")
|
||||
};
|
||||
blah.mode = ( args.l[0].length === 0 )? "new" : args.l[0];
|
||||
blah.last = parseInt(args.r[0]) || 0;
|
||||
blah.post = parseInt(args.r[1]) || 0;
|
||||
switch(blah.mode) {
|
||||
case "user":
|
||||
blah.user = ( args.l[1] )? args.l[1] : "";
|
||||
blah.mime = ( args.l[2] )? args.l[2] : "";
|
||||
break;
|
||||
case "mime":
|
||||
blah.user = ( args.l[2] )? args.l[2] : "";
|
||||
blah.mime = ( args.l[1] )? args.l[1] : "";
|
||||
break;
|
||||
}
|
||||
return {
|
||||
mode: blah.mode,
|
||||
user: blah.user,
|
||||
stamp: blah.last,
|
||||
mime: blah.mime,
|
||||
eps: this._dims.eps,
|
||||
sort: this._lastmode
|
||||
};
|
||||
};
|
||||
|
||||
export const render = items => {
|
||||
items.forEach(item => {
|
||||
let thumb = document.createElement('a');
|
||||
thumb.className = "thumb";
|
||||
thumb.href = "#";
|
||||
thumb.style.backgroundImage = `url("//f0ck.me/t/${item.id}.png")`;
|
||||
thumb.append(document.createElement('dummy'));
|
||||
cfg.container.thumbs.append(thumb);
|
||||
});
|
||||
};
|
5
test4/js/main.js
Normal file
5
test4/js/main.js
Normal file
@ -0,0 +1,5 @@
|
||||
import './helper.js';
|
||||
import './events.js';
|
||||
import './api.js';
|
||||
|
||||
import './swipe.js';
|
5
test4/js/runtimes.js
Normal file
5
test4/js/runtimes.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { eventrt } from './events.js';
|
||||
|
||||
export default {
|
||||
events: eventrt,
|
||||
};
|
67
test4/js/swipe.js
Normal file
67
test4/js/swipe.js
Normal file
@ -0,0 +1,67 @@
|
||||
import { scroll } from './events.js';
|
||||
import rt from './runtimes.js';
|
||||
|
||||
const eventtmp = {
|
||||
touchTracker: []
|
||||
};
|
||||
|
||||
const copyTouch = touch => {
|
||||
return {
|
||||
identifier: touch.identifier,
|
||||
screenX: touch.screenX,
|
||||
screenY: touch.screenY
|
||||
};
|
||||
};
|
||||
|
||||
const getTrackedTouchIndex = identifier => {
|
||||
for(let i = 0; i < eventtmp.touchTracker.length; i++) {
|
||||
if(eventtmp.touchTracker[i].identifier == identifier)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
const removeTouch = identifier => {
|
||||
let index = getTrackedTouchIndex(ct.item(i).identifier);
|
||||
if(index === -1)
|
||||
return index;
|
||||
eventtmp.touchTracker.splice(index, 1);
|
||||
};
|
||||
|
||||
const touchstart = e => {
|
||||
if(!rt.events.scroll) {
|
||||
const ct = e.changedTouches;
|
||||
for(let i = 0; i < e.changedTouches.length; i++)
|
||||
eventtmp.touchTracker.push(copyTouch(ct.item(i)));
|
||||
}
|
||||
};
|
||||
|
||||
const touchmove = e => {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
const touchend = e => {
|
||||
e.preventDefault();
|
||||
if(!rt.events.scroll) {
|
||||
let ct = e.changedTouches;
|
||||
for(let i = 0; i < ct.length; i++) {
|
||||
let index = getTrackedTouchIndex(ct.item(i).identifier);
|
||||
if(index !== -1) {
|
||||
let t = copyTouch(eventtmp.touchTracker[index]);
|
||||
if(Math.abs(Math.atan((ct.item(i).screenX - t.screenX) / (ct.item(i).screenY - t.screenY))) < 30)
|
||||
scroll({ deltaY: t.screenY > ct.item(i).screenY?1:-1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const touchcancel = e => {
|
||||
e.preventDefault();
|
||||
const ct = e.changedTouches;
|
||||
ct.forEach(e => removeTouch(ct.item(ct).identifier));
|
||||
};
|
||||
|
||||
window.addEventListener("touchstart", touchstart);
|
||||
window.addEventListener("touchmove", touchmove);
|
||||
window.addEventListener("touchend", touchend);
|
||||
window.addEventListener("touchcancel", touchcancel);
|
Reference in New Issue
Block a user