This commit is contained in:
Flummi 2021-12-31 07:18:41 +01:00
parent a9116a52d9
commit 0399fa9e51
28 changed files with 2102 additions and 0 deletions

175
test1/f0ck.js Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
};
}
}

View 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
View 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
View 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
View 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
View File

@ -0,0 +1,13 @@
<html>
<head>
<link href="./style.css" rel="stylesheet" />
</head>
<body>
<div class="navbar">&nbsp;</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
View 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
View 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
View 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
View 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
View 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
View 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">&nbsp;</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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,5 @@
import './helper.js';
import './events.js';
import './api.js';
import './swipe.js';

5
test4/js/runtimes.js Normal file
View File

@ -0,0 +1,5 @@
import { eventrt } from './events.js';
export default {
events: eventrt,
};

67
test4/js/swipe.js Normal file
View 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
View 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
View 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
View 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%;
}
}