blah
This commit is contained in:
parent
a9116a52d9
commit
0399fa9e51
175
test1/f0ck.js
Normal file
175
test1/f0ck.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
class f0ck {
|
||||
constructor(hash = "") {
|
||||
/*this.tpl = {
|
||||
row: ({ rowid, items }) => `<div class="row" data-row="${rowid}">${items}</div>`,
|
||||
item: ({ id, title, stamp }) => `<a href="//f0ck.me/${id}" data-stamp="${stamp}" class="thumb" style="background-image:url('//f0ck.me/t/${id}.png')"></a>`,
|
||||
};*/
|
||||
|
||||
this.tpl = {
|
||||
row: ({ rowid, items }) => `<div class="row" data-row="${rowid}">${items}</div>`,
|
||||
item: ({ stamp }) => `<a href="#" data-stamp="${stamp}" class="thumb" style="background-color: #0f0;"></a>`,
|
||||
};
|
||||
this._layout = {
|
||||
items: {
|
||||
size: 128,
|
||||
gutter: 8
|
||||
},
|
||||
min_margin: 16,
|
||||
min_rows: 2,
|
||||
min_cols: 3
|
||||
};
|
||||
this.tmp = {
|
||||
first: 0,
|
||||
last: 0
|
||||
}
|
||||
this._lastmode = "desc";
|
||||
this.scrollrows = 4;
|
||||
this._dims = null;
|
||||
this.init_events();
|
||||
this._scroll = false;
|
||||
this._items = new Map();
|
||||
this.tmphash = null;
|
||||
this.hash = hash; //setter
|
||||
}
|
||||
|
||||
render(tmp = null) {
|
||||
if(tmp !== null) {
|
||||
tmp.forEach(e => {
|
||||
this._items.set(e.stamp, e);
|
||||
});
|
||||
|
||||
/*let tmprow = "";
|
||||
for(let rows = 0; rows < this._dims.rows; rows++) {
|
||||
tmprow += [{ }]
|
||||
for(let cols = 0; cols < this._dims.cols; cols++) {
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
init_events() {
|
||||
let that = this;
|
||||
function resize() {
|
||||
let rows = Math.max(~~((window.innerHeight - that._layout.min_margin + that._layout.items.size) / (that._layout.items.size + that._layout.items.gutter)), that._layout.min_rows);
|
||||
let cols = Math.max(~~((window.innerWidth - that._layout.min_margin) / (that._layout.items.size + that._layout.items.gutter)), that._layout.min_cols);
|
||||
let pageWidth = cols * (that._layout.items.size + that._layout.items.gutter);
|
||||
let margin = Math.max((window.innerWidth - pageWidth + that._layout.items.gutter) / that._layout.min_rows, 0);
|
||||
let page = document.querySelector("div#page");
|
||||
page.style.width = pageWidth;
|
||||
page.style.marginLeft = margin;
|
||||
that._dims = {
|
||||
rows: rows,
|
||||
cols: cols,
|
||||
eps: rows * cols,
|
||||
pageWidth: pageWidth,
|
||||
margin: margin
|
||||
};
|
||||
that.render();
|
||||
}
|
||||
resize();
|
||||
|
||||
function scroll(e) {
|
||||
if(e.preventDefault)
|
||||
e.preventDefault();
|
||||
let deltaY = e.deltaY < 0?-1:1; // - up, + down
|
||||
|
||||
}
|
||||
window.addEventListener('resize', resize); // onresize
|
||||
document.addEventListener("wheel", scroll); // mousewheel
|
||||
document.querySelectorAll("div.pscroll").forEach(elem => elem.addEventListener("click", e => scroll({ deltaY: e.target.id === "up"?-1:1 }))); // buttons
|
||||
window.addEventListener("hashchange", () => { this.hash = window.location.hash }, false); // hashchange
|
||||
}
|
||||
|
||||
set hash(val) {
|
||||
console.log("hash changed");
|
||||
this.tmphash = this.getlink(val);
|
||||
this.firstrun = false;
|
||||
fetch(`/api/`, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.tmphash)
|
||||
})
|
||||
.then(res => {
|
||||
if(res.status === 200)
|
||||
return res.json();
|
||||
else
|
||||
return { error: true };
|
||||
})
|
||||
.then(data => {
|
||||
if(!data.error) {
|
||||
this.tmp = {
|
||||
first: data.meta.atFirst,
|
||||
last: data.meta.atLast
|
||||
};
|
||||
//const tmpmap = new Map();
|
||||
//data.items.forEach(e => tmpmap.set(e.stamp, e));
|
||||
//this.render(tmpmap);
|
||||
this.render(data.items);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getlink(tmp) {
|
||||
const tpl = {
|
||||
user: ({ user, mime, last }) => `user,${user},${mime},${last}`,
|
||||
mime: ({ user, mime, last }) => `mime,${mime},${user},${last}`,
|
||||
new: ({ user, mime, last }) => `items,${last}`,
|
||||
};
|
||||
let blah = {
|
||||
mode: "",
|
||||
user: "",
|
||||
mime: "",
|
||||
last: 0,
|
||||
post: 0
|
||||
};
|
||||
let 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;
|
||||
}
|
||||
console.log(this._lastmode);
|
||||
return {
|
||||
mode: blah.mode,
|
||||
user: blah.user,
|
||||
stamp: blah.last,
|
||||
mime: blah.mime,
|
||||
eps: this._dims.eps,
|
||||
sort: this._lastmode
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getKey(_map, _search) {
|
||||
let i = 0;
|
||||
for(let [key] of _map) {
|
||||
if(key === _search)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
}
|
31
test1/index.html
Normal file
31
test1/index.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
<!doctype blah>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test 1</title>
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<link href="./style.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<a href="./">reload</a> |
|
||||
<a href="#" data-id="1">debug 1</a> |
|
||||
<a href="#" data-id="2">page 2</a> |
|
||||
<a href="#" data-id="3">page 3</a>
|
||||
</div>
|
||||
|
||||
<div class="pscroll" id="up"></div>
|
||||
|
||||
<div id="page">
|
||||
<div id="thumbs" style="top: 0;"></div>
|
||||
</div>
|
||||
|
||||
<div class="pscroll" id="down"></div>
|
||||
|
||||
<script src="./f0ck.js"></script>
|
||||
<script>
|
||||
window.onload = () => {
|
||||
let f = new f0ck(window.location.hash);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
26
test1/script.js
Normal file
26
test1/script.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
$(document).ready(() => {
|
||||
$(window).on('resize', () => {
|
||||
let rows = Math.max(Math.floor(($(window).height() - 16 + 128) / (128 + 8)), 2);
|
||||
let cols = Math.max(Math.floor(($(window).width() - 16) / (128 + 8)), 3);
|
||||
let pageWidth = cols * (128 + 8);
|
||||
let margin = Math.max(($(window).width() - pageWidth + 8) / 2, 0);
|
||||
$("div#page").css({
|
||||
'width': pageWidth,
|
||||
'margin-left': margin
|
||||
});
|
||||
}).resize();
|
||||
|
||||
var scroll = false;
|
||||
$("body").on('DOMMouseScroll mousewheel', function(e) {
|
||||
e.preventDefault();
|
||||
if(!scroll) {
|
||||
scroll = true;
|
||||
$("#thumbs").animate({
|
||||
top: `${(parseInt($("#thumbs").css("top").replace("px","")) + (e.deltaY * 128))}px`
|
||||
}, 200, () => {
|
||||
scroll = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
96
test1/style.css
Normal file
96
test1/style.css
Normal file
|
@ -0,0 +1,96 @@
|
|||
* {
|
||||
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%;
|
||||
}
|
||||
.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;
|
||||
}
|
25
test2/index.html
Normal file
25
test2/index.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!doctype blah>
|
||||
<html>
|
||||
<head>
|
||||
<title>f0ckdev</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<span>Page 0</span>
|
||||
<a href="/">reload</a> |
|
||||
<a href="#" data-id="1">page 1</a> |
|
||||
<a href="#" data-id="2">page 2</a> |
|
||||
<a href="#" data-id="3">page 3</a>
|
||||
</div>
|
||||
|
||||
<div class="pscroll" id="up"></div>
|
||||
<div id="con"></div>
|
||||
<div class="pscroll" id="down"></div>
|
||||
|
||||
<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
|
||||
<script src="./lib/jquery.ba-hashchange.js"></script>
|
||||
<script src="./lib/f0ck.js"></script>
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
13
test2/lib/events.js
Normal file
13
test2/lib/events.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
$(document).ready(() => {
|
||||
$(window).on("resize", () => f.render());
|
||||
$(window).bind('mousewheel DOMMouseScroll MozMousePixelScroll', event => {
|
||||
f.page = (event.originalEvent.wheelDelta / 120 > 0)?-1:1;
|
||||
});
|
||||
|
||||
$("div#up").on("click", () => {
|
||||
f.page = -1;
|
||||
});
|
||||
$("div#down").on("click", () => {
|
||||
f.page = 1;
|
||||
});
|
||||
});
|
178
test2/lib/f0ck.js
Normal file
178
test2/lib/f0ck.js
Normal file
|
@ -0,0 +1,178 @@
|
|||
class f0ck {
|
||||
constructor(hash = "") {
|
||||
this.debug();
|
||||
this.tpl = {
|
||||
row: ({ items }) => `<ul class="posts">${items}</ul>`,
|
||||
item: ({ id, title, stamp }) => `<li class="post"><a href="https://f0ck.me/${id}" title="${title} ; ${stamp}"><img class="thumb" src="https://f0ck.me/t/${id}.png" /></a></li>`,
|
||||
};
|
||||
this.numitems = this.sumItems();
|
||||
this.items = {
|
||||
items: [],
|
||||
last: null,
|
||||
first: null
|
||||
};
|
||||
this.tmphash = null;
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
loadItems(init=false) {
|
||||
this.getItems().then(
|
||||
resolve => {
|
||||
console.log("resolved", this.items);
|
||||
//if(init) this.render(init);
|
||||
},
|
||||
reject => {
|
||||
console.error("REJECTED!");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.getJSON(`${this.tmphash.link},${(this.numitems.ipp*2)}`, data => {
|
||||
console.log("received data", data);
|
||||
this.items.last = data.meta.last;
|
||||
this.items.first = data.meta.first;
|
||||
|
||||
for(let item in data.items) {
|
||||
this.items.items[data.items[item].stamp] = data.items[item];
|
||||
}
|
||||
|
||||
return resolve();
|
||||
}).fail(err => {
|
||||
return reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
sumItems() {
|
||||
let h = $(window).innerHeight();
|
||||
let w = $(window).innerWidth();
|
||||
let itemsize = 128;
|
||||
let spacing = 10;
|
||||
let header = 90;
|
||||
let ipr = Math.floor( w / ( itemsize + spacing ) );
|
||||
let rpp = Math.floor( ( h - header ) / ( itemsize + spacing ) );
|
||||
let ipp = Math.floor( ipr * rpp );
|
||||
return {
|
||||
ipr: ipr, // items per row
|
||||
rpp: rpp, // rows per page
|
||||
ipp: ipp // items per page
|
||||
};
|
||||
}
|
||||
|
||||
render(init=false) {
|
||||
let tmpnum = this.sumItems();
|
||||
let container = $("div#con");
|
||||
if(this.numitems.ipp !== tmpnum.ipp || init) {
|
||||
console.log("rendering from", this.current);
|
||||
if(typeof this.current !== "number")
|
||||
return;
|
||||
container.html("");
|
||||
this.numitems = tmpnum;
|
||||
let rowtpl = "";
|
||||
let j, tmplast = 0;
|
||||
for(var i = this.current+1; j < this.numitems.ipp; i--) {
|
||||
if(this.items[i]) {
|
||||
rowtpl += [{ id: this.items[i].id, title: this.items[i].mime, stamp: this.items[i].stamp }].map(this.tpl.item).join``;
|
||||
j++;
|
||||
tmplast = this.items[i].stamp;
|
||||
}
|
||||
if(this.items.length < i) {
|
||||
j = this.numitems.ipp;
|
||||
}
|
||||
}
|
||||
this.scope.last = tmplast;
|
||||
console.log("finished rendering", container.length);
|
||||
container.append( [{ items: rowtpl }].map(this.tpl.row).join`` );
|
||||
}
|
||||
}
|
||||
|
||||
set hash(val) {
|
||||
console.log("hash changed");
|
||||
let tmp = this.getlink(val);
|
||||
this.tmphash = tmp;
|
||||
|
||||
//if(tmp.last < this.scope.first) {
|
||||
this.current = tmp.last;
|
||||
this.loadItems(true);
|
||||
//}
|
||||
//else if(tmp.last > this.scope.last || this.scope.last === 0) {
|
||||
// this.current = tmp.last;
|
||||
// this.loadItems(true);
|
||||
//}
|
||||
}
|
||||
|
||||
gethash() {
|
||||
return this.tmphash;
|
||||
}
|
||||
|
||||
debug() {
|
||||
$(".navbar a").on("click", event => {
|
||||
switch(event.target.innerText) {
|
||||
case "page 1":
|
||||
this.currentpage = 0;
|
||||
this.render(true);
|
||||
break;
|
||||
case "page 2":
|
||||
this.currentpage = 1;
|
||||
this.render(true);
|
||||
break;
|
||||
case "page 3":
|
||||
this.currentpage = 2;
|
||||
this.render(true);
|
||||
break;
|
||||
default:
|
||||
console.log("nope");
|
||||
break;
|
||||
}
|
||||
$(".navbar span").html(`Page ${this.currentpage}`);
|
||||
});
|
||||
}
|
||||
|
||||
getlink(tmp) {
|
||||
const tpl = {
|
||||
user: ({ user, mime, last, eps }) => `user,${user},${mime},${last}`,
|
||||
mime: ({ user, mime, last, eps }) => `mime,${mime},${user},${last}`,
|
||||
new: ({ user, mime, last, eps }) => `items,${last}`,
|
||||
};
|
||||
let blah = {
|
||||
mode: "",
|
||||
user: "",
|
||||
mime: "",
|
||||
last: 0,
|
||||
post: 0
|
||||
};
|
||||
let api = "/api/?";
|
||||
|
||||
if(!tmp.match(/\//)) {
|
||||
tmp = "#new/";
|
||||
}
|
||||
|
||||
|
||||
tmp = (tmp.match(/,/)?tmp:`${tmp},`).substr(1).split(",");
|
||||
console.log(tmp);
|
||||
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].length === 0 )? "" : args.l[1];
|
||||
blah.mime = ( args.l[2].length === 0 )? "" : args.l[2];
|
||||
break;
|
||||
case "mime":
|
||||
blah.user = ( args.l[2].length === 0 )? "" : args.l[2];
|
||||
blah.mime = ( args.l[1].length === 0 )? "" : args.l[1];
|
||||
break;
|
||||
}
|
||||
return {
|
||||
link: api + [{ user: blah.user, mime: blah.mime, last: blah.last, eps: this.numitems.ipp }].map(tpl[blah.mode]).join``,
|
||||
args: blah
|
||||
};
|
||||
}
|
||||
}
|
299
test2/lib/jquery.ba-hashchange.js
Normal file
299
test2/lib/jquery.ba-hashchange.js
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*!
|
||||
* jQuery hashchange event - v1.3 - 7/21/2010
|
||||
* http://benalman.com/projects/jquery-hashchange-plugin/
|
||||
*
|
||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
|
||||
// Script: jQuery hashchange event
|
||||
//
|
||||
// *Version: 1.3, Last updated: 7/21/2010*
|
||||
//
|
||||
// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
|
||||
// GitHub - http://github.com/cowboy/jquery-hashchange/
|
||||
// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
|
||||
// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)
|
||||
//
|
||||
// About: License
|
||||
//
|
||||
// Copyright (c) 2010 "Cowboy" Ben Alman,
|
||||
// Dual licensed under the MIT and GPL licenses.
|
||||
// http://benalman.com/about/license/
|
||||
//
|
||||
// About: Examples
|
||||
//
|
||||
// These working examples, complete with fully commented code, illustrate a few
|
||||
// ways in which this plugin can be used.
|
||||
//
|
||||
// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
|
||||
// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/
|
||||
//
|
||||
// About: Support and Testing
|
||||
//
|
||||
// Information about what version or versions of jQuery this plugin has been
|
||||
// tested with, what browsers it has been tested in, and where the unit tests
|
||||
// reside (so you can test it yourself).
|
||||
//
|
||||
// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
|
||||
// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
|
||||
// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
|
||||
// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/
|
||||
//
|
||||
// About: Known issues
|
||||
//
|
||||
// While this jQuery hashchange event implementation is quite stable and
|
||||
// robust, there are a few unfortunate browser bugs surrounding expected
|
||||
// hashchange event-based behaviors, independent of any JavaScript
|
||||
// window.onhashchange abstraction. See the following examples for more
|
||||
// information:
|
||||
//
|
||||
// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
|
||||
// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
|
||||
// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
|
||||
// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
|
||||
//
|
||||
// Also note that should a browser natively support the window.onhashchange
|
||||
// event, but not report that it does, the fallback polling loop will be used.
|
||||
//
|
||||
// About: Release History
|
||||
//
|
||||
// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more
|
||||
// "removable" for mobile-only development. Added IE6/7 document.title
|
||||
// support. Attempted to make Iframe as hidden as possible by using
|
||||
// techniques from http://www.paciellogroup.com/blog/?p=604. Added
|
||||
// support for the "shortcut" format $(window).hashchange( fn ) and
|
||||
// $(window).hashchange() like jQuery provides for built-in events.
|
||||
// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and
|
||||
// lowered its default value to 50. Added <jQuery.fn.hashchange.domain>
|
||||
// and <jQuery.fn.hashchange.src> properties plus document-domain.html
|
||||
// file to address access denied issues when setting document.domain in
|
||||
// IE6/7.
|
||||
// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin
|
||||
// from a page on another domain would cause an error in Safari 4. Also,
|
||||
// IE6/7 Iframe is now inserted after the body (this actually works),
|
||||
// which prevents the page from scrolling when the event is first bound.
|
||||
// Event can also now be bound before DOM ready, but it won't be usable
|
||||
// before then in IE6/7.
|
||||
// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
|
||||
// where browser version is incorrectly reported as 8.0, despite
|
||||
// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
|
||||
// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
|
||||
// window.onhashchange functionality into a separate plugin for users
|
||||
// who want just the basic event & back button support, without all the
|
||||
// extra awesomeness that BBQ provides. This plugin will be included as
|
||||
// part of jQuery BBQ, but also be available separately.
|
||||
|
||||
(function($,window,undefined){
|
||||
'$:nomunge'; // Used by YUI compressor.
|
||||
|
||||
// Reused string.
|
||||
var str_hashchange = 'hashchange',
|
||||
|
||||
// Method / object references.
|
||||
doc = document,
|
||||
fake_onhashchange,
|
||||
special = $.event.special,
|
||||
|
||||
// Does the browser support window.onhashchange? Note that IE8 running in
|
||||
// IE7 compatibility mode reports true for 'onhashchange' in window, even
|
||||
// though the event isn't supported, so also test document.documentMode.
|
||||
doc_mode = doc.documentMode,
|
||||
supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
|
||||
|
||||
// Get location.hash (or what you'd expect location.hash to be) sans any
|
||||
// leading #. Thanks for making this necessary, Firefox!
|
||||
function get_fragment( url ) {
|
||||
url = url || location.href;
|
||||
return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
|
||||
};
|
||||
|
||||
// Method: jQuery.fn.hashchange
|
||||
//
|
||||
// Bind a handler to the window.onhashchange event or trigger all bound
|
||||
// window.onhashchange event handlers. This behavior is consistent with
|
||||
// jQuery's built-in event handlers.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// > jQuery(window).hashchange( [ handler ] );
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// handler - (Function) Optional handler to be bound to the hashchange
|
||||
// event. This is a "shortcut" for the more verbose form:
|
||||
// jQuery(window).bind( 'hashchange', handler ). If handler is omitted,
|
||||
// all bound window.onhashchange event handlers will be triggered. This
|
||||
// is a shortcut for the more verbose
|
||||
// jQuery(window).trigger( 'hashchange' ). These forms are described in
|
||||
// the <hashchange event> section.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// (jQuery) The initial jQuery collection of elements.
|
||||
|
||||
// Allow the "shortcut" format $(elem).hashchange( fn ) for binding and
|
||||
// $(elem).hashchange() for triggering, like jQuery does for built-in events.
|
||||
$.fn[ str_hashchange ] = function( fn ) {
|
||||
return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
|
||||
};
|
||||
|
||||
// Property: jQuery.fn.hashchange.delay
|
||||
//
|
||||
// The numeric interval (in milliseconds) at which the <hashchange event>
|
||||
// polling loop executes. Defaults to 50.
|
||||
|
||||
// Property: jQuery.fn.hashchange.domain
|
||||
//
|
||||
// If you're setting document.domain in your JavaScript, and you want hash
|
||||
// history to work in IE6/7, not only must this property be set, but you must
|
||||
// also set document.domain BEFORE jQuery is loaded into the page. This
|
||||
// property is only applicable if you are supporting IE6/7 (or IE8 operating
|
||||
// in "IE7 compatibility" mode).
|
||||
//
|
||||
// In addition, the <jQuery.fn.hashchange.src> property must be set to the
|
||||
// path of the included "document-domain.html" file, which can be renamed or
|
||||
// modified if necessary (note that the document.domain specified must be the
|
||||
// same in both your main JavaScript as well as in this file).
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// jQuery.fn.hashchange.domain = document.domain;
|
||||
|
||||
// Property: jQuery.fn.hashchange.src
|
||||
//
|
||||
// If, for some reason, you need to specify an Iframe src file (for example,
|
||||
// when setting document.domain as in <jQuery.fn.hashchange.domain>), you can
|
||||
// do so using this property. Note that when using this property, history
|
||||
// won't be recorded in IE6/7 until the Iframe src file loads. This property
|
||||
// is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7
|
||||
// compatibility" mode).
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// jQuery.fn.hashchange.src = 'path/to/file.html';
|
||||
|
||||
$.fn[ str_hashchange ].delay = 50;
|
||||
/*
|
||||
$.fn[ str_hashchange ].domain = null;
|
||||
$.fn[ str_hashchange ].src = null;
|
||||
*/
|
||||
|
||||
// Event: hashchange event
|
||||
//
|
||||
// Fired when location.hash changes. In browsers that support it, the native
|
||||
// HTML5 window.onhashchange event is used, otherwise a polling loop is
|
||||
// initialized, running every <jQuery.fn.hashchange.delay> milliseconds to
|
||||
// see if the hash has changed. In IE6/7 (and IE8 operating in "IE7
|
||||
// compatibility" mode), a hidden Iframe is created to allow the back button
|
||||
// and hash-based history to work.
|
||||
//
|
||||
// Usage as described in <jQuery.fn.hashchange>:
|
||||
//
|
||||
// > // Bind an event handler.
|
||||
// > jQuery(window).hashchange( function(e) {
|
||||
// > var hash = location.hash;
|
||||
// > ...
|
||||
// > });
|
||||
// >
|
||||
// > // Manually trigger the event handler.
|
||||
// > jQuery(window).hashchange();
|
||||
//
|
||||
// A more verbose usage that allows for event namespacing:
|
||||
//
|
||||
// > // Bind an event handler.
|
||||
// > jQuery(window).bind( 'hashchange', function(e) {
|
||||
// > var hash = location.hash;
|
||||
// > ...
|
||||
// > });
|
||||
// >
|
||||
// > // Manually trigger the event handler.
|
||||
// > jQuery(window).trigger( 'hashchange' );
|
||||
//
|
||||
// Additional Notes:
|
||||
//
|
||||
// * The polling loop and Iframe are not created until at least one handler
|
||||
// is actually bound to the 'hashchange' event.
|
||||
// * If you need the bound handler(s) to execute immediately, in cases where
|
||||
// a location.hash exists on page load, via bookmark or page refresh for
|
||||
// example, use jQuery(window).hashchange() or the more verbose
|
||||
// jQuery(window).trigger( 'hashchange' ).
|
||||
// * The event can be bound before DOM ready, but since it won't be usable
|
||||
// before then in IE6/7 (due to the necessary Iframe), recommended usage is
|
||||
// to bind it inside a DOM ready handler.
|
||||
|
||||
// Override existing $.event.special.hashchange methods (allowing this plugin
|
||||
// to be defined after jQuery BBQ in BBQ's source code).
|
||||
special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
|
||||
|
||||
// Called only when the first 'hashchange' event is bound to window.
|
||||
setup: function() {
|
||||
// If window.onhashchange is supported natively, there's nothing to do..
|
||||
if ( supports_onhashchange ) { return false; }
|
||||
|
||||
// Otherwise, we need to create our own. And we don't want to call this
|
||||
// until the user binds to the event, just in case they never do, since it
|
||||
// will create a polling loop and possibly even a hidden Iframe.
|
||||
$( fake_onhashchange.start );
|
||||
},
|
||||
|
||||
// Called only when the last 'hashchange' event is unbound from window.
|
||||
teardown: function() {
|
||||
// If window.onhashchange is supported natively, there's nothing to do..
|
||||
if ( supports_onhashchange ) { return false; }
|
||||
|
||||
// Otherwise, we need to stop ours (if possible).
|
||||
$( fake_onhashchange.stop );
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// fake_onhashchange does all the work of triggering the window.onhashchange
|
||||
// event for browsers that don't natively support it, including creating a
|
||||
// polling loop to watch for hash changes and in IE 6/7 creating a hidden
|
||||
// Iframe to enable back and forward.
|
||||
fake_onhashchange = (function(){
|
||||
var self = {},
|
||||
timeout_id,
|
||||
|
||||
// Remember the initial hash so it doesn't get triggered immediately.
|
||||
last_hash = get_fragment(),
|
||||
|
||||
fn_retval = function(val){ return val; },
|
||||
history_set = fn_retval,
|
||||
history_get = fn_retval;
|
||||
|
||||
// Start the polling loop.
|
||||
self.start = function() {
|
||||
timeout_id || poll();
|
||||
};
|
||||
|
||||
// Stop the polling loop.
|
||||
self.stop = function() {
|
||||
timeout_id && clearTimeout( timeout_id );
|
||||
timeout_id = undefined;
|
||||
};
|
||||
|
||||
// This polling loop checks every $.fn.hashchange.delay milliseconds to see
|
||||
// if location.hash has changed, and triggers the 'hashchange' event on
|
||||
// window when necessary.
|
||||
function poll() {
|
||||
var hash = get_fragment(),
|
||||
history_hash = history_get( last_hash );
|
||||
|
||||
if ( hash !== last_hash ) {
|
||||
history_set( last_hash = hash, history_hash );
|
||||
|
||||
$(window).trigger( str_hashchange );
|
||||
|
||||
} else if ( history_hash !== last_hash ) {
|
||||
location.href = location.href.replace( /#.*/, '' ) + history_hash;
|
||||
}
|
||||
|
||||
timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
|
||||
};
|
||||
return self;
|
||||
})();
|
||||
|
||||
})(jQuery,this);
|
35
test2/lib/lib.js
Normal file
35
test2/lib/lib.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
var getlink = tmp => {
|
||||
const tpl = {
|
||||
user: ({ user, mime, last, eps }) => `user,${user},${mime},${last},${eps}`,
|
||||
mime: ({ user, mime, last, eps }) => `mime,${mime},${user},${last},${eps}`,
|
||||
new: ({ user, mime, last, eps }) => `items,${last},${eps}`,
|
||||
};
|
||||
|
||||
let api = "/api/?";
|
||||
tmp = (tmp.match(/,/)?tmp:`${tmp},`).substr(1).split(",");
|
||||
const args = {
|
||||
l: tmp[0].split("/"),
|
||||
r: tmp[1].split("/")
|
||||
};
|
||||
tmp = {
|
||||
mode: "",
|
||||
user: "",
|
||||
mime: "",
|
||||
last: 0,
|
||||
post: 0
|
||||
};
|
||||
tmp.mode = ( args.l[0].length === 0 )? "new" : args.l[0];
|
||||
tmp.last = parseInt(args.r[0]) || 0;
|
||||
tmp.post = parseInt(args.r[1]) || 0;
|
||||
switch(tmp.mode) {
|
||||
case "user":
|
||||
tmp.user = ( args.l[1].length === 0 )? "" : args.l[1];
|
||||
tmp.mime = ( args.l[2].length === 0 )? "" : args.l[2];
|
||||
break;
|
||||
case "mime":
|
||||
tmp.user = ( args.l[2].length === 0 )? "" : args.l[2];
|
||||
tmp.mime = ( args.l[1].length === 0 )? "" : args.l[1];
|
||||
break;
|
||||
}
|
||||
return api + [{ user: tmp.user, mime: tmp.mime, last: tmp.last, eps: 3 }].map(tpl[tmp.mode]).join``;
|
||||
};
|
38
test2/script.js
Normal file
38
test2/script.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
$(document).ready(() => {
|
||||
var f = new f0ck(window.location.hash);
|
||||
|
||||
$(window).hashchange(() => {
|
||||
f.hash = window.location.hash;
|
||||
});
|
||||
|
||||
//$(window).on("resize", () => f.render());
|
||||
//$(window).bind('mousewheel DOMMouseScroll MozMousePixelScroll', event => {
|
||||
// f.page = (event.originalEvent.wheelDelta / 120 > 0)?-1:1;
|
||||
//});
|
||||
|
||||
$("div#up").on("click", () => {
|
||||
return;
|
||||
});
|
||||
$("div#down").on("click", () => {
|
||||
let hash = f.tmphash.args;
|
||||
|
||||
let tmp = hash.mode;
|
||||
switch(hash.mode) {
|
||||
case "user":
|
||||
tmp += (hash.user.length > 1)?`/${hash.user}`:"";
|
||||
tmp += (hash.mime.length > 1)?`/${hash.mime}`:"";
|
||||
break;
|
||||
case "mime":
|
||||
tmp += (hash.mime.length > 1)?`/${hash.mime}`:"";
|
||||
tmp += (hash.user.length > 1)?`/${hash.user}`:"";
|
||||
break;
|
||||
}
|
||||
|
||||
tmp += ",";
|
||||
tmp += `${f.scope.last}`;
|
||||
//tmp += `${f.pages[f.currentpage][f.pages[f.currentpage].length-1][f.pages[f.currentpage][f.pages[f.currentpage].length-1].length-1].stamp}`;
|
||||
|
||||
window.location.hash = tmp;
|
||||
f.hash = window.location.hash;
|
||||
});
|
||||
});
|
81
test2/style.css
Normal file
81
test2/style.css
Normal file
|
@ -0,0 +1,81 @@
|
|||
* {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0em auto 3em auto;
|
||||
background-color: #262626;
|
||||
color: #fff;
|
||||
font-family: Monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.42857143;
|
||||
}
|
||||
|
||||
html, body {
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #9f0;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: #74c100;
|
||||
text-decoration: underline;
|
||||
}
|
||||
div#con {
|
||||
padding-top: 2.2em;
|
||||
height: 100%;
|
||||
}
|
||||
ul {
|
||||
width: 100%;
|
||||
margin: 15px 0 15px 0;
|
||||
}
|
||||
li.post {
|
||||
margin: 0 5px 0 5px;
|
||||
height: 128px;
|
||||
width: 128px;
|
||||
display: inline;
|
||||
}
|
||||
.thumb {
|
||||
border: 2px solid #4c4a4a;
|
||||
height: 128px;
|
||||
width: 128px;
|
||||
}
|
||||
.thumb:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.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#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;
|
||||
}
|
||||
|
||||
div.pscroll {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
left: 50%;
|
||||
margin-left: -36px;
|
||||
}
|
13
test3/index.html
Normal file
13
test3/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="./style.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> </div>
|
||||
<div id="page">
|
||||
<div id="thumbs" style="top: 0;">
|
||||
</div>
|
||||
</div>
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
37
test3/promises_fetch.js
Normal file
37
test3/promises_fetch.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*let rt = {
|
||||
user: "Flummi",
|
||||
mime: "",
|
||||
stamp: 1506717559,
|
||||
eps: 20,
|
||||
act: 0,
|
||||
items: new Map(),
|
||||
last: 0,
|
||||
first: 0,
|
||||
};
|
||||
|
||||
(function getitems() {
|
||||
Promise.all([
|
||||
fetch(`/api/test/?user=${rt.user}&mime=${rt.mime}&stamp=${rt.stamp}&eps=${rt.eps}`),
|
||||
fetch(`/api/test/?user=${rt.user}&mime=${rt.mime}&stamp=${rt.stamp}&eps=${rt.eps}&get=meta`)
|
||||
])
|
||||
.then(res => Promise.all(res.map(muh => muh.json())))
|
||||
.then(data => {
|
||||
return {
|
||||
act: data[0].items[0][0],
|
||||
items: data[0].items[1].concat(data[0].items[0]),
|
||||
items: [...data[0].items[1], ...data[0].items[0]],
|
||||
meta: data[1].meta
|
||||
};
|
||||
})
|
||||
.then(final => render(final));
|
||||
})();
|
||||
|
||||
function render(data=null) {
|
||||
if(data !== null) {
|
||||
data.items.forEach(e => rt.items.set(e.stamp, e));
|
||||
rt.act = data.act.stamp;
|
||||
rt.last = data.meta.last;
|
||||
rt.first = data.meta.first;
|
||||
}
|
||||
console.log(rt);
|
||||
}*/
|
120
test3/script.js
Normal file
120
test3/script.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
let _layout = {
|
||||
items: {
|
||||
size: 128,
|
||||
gutter: 8
|
||||
},
|
||||
min_margin: 16,
|
||||
min_rows: 2,
|
||||
min_cols: 3
|
||||
};
|
||||
_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>`,
|
||||
};
|
||||
let rt = {
|
||||
user: "Flummi",
|
||||
mime: "",
|
||||
stamp: 1506717559,
|
||||
act: 0,
|
||||
items: new Map(),
|
||||
last: 0,
|
||||
first: 0,
|
||||
};
|
||||
let _cache = [];
|
||||
let _dims = null;
|
||||
let _scroll = false;
|
||||
let _scrollrows = 4;
|
||||
let _container = {
|
||||
debug: document.querySelector("div.navbar"),
|
||||
page: document.querySelector("div#page"),
|
||||
thumbs: document.querySelector("div#thumbs")
|
||||
};
|
||||
|
||||
window.onload = () => {
|
||||
function resize() {
|
||||
let rows = Math.max(~~((window.innerHeight - _layout.min_margin + _layout.items.size) / (_layout.items.size + _layout.items.gutter)), _layout.min_rows);
|
||||
let cols = Math.max(~~((window.innerWidth - _layout.min_margin) / (_layout.items.size + _layout.items.gutter)), _layout.min_cols);
|
||||
let pageWidth = cols * (_layout.items.size + _layout.items.gutter);
|
||||
let margin = Math.max((window.innerWidth - pageWidth + _layout.items.gutter) / _layout.min_rows, 0);
|
||||
let page = _container.page;
|
||||
page.style.width = pageWidth;
|
||||
page.style.marginLeft = margin;
|
||||
_dims = {
|
||||
rows: rows,
|
||||
cols: cols,
|
||||
eps: rows * cols,
|
||||
pageWidth: pageWidth,
|
||||
margin: margin
|
||||
};
|
||||
render();
|
||||
}
|
||||
function scroll(e) {
|
||||
if(e.preventDefault)
|
||||
e.preventDefault();
|
||||
let deltaY = e.deltaY < 0?-1:1; // - up, + down
|
||||
|
||||
if(!_scroll) {
|
||||
_scroll = true;
|
||||
let dura = 500;
|
||||
let top = parseInt(_container.thumbs.style.top.replace("px",""));
|
||||
let go = `${(top + (-deltaY * ((_layout.items.size + _layout.items.gutter) * _scrollrows)))}`;
|
||||
_container.thumbs.animate( [{ top: `${top}px` }, { top: `${go}px` } ], { duration: dura } );
|
||||
setTimeout(() => { // after scroll
|
||||
_container.thumbs.style.top = `${go}px`;
|
||||
_scroll = false;
|
||||
//console.log( getpos( thumbs.querySelectorAll("div.row") ) );
|
||||
console.log( getposall( thumbs.querySelectorAll("div.row") ) );
|
||||
}, dura);
|
||||
}
|
||||
}
|
||||
resize();
|
||||
window.addEventListener("resize", resize);
|
||||
document.addEventListener("wheel", scroll);
|
||||
|
||||
function render() {
|
||||
let items = new Array(_dims.eps).fill({id: 25788}, 0, _dims.eps);
|
||||
let rowtpl = "";
|
||||
let blah = "";
|
||||
let rowid = 0;
|
||||
let j = 0;
|
||||
items.forEach(e => {
|
||||
rowtpl += [{ id: e.id }].map(_tpl.item).join``;
|
||||
if(++j % _dims.cols === 0) {
|
||||
blah += [{ rowid: rowid++, items: rowtpl }].map(_tpl.row).join``;
|
||||
rowtpl = "";
|
||||
}
|
||||
});
|
||||
_container.thumbs.innerHTML = blah;
|
||||
//console.log( getpos( thumbs.querySelectorAll("div.row") ) );
|
||||
console.log( getposall( thumbs.querySelectorAll("div.row") ) );
|
||||
}
|
||||
|
||||
function getpos(elems) {
|
||||
return [elems[0], elems[elems.length-1]].map(e => [e.children[0], e.parentNode].reduce((a, b) => a.offsetTop + b.offsetTop));
|
||||
}
|
||||
|
||||
function getposall(elems) {
|
||||
return [...elems].map(e => [e.children[0], e.parentNode].reduce((a,b) => a.offsetTop + b.offsetTop));
|
||||
}
|
||||
|
||||
function getItems(sum = 0, pos = "bottom") { // top/bottom
|
||||
sum = sum===0?_dims.eps:sum;
|
||||
Promise.all([
|
||||
fetch(`/api/test/?user=${rt.user}&mime=${rt.mime}&stamp=${rt.stamp}&eps=${sum}`),
|
||||
fetch(`/api/test/?user=${rt.user}&mime=${rt.mime}&stamp=${rt.stamp}&eps=${sum}&get=meta`)
|
||||
])
|
||||
.then(res => Promise.all(res.map(muh => muh.json())))
|
||||
.then(data => {
|
||||
_cache = data[0].items[1].concat(data[0].items[0]).sort().reverse();
|
||||
/*return {
|
||||
act: data[0].items[0][0],
|
||||
items: data[0].items[1].concat(data[0].items[0]),
|
||||
items: [...data[0].items[1], ...data[0].items[0]],
|
||||
meta: data[1].meta
|
||||
};*/
|
||||
});
|
||||
}
|
||||
|
||||
getItems();
|
||||
setTimeout(() => { console.log(_cache); }, 1000);
|
||||
};
|
73
test3/style.css
Normal file
73
test3/style.css
Normal file
|
@ -0,0 +1,73 @@
|
|||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #262626;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
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;
|
||||
}
|
||||
div#page {
|
||||
position: absolute;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
top: 22px;
|
||||
bottom: 16px;
|
||||
}
|
||||
div#thumbs {
|
||||
position: absolute;
|
||||
background-color: #040;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
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;
|
||||
}
|
||||
.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;
|
||||
}
|
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);
|
15
test5/index.html
Normal file
15
test5/index.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!doctype blah>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>f0ck-fe test</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="./style.css" rel="stylesheet" media="all">
|
||||
</head>
|
||||
<body>
|
||||
<div id="page">
|
||||
<section id="wall"></section>
|
||||
</div>
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
95
test5/script.js
Normal file
95
test5/script.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
let _layout = {
|
||||
items: {
|
||||
size: 128,
|
||||
gutter: 8
|
||||
},
|
||||
min_margin: 16,
|
||||
min_rows: 2,
|
||||
min_cols: 3
|
||||
};
|
||||
_tpl = {
|
||||
item: ({ id }) => `<article id="id${id}"><a href="#id${id}"><img src="//f0ck.me/t/${id}.png" /></a><div class="info"><div class="description"><h1>${id}</h1><p>Penis</p></div><ol><li>Infos lol</li><li>und so</li></ol></div></article>`
|
||||
};
|
||||
let rt = {
|
||||
user: "Flummi",
|
||||
mime: "",
|
||||
stamp: 1506717559,
|
||||
act: 0,
|
||||
items: new Map(),
|
||||
last: 0,
|
||||
first: 0,
|
||||
};
|
||||
let _cache = [];
|
||||
let _dims = null;
|
||||
let _scroll = false;
|
||||
let _scrollrows = 4;
|
||||
let _container = {
|
||||
page: document.querySelector("div#page"),
|
||||
wall: document.querySelector("section#wall")
|
||||
};
|
||||
|
||||
window.onload = () => {
|
||||
function init() {
|
||||
let rows = Math.max(~~((window.innerHeight - _layout.min_margin + _layout.items.size) / (_layout.items.size + _layout.items.gutter)), _layout.min_rows);
|
||||
let cols = Math.max(~~((window.innerWidth - _layout.min_margin) / (_layout.items.size + _layout.items.gutter)), _layout.min_cols);
|
||||
let pageWidth = cols * (_layout.items.size + _layout.items.gutter);
|
||||
let margin = Math.max((window.innerWidth - pageWidth + _layout.items.gutter) / _layout.min_rows, 0);
|
||||
let page = _container.page;
|
||||
page.style.width = pageWidth;
|
||||
page.style.marginLeft = margin;
|
||||
_dims = {
|
||||
rows: rows,
|
||||
cols: cols,
|
||||
eps: rows * cols,
|
||||
pageWidth: pageWidth,
|
||||
margin: margin
|
||||
};
|
||||
//render();
|
||||
}
|
||||
function scroll(e) {
|
||||
if(e.preventDefault)
|
||||
e.preventDefault();
|
||||
let deltaY = e.deltaY < 0?-1:1; // - up, + down
|
||||
|
||||
if(!_scroll) {
|
||||
_scroll = true;
|
||||
let dura = 500;
|
||||
let top = parseInt(_container.wall.style.top.replace("px",""));
|
||||
let go = `${(top + (-deltaY * ((_layout.items.size + _layout.items.gutter) * _scrollrows)))}`;
|
||||
_container.wall.animate( [{ top: `${top}px` }, { top: `${go}px` } ], { duration: dura } );
|
||||
setTimeout(() => { // after scroll
|
||||
_container.wall.style.top = `${go}px`;
|
||||
_scroll = false;
|
||||
}, dura);
|
||||
}
|
||||
}
|
||||
//document.addEventListener("wheel", scroll);
|
||||
|
||||
function render() {
|
||||
let blah = "";
|
||||
_cache.forEach(e => {
|
||||
blah += [{ id: e.id }].map(_tpl.item).join``;
|
||||
});
|
||||
_container.wall.innerHTML = blah;
|
||||
}
|
||||
|
||||
function getpos(elems) {
|
||||
return [elems[0], elems[elems.length-1]].map(e => [e.children[0], e.parentNode].reduce((a, b) => a.offsetTop + b.offsetTop));
|
||||
}
|
||||
|
||||
function getposall(elems) {
|
||||
return [...elems].map(e => [e.children[0], e.parentNode].reduce((a,b) => a.offsetTop + b.offsetTop));
|
||||
}
|
||||
|
||||
//api.allorigins.win/raw?url=https:
|
||||
function getItems(sum = 0, pos = "bottom") { // top/bottom
|
||||
fetch(`//f0ck.me/api/user/${rt.user}`)
|
||||
.then(res => res.json())
|
||||
.then(data => _cache = data);
|
||||
}
|
||||
|
||||
init();
|
||||
getItems();
|
||||
setTimeout(() => { render(); }, 500);
|
||||
setTimeout(() => { console.log(_cache); }, 1000);
|
||||
};
|
341
test5/style.css
Normal file
341
test5/style.css
Normal file
|
@ -0,0 +1,341 @@
|
|||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
body {
|
||||
background: #333;
|
||||
color: white;
|
||||
font-family: "Noto Sans", Tahoma, sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
section {
|
||||
max-width: 1600px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
section article {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
zoom: 1;
|
||||
padding: 5px;
|
||||
vertical-align: top;
|
||||
width: 50%;
|
||||
}
|
||||
section article:nth-child(2n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(2n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
section .info {
|
||||
width: 180%;
|
||||
padding: 2em 0;
|
||||
margin: 0 10%;
|
||||
position: relative;
|
||||
float: left;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
section .info h1 {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
section .info p,
|
||||
section .info ol {
|
||||
margin-bottom: 2em;
|
||||
line-height: 140%;
|
||||
}
|
||||
section .info ol {
|
||||
margin-left: 20px;
|
||||
}
|
||||
section .info li {
|
||||
list-style: decimal;
|
||||
line-height: 140%;
|
||||
}
|
||||
section .info .purchase {
|
||||
display: block;
|
||||
margin-top: .4em;
|
||||
padding: .4em;
|
||||
background: #006699;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
-webkit-transition: 0.5s background-color;
|
||||
-moz-transition: 0.5s background-color;
|
||||
-ms-transition: 0.5s background-color;
|
||||
-o-transition: 0.5s background-color;
|
||||
transition: 0.5s background-color;
|
||||
}
|
||||
section .info .purchase:hover {
|
||||
background: #0066CC;
|
||||
}
|
||||
section article:target .info {
|
||||
height: auto;
|
||||
font-size: 100%;
|
||||
opacity: 1;
|
||||
-webkit-transition: .5s .5s opacity;
|
||||
-moz-transition: .5s .5s opacity;
|
||||
-ms-transition: .5s .5s opacity;
|
||||
-o-transition: .5s .5s opacity;
|
||||
transition: .5s .5s opacity;
|
||||
}
|
||||
section article:target img {
|
||||
-webkit-box-shadow: 0 8px 3px -5px rgba(0,0,0,.5);
|
||||
-moz-box-shadow: 0 8px 3px -5px rgba(0,0,0,.5);
|
||||
box-shadow: 0 8px 3px -5px rgba(0,0,0,.5);
|
||||
-webkit-transform: scale(1.1);
|
||||
-moz-transform: scale(1.1);
|
||||
-ms-transform: scale(1.1);
|
||||
-o-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
-webkit-transition: .5s;
|
||||
-moz-transition: .5s;
|
||||
-ms-transition: .5s;
|
||||
-o-transition: .5s;
|
||||
transition: .5s;
|
||||
}
|
||||
footer {
|
||||
min-height: 400px;
|
||||
padding: 4em 1em;
|
||||
background: black;
|
||||
font-size: 1em;
|
||||
word-break: break-word;
|
||||
}
|
||||
footer .credits {
|
||||
width: 250px;
|
||||
}
|
||||
footer .credits li {
|
||||
display: inline-block;
|
||||
width: 32%;
|
||||
}
|
||||
footer a {
|
||||
color: white;
|
||||
}
|
||||
footer h2 {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
footer h1,
|
||||
footer h2,
|
||||
footer p,
|
||||
footer ul {
|
||||
line-height: 140%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 400px) {
|
||||
section article {
|
||||
width: 33.333333%;
|
||||
}
|
||||
section article .info {
|
||||
width: 280%;
|
||||
}
|
||||
section article .purchase {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
zoom: 1;
|
||||
float: left;
|
||||
clear: both;
|
||||
width: auto;
|
||||
margin-top: 2em 0 0 0;
|
||||
}
|
||||
section article .description {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
section article ol {
|
||||
float: right;
|
||||
width: 30%;
|
||||
}
|
||||
section article:nth-child(3n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(3n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section article:nth-child(3n+3) .info {
|
||||
left: -200%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) {
|
||||
section article .info {
|
||||
width: 380%;
|
||||
}
|
||||
section article {
|
||||
width: 25%;
|
||||
}
|
||||
section article:nth-child(4n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(4n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section article:nth-child(4n+3) .info {
|
||||
left: -200%;
|
||||
}
|
||||
section article:nth-child(4n+4) .info {
|
||||
left: -300%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 800px) {
|
||||
section article .info {
|
||||
width: 480%;
|
||||
}
|
||||
section article {
|
||||
width: 20%;
|
||||
}
|
||||
section article:nth-child(5n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(5n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section article:nth-child(5n+3) .info {
|
||||
left: -200%;
|
||||
}
|
||||
section article:nth-child(5n+4) .info {
|
||||
left: -300%;
|
||||
}
|
||||
section article:nth-child(5n+5) .info {
|
||||
left: -400%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1000px) {
|
||||
section article .info {
|
||||
width: 580%;
|
||||
}
|
||||
section article {
|
||||
width: 16.6666667%;
|
||||
}
|
||||
section article:nth-child(6n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(6n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section article:nth-child(6n+3) .info {
|
||||
left: -200%;
|
||||
}
|
||||
section article:nth-child(6n+4) .info {
|
||||
left: -300%;
|
||||
}
|
||||
section article:nth-child(6n+5) .info {
|
||||
left: -400%;
|
||||
}
|
||||
section article:nth-child(6n+6) .info {
|
||||
left: -500%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1200px) {
|
||||
section article .info {
|
||||
width: 680%;
|
||||
}
|
||||
section article {
|
||||
width: 14.2857143%;
|
||||
}
|
||||
section article:nth-child(7n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(7n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section article:nth-child(7n+3) .info {
|
||||
left: -200%;
|
||||
}
|
||||
section article:nth-child(7n+4) .info {
|
||||
left: -300%;
|
||||
}
|
||||
section article:nth-child(7n+5) .info {
|
||||
left: -400%;
|
||||
}
|
||||
section article:nth-child(7n+6) .info {
|
||||
left: -500%;
|
||||
}
|
||||
section article:nth-child(7n+7) .info {
|
||||
left: -600%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1400px) {
|
||||
section article .info {
|
||||
width: 780%;
|
||||
}
|
||||
section article {
|
||||
width: 12.5%;
|
||||
}
|
||||
section article:nth-child(8n+1) .info {
|
||||
left: 0;
|
||||
}
|
||||
section article:nth-child(8n+2) .info {
|
||||
left: -100%;
|
||||
}
|
||||
section article:nth-child(8n+3) .info {
|
||||
left: -200%;
|
||||
}
|
||||
section article:nth-child(8n+4) .info {
|
||||
left: -300%;
|
||||
}
|
||||
section article:nth-child(8n+5) .info {
|
||||
left: -400%;
|
||||
}
|
||||
section article:nth-child(8n+6) .info {
|
||||
left: -500%;
|
||||
}
|
||||
section article:nth-child(8n+7) .info {
|
||||
left: -600%;
|
||||
}
|
||||
section article:nth-child(8n+8) .info {
|
||||
left: -700%;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user