您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
add clickable favorite markers to jobs in the list
// ==UserScript== // @name GIS Jobs Favorite // @namespace http://tampermonkey.net/ // @version 0.1 // @description add clickable favorite markers to jobs in the list // @author You // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @match http://gisjobsmap.com // @grant GM_addStyle // ==/UserScript== /*- The @grant directive is needed to work around a major design change introduced in GM 1.0. It restores the sandbox. */ (function init() { 'use strict'; var hasRun = false; waitForKeyElements (".feature-row", run); function run() { var jobs = document.getElementsByClassName("feature-row"); // print out the job id if (!jobs || jobs.length <= 0) { console.log(" no jobs, why am i here?"); return; } console.log("found "+ jobs.length + " jobs"); var i = 0; while (i < jobs.length) { // console.log("decorate ", i); decorateJob(jobs[i]); i++; } } function decorateJob(job){ var jobStorageKey = "favorite-set-" + job.attributes.id.value; //console.log(job, job.attributes.id); // add a span as a following sibling if(!document.getElementById(jobStorageKey)){ var favoriteInsert = document.createElement("span"); favoriteInsert.appendChild(document.createTextNode("F")); favoriteInsert.setAttribute("id", jobStorageKey); applyStyle(favoriteInsert, jobStorageKey); job.appendChild(favoriteInsert); //console.log(job, favoriteInsert); // add an onclick handler that // checks if the localStorage value exists and toggles it if so // else creates it and sets it to true //--- Activate the newly added button. favoriteInsert.addEventListener ( "click", toggleFavorite, false ); } } function applyStyle(element, jobStorageKey){ var favoritedStyle = "position: absolute; text-align: center; border:1px solid blue; height:30px; width:30px; margin-left: -30px; background: yellow;"; var hatedStyle = "position: absolute; text-align: center; border:1px solid blue; height:30px; width:30px; margin-left: -30px; background: red;"; var unknownStyle = "position: absolute; text-align: center; border:1px solid blue; height:30px; width:30px; margin-left: -30px;"; if (getValue(jobStorageKey) == "faved") { element.style.cssText = favoritedStyle;} else if (getValue(jobStorageKey) == "nothing"){ element.style.cssText = unknownStyle; } else { element.style.cssText = hatedStyle; } } function setDefaultValue(storageKey){ localStorage.setItem(storageKey, "nothing"); } function getValue(storageKey){ var value = localStorage.getItem(storageKey); if (value == "faved") { return value; } else if (value == "hated") { return value; } else { return "nothing"; } } function setNextValue(storageKey){ var value = getValue(storageKey); if (value == "faved"){ localStorage.setItem(storageKey, "hated");} else if (value == "hated") { localStorage.setItem(storageKey, "nothing");} else { localStorage.setItem(storageKey, "faved"); } } function toggleFavorite(event){ event.preventDefault(); event.cancelBubble = true; event.returnValue = false; var jobStorageKey = event.target.id; //console.log(getValue(jobStorageKey)); //console.log("toggle toggle: ", event); var oldValue = getValue(jobStorageKey); setNextValue(jobStorageKey); var newValue = getValue(jobStorageKey); applyStyle(event.target, jobStorageKey); console.log(oldValue, "for ", jobStorageKey, "changed to", newValue); } })(); // @require https://gist.github.com/raw/2625891/waitForKeyElements.js // greasyfork doesn't allow require of external scripts /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, that detects and handles AJAXed content. Usage example: waitForKeyElements ( "div.comments" , commentCallbackFunction ); //--- Page-specific function to do what we want when the node is found. function commentCallbackFunction (jNode) { jNode.text ("This comment changed by waitForKeyElements()."); } IMPORTANT: This function requires your script to have loaded jQuery. */ function waitForKeyElements ( selectorTxt, /* Required: The jQuery selector string that specifies the desired element(s). */ actionFunction, /* Required: The code to run when elements are found. It is passed a jNode to the matched element. */ bWaitOnce, /* Optional: If false, will continue to scan for new elements even after the first match is found. */ iframeSelector /* Optional: If set, identifies the iframe to search. */ ) { var targetNodes, btargetsFound; if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt); else targetNodes = $(iframeSelector).contents () .find (selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; /*--- Found target node(s). Go through each and act if they are new. */ targetNodes.each ( function () { var jThis = $(this); var alreadyFound = jThis.data ('alreadyFound') || false; if (!alreadyFound) { //--- Call the payload function. var cancelFound = actionFunction (jThis); if (cancelFound) btargetsFound = false; else jThis.data ('alreadyFound', true); } } ); } else { btargetsFound = false; } //--- Get the timer-control variable for this selector. var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace (/[^\w]/g, "_"); var timeControl = controlObj [controlKey]; //--- Now set or clear the timer as appropriate. if (btargetsFound && bWaitOnce && timeControl) { //--- The only condition where we need to clear the timer. clearInterval (timeControl); delete controlObj [controlKey] } else { //--- Set a timer, if needed. if ( ! timeControl) { timeControl = setInterval ( function () { waitForKeyElements ( selectorTxt, actionFunction, bWaitOnce, iframeSelector ); }, 300 ); controlObj [controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; }