-
Notifications
You must be signed in to change notification settings - Fork 0
/
hide-twitter-trends.js
126 lines (118 loc) · 3.75 KB
/
hide-twitter-trends.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
* Content script.
* Hides Twitter Trends on page load
* and when receiving a removeTrends message.
*/
'use strict';
/**
* Try to remove the Trends widget. We try several approaches to identify it.
* They all try to identify the widget without relying on localized strings,
* and also without any class names, which don’t look very stable.
* Checks on the surrounding DOM try to reduce false positives.
*
* 1. Trends widget with a cogwheel link in the corner of the widget;
* the cogwheel is a real link with a constant href.
* 2. Trends widget with a “show more” link at the end;
* another real link with a constant href.
* 3. Trends widget with some “trending with…” links in the trends;
* real links with &src=trend_click in the URL.
*
* Most other things in these widgets, including the trends themselves,
* are unfortunately not links but divs with event handlers,
* so we can’t match on them very well.
*/
function removeTrends() {
for (let trends of document.querySelectorAll('a[href="/settings/trends"]')) {
if (trends.closest('article')) {
// trends link in a tweet
continue;
}
trends = trends.closest('h2');
if (!trends) {
// trends link in settings? maybe?
continue;
}
trends = trends.closest('section');
if (!trends) {
// (unclear if this can happen)
continue;
}
if (trends.firstElementChild.tagName !== 'H1') {
// (unclear if this can happen)
continue;
}
let parent;
while ((parent = trends.parentElement).childElementCount == 1)
trends = parent;
trends.remove();
return;
}
for (let trends of document.querySelectorAll('a[href="/i/trends"]')) {
if (trends.closest('article')) {
// trends link in a tweet
continue;
}
trends = trends.closest('section');
if (!trends) {
// (unclear if this can happen)
continue;
}
if (trends.firstElementChild.tagName !== 'H1') {
// (unclear if this can happen)
continue;
}
let parent;
while ((parent = trends.parentElement).childElementCount == 1)
trends = parent;
trends.remove();
return;
}
for (let trends of document.querySelectorAll('a[href*="&src=trend_click"]')) {
if (trends.closest('article')) {
// trends link in a tweet
continue;
}
trends = trends.closest('section');
if (!trends) {
// (unclear if this can happen)
continue;
}
if (trends.firstElementChild.tagName !== 'H1') {
// (unclear if this can happen)
continue;
}
let parent;
while ((parent = trends.parentElement).childElementCount == 1)
trends = parent;
trends.remove();
return;
}
}
/**
* Call removeTrends() immediately,
* and also a few more times with a delay,
* in case Twitter hadn’t finished updating the page yet.
*/
function removeTrendsAFewTimes() {
removeTrends();
for (const delay of [100, 500, 3000]) {
setTimeout(removeTrends, delay);
}
}
/**
* Call removeTrends() every so often,
* since Twitter occasionally seems to re-render itself
* even without any navigation activity.
*/
function removeTrendsPeriodically() {
setInterval(removeTrends, 30 * 60 * 1000); // every 30 minutes
}
removeTrendsAFewTimes();
removeTrendsPeriodically();
browser.runtime.onMessage.addListener(request => {
if (request === 'removeTrends') {
removeTrendsAFewTimes();
} else {
throw new Error(`Unknown request ${request}`);
}
});