parsav  Diff

Differences From Artifact [682908b4c8]:

To Artifact [9100f46c08]:


     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) {