Skip to content

Instantly share code, notes, and snippets.

@blasten
Created January 19, 2018 22:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blasten/1047d00eaf8852adfdc3d705b3a0c4d2 to your computer and use it in GitHub Desktop.
Save blasten/1047d00eaf8852adfdc3d705b3a0c4d2 to your computer and use it in GitHub Desktop.
!(function(t, i) {
"object" == typeof exports && "undefined" != typeof module
? (module.exports = i())
: "function" == typeof define && define.amd ? define(i) : (t.Layout = i());
})(this, function() {
"use strict";
function t(t, i, n) {
let e = S;
if (n) {
X.length = 0;
let t;
for (; (t = S.shift()); )
t();
e = X;
}
return e.push(i), t().then(t => {
if (e.shift() === i) return i();
});
}
function i(t, i, n) {
return Math.max(i, Math.min(n, t));
}
function n(t, i, n, e, s, h) {
return s == L ? t <= n - h : i >= n + e + h;
}
function e(t, i, n, e, s) {
if (n == L && i + 1 < e.length) {
let n = s.get(e[i + 1]);
return n.a - t.b;
}
if (n == w && i > 0) {
let t = s.get(e[i - 1]);
return t.a + t.b;
}
return t.a;
}
function s(t) {
if (t.hasOwnProperty("props")) {
let i = t.props;
delete t.props, (t.props = i);
}
}
function h(t) {
const i = document;
return t !== i.body && t !== i.documentElement && t instanceof HTMLElement
? t
: window;
}
function o(t) {
return h(t) == E ? E.pageYOffset : t.scrollTop;
}
function r(t, i) {
h(t) == E ? E.scrollTo(0, i) : (t.scrollTop = i);
}
function u(t, i) {
if (0 == t) return [];
let n = Array(t);
n[0] = [0, i(0)];
for (let e = 1; e < t; e++) {
let t = n[e - 1][1] + 1, s = t + i(e);
n[e] = [t, s];
}
return n;
}
function f(t, i) {
let n = 0, e = i.length - 1;
for (; n <= e; ) {
let s = (n + e) >> 1;
if (t < i[s][0]) e = s - 1;
else {
if (!(t > i[s][1])) return s;
n = s + 1;
}
}
return null;
}
function a(t, i) {
return Object.keys(t).reduce((n, e) => {
let s = t[e];
return s.b > 0 && s.a <= i && (!n || i - s.a < i - n.a) ? s : n;
}, null);
}
function c(t, i, n) {
t[i] || (t[i] = []), t[i].push(n);
}
function d(t, i) {
return t[i] ? t[i].pop() : null;
}
function l() {
return document.createElement("div");
}
function g(t) {
let i = t.style;
return (i.position =
"absolute"), (i.top = "-10000px"), (i.height = ""), (i.bottom = ""), (i.left = "0"), (i.right = "0"), t;
}
function p() {
return Promise.resolve();
}
function m() {
return new Promise(function(t) {
E.requestIdleCallback
? E.requestIdleCallback(t)
: E.setTimeout(
t.bind(null, {
timeRemaining() {
return 50;
}
}),
16
);
});
}
function b() {
return new Promise(function(t) {
E.requestAnimationFrame(t);
});
}
function x() {
return new Promise(function(t) {
setTimeout(function() {
E.requestAnimationFrame(t);
});
});
}
const y = {},
k = -1,
L = 1,
w = 2,
M = 0,
v = 10,
E = window,
j = "scrollingElement",
T = "numberOfRowsInSection",
R = "numberOfSections",
C = "sectionIndex",
F = "rowIndex",
O = "poolForHeader",
P = "poolForRow",
H = "heightForHeader",
q = "heightForRow",
z = "domForHeader",
I = "domForRow",
N = "keyForHeader",
Z = "keyForRow",
A = "bottom";
let X = [], S = [];
class V {
constructor(t, i, n, e, s) {
(this.c = t), (this.d = n), (this.e = e), (this.f = i), (this.g = []), (this.h = []), (this.i = {}), (this.j = s);
}
k(t, i) {
let n = this.j, e = [], s = k;
t.forEach((t, i) => {
let n = t.dataset.key;
this.i[n] || (e.push(n), this.l(t));
}), t === this.g && ((s = (i == L ? this.m : this.n).idx), (this.g = [])), this.o(
i,
p,
n.p,
Math.max(v, t.length),
!0,
s
).then(t => {
e.forEach(t => {
let i = this.e.get(this.i[t]);
(i && !this.q(i.idx)) || this.r(t);
});
});
}
s(t, i) {
let n = this.j, e = t ? 3 : v, s = t ? n.t : n.p, h = t ? m : p;
return this.o(L, h, s, e, i).then(t => this.o(w, h, s, e, i));
}
o(i, n, e, s, h, o = k) {
let r, u = h ? p : x;
return t(
n,
f => {
if (!e(this.n, this.m, i))
return (r = this.u(i, s, o)), r.size > 0
? t(
u,
t => {
return this.v(r), (this.g = r.nodes), this.o(
i,
n,
e,
s,
h,
o
);
},
!1
)
: void 0;
},
!0
);
}
w(t) {
let i = t.dataset;
i.pool || (i.pool = M), this.i[i.key] || c(this.f, i.pool, g(t));
}
u(t, i, n) {
let e,
s,
h = this.j,
o = this.g,
r = this.e,
u = 0,
f = this.n,
a = this.m;
if (
!((f && t == L && 0 === f.idx) || (a && t == w && a.idx === h.x() - 1))
) {
for (; t == L && (e = o[o.length - 1]) && (s = r.get(e)) && h.y(s); )
this.w(e), o.pop();
for (; t == w && (e = o[0]) && (s = r.get(e)) && h.y(s); )
this.w(e), o.shift();
for (; u < i && (e = this.z(t, n)); )
t == L ? o.unshift(e) : o.push(e), this.A(e), u++;
}
return { dir: t, nodes: o, size: u };
}
v(t) {
let i = t.nodes, n = t.dir, e = t.size, s = this.e, h = this.j;
for (
let o = e - 1;
n == L && o >= 0;
o--
) h.B(i[o], s.get(i[o]), i, s, o, n);
for (
let o = i.length - e;
n == w && o < i.length;
o++
) h.B(i[o], s.get(i[o]), i, s, o, n);
for (let o = e - 1; n == L && o >= 0; o--) h.C(i[o], s.get(i[o]));
for (
let o = i.length - e;
n == w && o < i.length;
o++
) h.C(i[o], s.get(i[o]));
}
A(t) {
let i = this.c;
t.appendChild && t.parentNode !== i && i.appendChild(t);
}
z(t, i = k) {
let n, e = this.j.x();
if (0 == this.g.length) n = Math.min(i, e - 1);
else if (((n = t == L ? this.n.idx - 1 : this.m.idx + 1), n < 0))
return null;
return n < e && e > 0 ? this.D(n) : null;
}
D(t) {
let i, n, e, s = t, h = this.j, o = this.i;
h.x();
return (i = h.F(
this.d[t] || { idx: t, key: s }
)), (e = h.G(i.idx, i)), (s = i.key), (n = o[s] || d(this.f, e) || g(h.H())), (n = h.I(n, i.idx, i)), (this.d[i.idx] = i), this.e.set(n, i), (n.dataset.key = s), (n.dataset.pool = e), o[s] && (o[s] = n), n;
}
q(t) {
return t >= this.n.idx && t <= this.m.idx;
}
l(t) {
this.i[t.dataset.key] = t;
}
J(t) {
let i, n = this.j, e = this.d[t];
return e && (i = this.i[e.key])
? (n.C(i, e), e.key)
: ((i = this.q(t) ? this.g[t - this.n.idx] : this.D(t)), this.l(
i,
!1
), this.A(i, w), n.C(i, this.e.get(i)), i.dataset.key);
}
r(t) {
let i = this.i[t];
if (i) {
let n = this.e.get(i) || y;
delete this.i[t], this.g[n.idx - this.n.idx] == i
? this.j.C(i, n)
: this.w(i);
}
}
get n() {
return this.e.get(this.g[0]) || y;
}
get m() {
return this.e.get(this.g[this.g.length - 1]) || y;
}
get K() {
return this.g;
}
}
class W extends HTMLElement {
constructor() {
super(), s(
this
), (this.L = 0), (this.M = 0), (this.N = 0), (this.O = 0), (this.P = k), (this.Q = null), (this.R = null), (this.d = {}), (this.f = {}), (this.S = 0), (this.T = !1), (this.e = new WeakMap()), (this.U = this.U.bind(this)), (this.V = this.V.bind(this)), (this.W = this.W.bind(this));
let t = this;
this.X = new V(this, this.f, this.d, this.e, {
F(n) {
if (n.idx != k) return t.Y(n);
let e = a(t.d, t.L);
if (e && e.idx < t.Z && !this.y(e)) return t.Y(e);
let s = i(~~(t.L / t.$), 0, t.Z - 1);
return t.Y({ idx: s, b: 0, a: s * t.$ });
},
y(i) {
return i.a + i.b < t.L || i.a > t.L + t._;
},
p(i, e, s) {
return n(i.a, e.a + e.b, t.L, t._, s, t.aa === s ? t.S : 0);
},
t(i, e, s) {
return n(i.a, e.a + e.b, t.L, t._, s, 500);
},
G(i, n) {
let e = t.ba;
return n.ca ? e[O](n.da) : e[P](n.da, n.ea);
},
C(i, n) {
let e = i.style;
if (
((e.position = "absolute"), (e.top = `${n.a}px`), (e.left =
"0"), (e.right = "0"), n.ca)
) {
let s = t.R,
h = s[n.da + 1],
o = i.fa.style,
r = h ? t.d[h[0]] : null;
r && r.a > n.a
? ((e.height = `${r.a - n.a}px`), (e.bottom = "auto"))
: ((e.height = ""), (e.bottom = "0")), (o.position =
"-webkit-sticky"), (o.position = "sticky"), (o.top = "0px");
} else e.contain = "content";
},
B(i, n, s, h, o, r) {
let u = t.ba;
(n.b = n.ca
? u[H](i.firstElementChild, n.da)
: u[q](i, n.da, n.ea)), (n.a = e(n, o, r, s, h)), (n.M =
t.M), (t.N = t.N + n.b), (t.O = t.O + 1);
},
I(i, n, e) {
let s = t.ba, h = s[A], o = i.fa, r = h ? s[R] - e.da - 1 : e.da;
return e.ca
? (o ||
((o = i), (i = l()), (i.fa = o), i.appendChild(
o
)), (i.style.pointerEvents = "none"), (o.style.zIndex =
"1"), (o.style.pointerEvents = "auto"), s[z](o, r))
: s[I](i, r, h ? s[T](r) - e.ea - 1 : e.ea), i;
},
x() {
return t.Z;
},
H() {
return l();
}
});
}
connectedCallback() {
(this.style.cssText = `
display: block;
position: absolute;
`), E.addEventListener("resize", this.V), this.addEventListener("focus", this.W, !0);
}
disconnectedCallback() {
E.removeEventListener(
"resize",
this.V
), this.removeEventListener("focus", this.W);
}
get props() {
return Object.assign({}, this.ba);
}
set props(t) {
let i = this.ba;
this.ba = t;
let n = t[A];
this.R = u(t[R], i => t[T](n ? t[R] - i - 1 : i));
let e = n ? t[R] - t[C] - 1 : t[C];
this.ga(e, n ? t[T](e) - t[F] - 1 : t[F]), this.ha();
let s = i ? i[j] : null, o = t[j];
s !== o &&
(i && h(s).removeEventListener("scroll", this.U), h(o).addEventListener(
"scroll",
this.U
));
}
get Z() {
let t = this.R;
return t && t.length > 0 ? t[t.length - 1][1] + 1 : 0;
}
get $() {
return ~~(this.N / this.O) || 100;
}
get ia() {
if (0 === this.Z) return 0;
let t = this.d[this.Z - 1];
return t && this.M == t.M ? t.a + t.b : this.$ * this.Z;
}
ga(t, i = k) {
if (null != t && null != i) {
t < 0 && (t = 0);
let n = this.ba, e = n[R] - 1, s = this.R[t], h = s[0] + i + 1;
if (t > e)
return i >= s[1] - s[0] ? this.ga(e, n[T](e)) : this.ga(e, i);
(this.style.height = `${2 * this.ia}px`), (this.L = h * this.$), r(
n[j],
this.L
);
}
}
ha() {
let t = this.ba, i = this.M, n = this.X;
return b()
.then(e => {
if (i === this.M && (this.T || 0 != this.Z)) {
let i = t[j];
return this.M++, (this.O = 0), (this.N = 0), (this.L = o(
i
)), (this._ = i.clientHeight), n.k(
this.T ? n.K : Array.from(this.children),
t[A] ? L : w
);
}
})
.then(t => {
return this.ja(), n.s(!0);
})
.then(t => {
this.T = !0;
});
}
ja() {
let t = this.X, i = this.ba, n = t.n;
Promise.resolve()
.then(e => {
let s = n.idx, h = n.a;
if ((s > 0 && h < 0) || (0 == s && 0 != h))
return (n.a = this.$ * s), r(i[j], n.a + this.L - h), t.k(
t.K,
this.ba[A] ? L : w
);
})
.then(i => {
let n = this.R[t.n.da];
if (n) {
let i = n[0], e = t.J(i);
e != this.P && (t.r(this.P), (this.P = e));
}
this.style.height = `${this.ia}px`;
});
}
Y(t) {
let i = this.R,
n = this.ba,
e = f(t.idx, i),
s = t.idx - i[e][0] - 1,
h = t.idx == i[e][0],
o = h ? n[N](e) : n[Z](e, s);
return {
idx: t.idx,
key: o,
b: t.b || 0,
a: t.a || 0,
M: t.M || -1,
ca: h,
da: e,
ea: s
};
}
U() {
if (this.T) {
let t = this.props[j],
i = o(t),
n = this.L,
e = t.clientHeight,
s = Math.abs(n - i);
(this.L = i), (this._ = e), (this.S = s > e ? 0 : 3 * s), (this.aa = i >
n
? w
: L), this.X.s(!1, s > e).then(t => this.ja());
}
}
V() {
this.ha();
}
W(t) {
let i = t.target;
for (; i && i != this && !this.e.q(i); ) i = i.parentNode;
let n = this.e.get(i);
n && (this.ka && this.X.r(this.ka), (this.ka = this.X.J(n.idx)));
}
}
return customElements.define("layout-vertical", W), { LayoutVertical: W };
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment