Differences From
Artifact [682908b4c8]:
3 3 * interactivity beyond what native HTML+CSS can provide. if so,
4 4 * we attach the appropriate listeners to them. */
5 5 window.addEventListener('load', function() {
6 6 /* social media is less fun when you can't just click on a tweet
7 7 * to insta-like or -retweet it. this is unfortunately not possible
8 8 * (except in various hideously shitty ways) without javascript. */
9 9 function mk(elt) { return document.createElement(elt); }
10 + function posturl(post) {
11 + return post.querySelector('.permalink').attributes.getNamedItem('href').value;
12 + }
13 + function postReq(url,act,elt) {
14 + fetch(new Request(url, {
15 + method: 'POST',
16 + body: 'act='+act
17 + })).then(function(resp) {
18 + if (resp.ok && resp.status == 200) {
19 + var i = parseInt(elt.innerHTML)
20 + if (isNaN(i)) {i=0}
21 + elt.innerHTML = (i+1).toString()
22 + }
23 + })
24 + }
25 +
26 + /* div-based like and rt aren't very keyboard-friendly. add a replacement */
27 + if (document.querySelector('body.timeline, body.profile') != null) {
28 + window.addEventListener('keydown', function(event) {
29 + if (!window._liveTweetMap) { return; }
30 + if (event.isComposing || event.keyCode === 229) { return; } // 🙄
31 + var cururl = window._liveTweetMap.cur;
32 + var nexturl = null;
33 + if (event.key == 'j') { // down
34 + if (cururl == null) {
35 + nexturl = window._liveTweetMap.first
36 + } else {
37 + nexturl = window._liveTweetMap.map.get(cururl).next
38 + }
39 + } else if (event.key == 'k') { // up
40 + if (cururl == null) {
41 + nexturl = window._liveTweetMap.last
42 + } else {
43 + nexturl = window._liveTweetMap.map.get(cururl).prev
44 + }
45 + } else if (cururl != null) {
46 + var post = window._liveTweetMap.map.get(cururl).me
47 + if (event.key == 'f') { // fave
48 + postReq(cururl, 'like', post.querySelector('.stats>.like'))
49 + } else if (event.key == 'r') { // rt
50 + postReq(cururl, 'rt', post.querySelector('.stats>.rt'))
51 + } else if (event.key == 'Enter') { // nav
52 + window.location = cururl;
53 + return;
54 + }
55 + }
56 + if (nexturl != null) {
57 + if (cururl != null) {
58 + var cur = window._liveTweetMap.map.get(cururl);
59 + cur.me.classList.remove('live-selected')
60 + }
61 + var next = window._liveTweetMap.map.get(nexturl);
62 + next.me.classList.add('live-selected')
63 + window._liveTweetMap.cur = nexturl
64 + }
65 + });
66 + }
67 +
10 68 function attachButtons() {
11 - document.querySelectorAll('body:not(.post) main div.post').forEach(function(post){
12 - let url = post.querySelector('.permalink').attributes.getNamedItem('href').value;
13 - function postReq(act,elt) {
14 - fetch(new Request(url, {
15 - method: 'POST',
16 - body: 'act='+act
17 - })).then(function(resp) {
18 - if (resp.ok && resp.status == 200) {
19 - var i = parseInt(elt.innerHTML)
20 - if (isNaN(i)) {i=0}
21 - elt.innerHTML = (i+1).toString()
22 - }
23 - })
69 + var last = null;
70 + var newmap = { cur: null, first: null, last: null, map: new Map() }
71 + document.querySelectorAll('body:not(.post) main article.post').forEach(function(post){
72 + let url = posturl(post);
73 + if (last == null) { newmap.first = url; } else {
74 + newmap.map.get(last).next = url
75 + }
76 + newmap.map.set(url, {me: post, prev: last, next: null})
77 + last = url
78 + if (window._liveTweetMap && window._liveTweetMap.cur == url) {
79 + post.classList.add('live-selected');
24 80 }
25 81
26 82 var stats = post.querySelector('.stats');
27 83 if (stats == null) {
28 84 /* no stats box; create one */
29 85 var n = mk('div');
30 86 n.classList.add('stats');
................................................................................
41 97 }
42 98 return n
43 99 } else { return s }
44 100 }
45 101 var like = ensureElt('like', null);
46 102 var rt = ensureElt('rt','.like');
47 103 function activate(elt,name) {
48 - elt.addEventListener('click', function(e) { postReq(name,elt) });
104 + elt.addEventListener('click', function(e) { postReq(url,name,elt) });
49 105 elt.style.setProperty('cursor','pointer');
106 + elt.setAttribute('tabindex','0');
50 107 }
51 108 activate(like,'like');
52 109 activate(rt,'rt');
53 110 });
111 + newmap.last = last
112 + if (window._liveTweetMap) {
113 + newmap.cur = window._liveTweetMap.cur // TODO handle vanishments
114 + }
115 + window._liveTweetMap = newmap
54 116 }
55 117
56 118 /* update hue-picker background when slider is adjusted */
57 119 document.querySelectorAll('.color-picker').forEach(function(box) {
58 120 let slider = box.querySelector('[data-color-pick]');
59 121 box.style.setProperty('--hue', slider.value);
60 122 slider.addEventListener('input', function(e) {