您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
11/13/2024, 5:53:40 PM
- // ==UserScript==
- // @name LinkedIn Job Visibility Settings; year, job status highlight
- // @namespace Violentmonkey Scripts
- // @match https://www.linkedin.com/jobs/search/*
- // @match https://www.glassdoor.ca/Job/*
- // @match https://ca.indeed.com/*
- // @grant GM_getValue
- // @grant GM_setValue
- // @version 1.0
- // @author LAMSTREAM
- // @description 11/13/2024, 5:53:40 PM
- // ==/UserScript==
- (function() {
- 'use strict';
- // Define colors for each status
- const statusColors = { viewed: 'red',
- applied: 'green',
- promoted: 'purple',
- year: 'red' };
- // Initialize settings with stored values or defaults
- const settings = {
- hideViewed: GM_getValue('hideViewed', true),
- hideApplied: GM_getValue('hideApplied', true),
- hidePromoted: GM_getValue('hidePromoted', true),
- panelPosition: GM_getValue('panelPosition', { x: 20, y: 20 }),
- isCollapsed: GM_getValue('isCollapsed', false)
- };
- // Create and style the settings panel
- function createSettingsPanel() {
- const panel = document.createElement('div');
- panel.style.cssText = `
- position: fixed;
- top: ${settings.panelPosition.y}px;
- left: ${settings.panelPosition.x}px;
- background: white;
- padding: 15px;
- border-radius: 8px;
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
- z-index: 9999;
- font-family: system-ui, -apple-system, sans-serif;
- cursor: move;
- min-width: 200px;
- user-select: none;
- `;
- // Header container
- const header = document.createElement('div');
- header.style.cssText = `
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 10px;
- cursor: move;
- `;
- const title = document.createElement('h3');
- title.textContent = 'Job Visibility Settings';
- title.style.margin = '0';
- title.style.flex = '1';
- // Collapse/Expand button
- const collapseBtn = document.createElement('button');
- collapseBtn.style.cssText = `
- background: none;
- border: none;
- cursor: pointer;
- font-size: 20px;
- padding: 0 5px;
- margin-left: 10px;
- `;
- collapseBtn.textContent = settings.isCollapsed ? '▼' : '▲';
- collapseBtn.title = settings.isCollapsed ? 'Expand' : 'Collapse';
- header.appendChild(title);
- header.appendChild(collapseBtn);
- panel.appendChild(header);
- // Content container
- const content = document.createElement('div');
- content.style.display = settings.isCollapsed ? 'none' : 'block';
- // Create toggle switches for each setting
- const options = [
- { key: 'hideViewed', label: 'Hide Viewed', color: statusColors.viewed },
- { key: 'hideApplied', label: 'Hide Applied', color: statusColors.applied },
- { key: 'hidePromoted', label: 'Hide Promoted', color: statusColors.promoted }
- ];
- options.forEach(({ key, label, color }) => {
- const container = document.createElement('div');
- container.style.cssText = `
- margin: 10px 0;
- padding: 8px;
- border-radius: 4px;
- background: ${color}15;
- border: 1px solid ${color}40;
- `;
- const toggle = document.createElement('input');
- toggle.type = 'checkbox';
- toggle.id = key;
- toggle.checked = settings[key];
- toggle.style.marginRight = '8px';
- const labelElement = document.createElement('label');
- labelElement.htmlFor = key;
- labelElement.textContent = label;
- labelElement.style.color = color;
- labelElement.style.fontWeight = 'bold';
- toggle.addEventListener('change', (e) => {
- settings[key] = e.target.checked;
- GM_setValue(key, e.target.checked);
- hideListItems();
- });
- container.appendChild(toggle);
- container.appendChild(labelElement);
- content.appendChild(container);
- });
- panel.appendChild(content);
- // Make panel draggable
- let isDragging = false;
- let currentX;
- let currentY;
- let initialX;
- let initialY;
- header.addEventListener('mousedown', dragStart);
- document.addEventListener('mousemove', drag);
- document.addEventListener('mouseup', dragEnd);
- function dragStart(e) {
- initialX = e.clientX - settings.panelPosition.x;
- initialY = e.clientY - settings.panelPosition.y;
- isDragging = true;
- }
- function drag(e) {
- if (!isDragging) return;
- e.preventDefault();
- currentX = e.clientX - initialX;
- currentY = e.clientY - initialY;
- // Update position
- settings.panelPosition = { x: currentX, y: currentY };
- panel.style.left = `${currentX}px`;
- panel.style.top = `${currentY}px`;
- }
- function dragEnd() {
- if (!isDragging) return;
- isDragging = false;
- GM_setValue('panelPosition', settings.panelPosition);
- }
- // Handle collapse/expand
- collapseBtn.addEventListener('click', () => {
- settings.isCollapsed = !settings.isCollapsed;
- content.style.display = settings.isCollapsed ? 'none' : 'block';
- collapseBtn.textContent = settings.isCollapsed ? '▼' : '▲';
- collapseBtn.title = settings.isCollapsed ? 'Expand' : 'Collapse';
- GM_setValue('isCollapsed', settings.isCollapsed);
- });
- document.body.appendChild(panel);
- }
- // Function to hide li elements and color the status text
- const hideListItems = () => {
- const elements = document.querySelectorAll('.job-card-container__footer-item');
- elements.forEach(element => {
- const text = element.innerText;
- // Color the status text based on type
- if (text.includes('Viewed')) {
- element.style.color = statusColors.viewed;
- if (settings.hideViewed) hideFromAncestor(element);
- }
- else if (text.includes('Applied')) {
- element.style.color = statusColors.applied;
- if (settings.hideApplied) hideFromAncestor(element);
- }
- else if (text.includes('Promoted')) {
- element.style.color = statusColors.promoted;
- if (settings.hidePromoted) hideFromAncestor(element);
- }
- });
- };
- // Function to hide the ancestor li element
- const hideFromAncestor = (element) => {
- let liElement = element.parentElement.closest('li');
- if (liElement) {
- liElement.style.display = 'none';
- }
- };
- // Function to highlight the word "year" in text content
- const highlightYear = () => {
- const elements = [...document.querySelectorAll('.jobs-search__job-details--wrapper'), ...document.querySelectorAll('[class^="JobDetails_jobDescription"]'), ...document.querySelectorAll('#jobDescriptionText') ]
- observer.disconnect()
- elements.forEach(element => {
- // Get all text nodes within the element, including nested ones
- const walk = document.createTreeWalker(
- element,
- NodeFilter.SHOW_TEXT,
- null,
- false
- );
- const textNodes = [];
- let node;
- while (node = walk.nextNode()) {
- textNodes.push(node);
- }
- // Process each text node
- textNodes.forEach(textNode => {
- const text = textNode.textContent;
- if (/(year|years)/i.test(text)) {
- const span = document.createElement('span');
- span.innerHTML = text.replace(/(years|year)/gi, '<span style="color: red">$1</span>');
- textNode.parentNode.replaceChild(span, textNode);
- }
- });
- });
- // Observe changes in the DOM
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- characterData: true
- });
- };
- const highlightCurrentTab = () => {
- observer.disconnect(); // Temporarily stop observing mutations
- const items = document.querySelectorAll('[class*="JobsList_jobListItem"]'); // Get all job list items
- items.forEach(item => {
- const classList = item.className; // Get full class name as string
- if (classList.includes("JobsList_selected")) {
- item.classList.add("highlight"); // Add highlight if selected
- } else {
- item.classList.remove("highlight"); // Remove highlight if not selected
- }
- });
- observer.observe(document.body, { childList: true, subtree: true }); // Resume observing
- };
- // Observe changes in the DOM to apply the filtering dynamically
- const observer = new MutationObserver((mutations) => {
- hideListItems();
- highlightYear();
- highlightCurrentTab();
- });
- // Observe changes in the DOM
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- characterData: true
- });
- // Initial setup
- createSettingsPanel();
- hideListItems();
- highlightYear();
- highlightCurrentTab()
- setTimeout(() => {
- const style = document.createElement("style");
- style.textContent = `
- body .highlight {
- position: relative !important;
- }
- body .highlight::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(144, 238, 144, 0.5) !important;
- pointer-events: none;
- z-index: 1000;
- }
- `;
- document.head.appendChild(style);
- }, 100);
- })();