Multi column layout for reddit redesign
当前为
// ==UserScript==
// @name Reddit Multi Column
// @namespace http://tampermonkey.net/
// @version 0.1.3
// @description Multi column layout for reddit redesign
// @author Can Altıparmak
// @homepage https://gist.github.com/c6p/463892bb243f611f2a3cfa4268c6435e
// @match https://www.reddit.com/*
// @grant none
// ==/UserScript==
/* jshint esversion: 6 */
(function() {
'use strict';
const MIN_WIDTH = 400;
const COLUMNS = 4;
let columns = COLUMNS;
let cleanup = false;
const OUTER = [
'#SHORTCUT_FOCUSABLE_DIV > div > div:nth-child(2) > div > div > div > div:nth-child(2) > div:nth-child(3) > div:nth-child(1)',
'#SHORTCUT_FOCUSABLE_DIV > div > div:nth-child(2) > div > div > div > div > div:nth-child(2) > div:nth-child(3) > div:nth-child(1)']
const cardButton = () => document.querySelector('#layoutSwitch--card');
const indexOfSmallest = function (a) {
let lowest = 0;
for (let i = 1; i<a.length; i++) {
if (a[i] < a[lowest]) lowest = i;
}
return lowest;
};
const select = function() {
let outer = null;
for (let o of OUTER) {
outer = document.querySelector(o);
if (outer !== null) break;
}
let inner = outer !== null ? outer.firstChild.firstChild : null;
return { outer, inner };
}
const makeLayout = function(changes=[]) {
// TODO if changes not empty, update only changed
const { outer, inner } = select();
if (inner === null) return;
const cols = Math.floor(inner.offsetWidth / MIN_WIDTH);
if (changes.length === 0 && cols === columns) return;
const c = cleanup;
if (c) {
outer.style.width = '';
inner.removeAttribute("style");
} else {
outer.style.width = "100%";
inner.setAttribute("style", "display: flex; width: 100%; flex-flow: column wrap; position: relative;");
}
columns = cols;
const WIDTH = Math.floor((100-columns)/columns);
let posts = inner.children;
let heights = Array(columns).fill(0);
for (let i=0; i<posts.length; i++) {
const post = posts[i];
const col = indexOfSmallest(heights);
let s = post.style
s.position = c ? "" : "absolute";
s.width = c ? "" : `${WIDTH}%`;
s.left = c ? "" : `${col*(WIDTH+1)}%`;
s.top = c ? "" : `${heights[col]}px`;
heights[col] += post.offsetHeight;
}
inner.style.height = c ? "" : `${Math.max(...heights)}px`;
};
const setLayout = function(changes, observer) {
const button = cardButton();
const c = button.getAttribute("aria-pressed") === "false";
if (c !== cleanup) {
cleanup = c;
makeLayout();
}
};
const pageChange = new MutationObserver(makeLayout);
const resize = new ResizeObserver(() => makeLayout());
const layoutSwitch = new MutationObserver(setLayout);
const watch = function(changes, observer) {
const { inner } = select();
if (inner === null) return;
layoutSwitch.observe(cardButton(), {attributes: true});
pageChange.observe(inner, {childList: true});
resize.observe(inner, {childList: true});
};
const apply = new MutationObserver(watch);
const page = document.querySelector('#SHORTCUT_FOCUSABLE_DIV > div > div:nth-child(2)');
apply.observe(page, {childList: true, subtree: true});
watch();
setLayout();
})();