-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBetter Indeed.user.js
More file actions
158 lines (150 loc) · 6.36 KB
/
Copy pathBetter Indeed.user.js
File metadata and controls
158 lines (150 loc) · 6.36 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// ==UserScript==
// @id better-indeed
// @name Better Indeed
// @version 1.1.1
// @namespace https://github.com/luigia
// @author Luigi Agcaoili
// @license MIT - https://opensource.org/licenses/MIT
// @description Removes bloat on Indeed by giving users the option to remove sponsored and/or Job Spotter postings
// @include https://indeed.com/jobs?*
// @include *indeed.com/*
// @run-at document-end
// @grant none
// @downloadURL https://update.greasyfork.org/scripts/371639/Better%20Indeed.user.js
// @updateURL https://update.greasyfork.org/scripts/371639/Better%20Indeed.meta.js
// ==/UserScript==
// select & edit the side bar
const filters = document.querySelector('#refineresults'),
bar = document.createElement('div');
bar.innerHTML = `
<h4 class="toggle-title">Toggle ads</h4>
<input type="checkbox" id="job-spotter-checkbox">
<label for="job-spotter-checkbox">Hide Job Spotter ads</label>
<input type="checkbox" id="sponsored-checkbox">
<label for="sponsored-checkbox">Hide sponsored ads</label>
`;
// add consistent styling to div
bar.style.marginBottom = '24px';
bar.style.marginLeft = '0';
bar.style.paddingLeft = '24px';
bar.style.color = '#2d2d2d';
bar.style.fontSize = '12px';
bar.style.maxWidth = '70%';
// add consistent styling to title
bar.firstElementChild.style.fontSize = '14px';
bar.firstElementChild.style.fontWeight = '500';
bar.firstElementChild.style.color = '#000';
// insert the div before the first child
filters.insertBefore(bar, filters.firstChild);
// checkbox variables
const jobSpotCb = document.querySelector('#job-spotter-checkbox'),
sponsoredCb = document.querySelector('#sponsored-checkbox');
// addEventListeners & check localStorage
window.onload = () => {
jobSpotCb.addEventListener('change', hideJobSpot);
sponsoredCb.addEventListener('change', hideSponsored);
// call the function based on localStorage definitions
let jobSpotLS = JSON.parse(localStorage.getItem(jobSpotCb.id)),
sponsoredLS = JSON.parse(localStorage.getItem(sponsoredCb.id));
if (jobSpotLS) {
jobSpotCb.checked = true;
hideJobSpot();
}
if (sponsoredLS) {
sponsoredCb.checked = true;
hideSponsored();
}
// re-insert pagination to the side or job posting after the pagination is moved
// check if there is only 1 page
// there won't be a pagination if there is only 1 page
if (document.querySelector('.pagination')) {
const pagination = document.querySelector('.pagination'),
results = document.querySelector('#resultsCol');
// add a delay as job postings aren't instantly loaded
setTimeout(() => {
let side = document.querySelector('#jobalerts') || document.querySelector('#vjs-header');
side.insertBefore(pagination, side.firstChild);
}, 200);
// move pagination when a result card is clicked
results.addEventListener('click', (e) => {
setTimeout(() => {
// currently viewing a job listing
if (document.querySelector('#vjs-header')) {
let vjsHeader = document.querySelector('#vjs-header');
// add pagination as the last child in the job posting header
vjsHeader.appendChild(pagination);
}
// add event listener to close button
if (document.querySelector('#vjs-x')) {
let close = document.querySelector('#vjs-x');
close.addEventListener('click', (e) => {
// move pagination back to the side if it's removed
if (document.querySelector('#jobalerts')) {
side = document.querySelector('#jobalerts');
side.insertBefore(pagination, side.firstChild);
}
});
}
}, 200);
})
}
}
// functions
// hide job spotter postings
const hideJobSpot = (e) => {
const linkSource = Array.from(document.querySelectorAll('.result-link-source')),
jobSpot = [];
// sources that include Job Spotter text are recorded
linkSource.forEach((source) => (source.textContent == 'Job Spotter ') && jobSpot.push(source));
// set variable in localStorage & show/hide Job Spotter postings
if (jobSpotCb.checked) {
localStorage.setItem(jobSpotCb.id, jobSpotCb.checked);
(jobSpot.length > 0) && jobSpot.forEach((posting) => posting.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.style.display = 'none');
} else {
localStorage.removeItem(jobSpotCb.id);
jobSpot.forEach((posting) => posting.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.style.display = 'block');
}
}
// hide sponsored postings
const hideSponsored = (e) => {
const lastSponsored = Array.from(document.querySelectorAll('.sjlast'));
// set variable in localStorage & show/hide sponsored postings
if (sponsoredCb.checked) {
localStorage.setItem(sponsoredCb.id, sponsoredCb.checked);
// use a loop only if there is more than one element for performance
(lastSponsored.length === 1) ? lastSponsored[0].parentElement.style.display = 'none' : lastSponsored.forEach((section) => section.parentElement.style.display = 'none');
// sometimes there will be a sponsored posting that is separate from other sponsored listings
if (document.querySelector('.sjita')) {
const singleAd = document.querySelector('.sjita');
singleAd.style.display = 'none';
}
} else {
localStorage.removeItem(sponsoredCb.id);
(lastSponsored.length === 1) ? lastSponsored[0].parentElement.style.display = 'block' : lastSponsored.forEach((section) => section.parentElement.style.display = 'block');
if (document.querySelector('.sjita')) {
const singleAd = document.querySelector('.sjita');
singleAd.style.display = 'none';
}
}
}
// keyboard navigation
const keyboardNav = (e) => {
// check if there is only 1 page
// there won't be a pagination if there is only 1 page
if (document.querySelector('.pagination')) {
const activePage = document.querySelector('.pagination b');
switch (e.keyCode) {
// left arrow key
case 37:
// this is not the first page
(activePage.previousElementSibling !== null) && activePage.previousElementSibling.click();
break;
// right arrow key
case 39:
// this is not the last page
(activePage.nextElementSibling !== null) && activePage.nextElementSibling.click();
break;
}
}
}
document.onkeydown = keyboardNav;