// ==UserScript== // @name Make Bookmarklets from Javascript URLs // @namespace MBFU // @description When it sees a link to a userscript or general Javascript URL, adds a Bookmarklet besides it, which you can drag to your toolbar to load the script when you next need it (running outside Greasemonkey of course). // @include http://hwi.ath.cx/*/gm_scripts/* // @include http://hwi.ath.cx/*/userscripts/* // @include http://*userscripts.org/* // @include https://*userscripts.org/* // @include http://openuserjs.org/* // @include https://openuserjs.org/* // @include http://greasyfork.org/* // @include https://greasyfork.org/* // @include http://*/* // @include https://*/* // @exclude http://hwi.ath.cx/code/other/gm_scripts/joeys_userscripts_and_bookmarklets_overview.html // @exclude http://neuralyte.org/~joey/gm_scripts/joeys_userscripts_and_bookmarklets_overview.html // @exclude http://joeytwiddle.github.io/code/other/gm_scripts/joeys_userscripts_and_bookmarklets_overview.html // @grant none // @version 1.2.8 // @downloadURL https://update.greasyfork.icu/scripts/7668/Make%20Bookmarklets%20from%20Javascript%20URLs.user.js // @updateURL https://update.greasyfork.icu/scripts/7668/Make%20Bookmarklets%20from%20Javascript%20URLs.meta.js // ==/UserScript== // BUG: We had (i%32) in a userscript (DLT) but when this was turned into a bookmarklet and dragged into Chrome, the debugger showed it had become (i2), causing the script to error with "i2 is not defined". Changing the code to (i % 32) worked around the problem. // TODO: All links with using dummy=random should change the value on mouseover/mousemove/click, so they can be re-used live without refreshing the page. // Static bookmarklets could timeout and re-build after ... 10 seconds? ^^ // Most people will NOT want the NoCache version. It's only useful for script developers. // Firefox/Greasemonkey does not like to install scripts ending ".user.js?dummy=123" // But in Chrome it is a useful way to prevent the script from being cached when you are developing it. var inGoogleChrome = window && window.navigator && window.navigator.vendor.match(/Google/); // It doesn't make much sense for me to make it browser-dependent, because I share my bookmarks between Chrome and Firefox (using XMarks). var preventBrowserFromCachingBookmarklets = inGoogleChrome; //var preventBrowserFromCachingBookmarklets = true; // Sometimes Chrome refuses to acknowledge that a script has been updated, and repeatedly installs an old version from its cache! var preventCachingOfInstallScripts = inGoogleChrome; // BUG: Chrome sometimes installs a new instance of an extension for each click, rather than overwriting (upgrading) the old. However disabling preventBrowserFromCachingBookmarklets does not fix that. It may have been the name "Wikimedia+"? var addGreasemonkeyLibToBookmarklets = true; // If enabled, as well as *.user.js files, it will also offer bookmarklets for *.js files var activateOnAllJavascriptFiles = false; // DONE: All bookmarklets optionally preload the Fallback GMAPI. // DONE: All bookmarklets optionally load in non-caching fashion (for changing scripts). // DONE: Use onload event to ensure prerequisite scripts are loaded before dependent scripts. // DONE via FBGMAPI: We could provide neat catches for GM_ API commands so they won't fail entirely. // TODO: Provide extra feature, which allows the Bookmarks to actually trigger // the userscript properly-running inside Greasemonkey, if this userscript is // present to handle the request, otherwise (with warning) load outside GM. // TODO: Support @include/@excude and @require meta rules? // This requires parsing the script's header using XHR before creating each bookmarklet. // DONE: Optionally create static bookmarklet, with all code inline, rather than loaded from a URL. // // comments will need to be removed or converted to /*...*/ comments var addDateToStaticBookmarklets = true; var defaultScripts = []; var includeGMCompat = addGreasemonkeyLibToBookmarklets; if (includeGMCompat) { // defaultScripts.push("http://hwi.ath.cx/code/other/gm_scripts/fallbackgmapi/fallbackgmapi.user.js"); // defaultScripts.push("//neuralyte.org/~joey/gm_scripts/fallbackgmapi/fallbackgmapi.user.js"); defaultScripts.push("//joeytwiddle.github.io/code/other/gm_scripts/fallbackgmapi/fallbackgmapi.user.js"); } function buildLiveBookmarklet(url) { var neverCache = preventBrowserFromCachingBookmarklets; var scriptsToLoad = defaultScripts.slice(0); // The bookmarklet should load scripts using the same protocol as the page. Otherwise browsers may give error messages about "mixed content", and refuse to load the script. url = url.replace(/^http[s]*:[/][/]/, "//"); scriptsToLoad.push(url); var neverCacheStr = ( neverCache ? "+'?dummy='+new Date().getTime()" : "" ); /* var toRun = "(function(){\n"; for (var i=0;i or // However since we are commonly reading the description, sans seems better. var displayDiv = document.createElement("div"); displayDiv.style.fontSize = '0.8em'; displayDiv.style.whiteSpace = "pre-wrap"; displayDiv.style.height = "100%"; displayDiv.style.overflow = "auto"; var displayCode = document.createElement("pre"); displayCode.textContent = res.responseText; //displayCode.style.maxHeight = "100%"; //displayCode.style.overflow = "auto"; displayDiv.appendChild(displayCode); while (frame.firstChild) { frame.removeChild(frame.firstChild); } frame.appendChild(displayDiv); if (typeof Rainbow != null) { /* // Works fine in Chrome, but in Firefox it causes Rainbow to fail with "too much recursion". Rainbow.extend('javascript', [ { 'name': 'importantcomment', 'pattern': /(\/\/|\#) @(name|description|include) [\s\S]*?$/gm }, ], false); */ setTimeout(function(){ displayCode.setAttribute('data-language', "javascript"); displayCode.style.fontSize = '100%'; Rainbow.color(displayCode.parentNode, function(){ console.log("Rainbow finished."); }); },50); } // frame.addEventListener("mouseout",cleanup,false); // newLink.title = res.responseText; var lines = res.responseText.split("\n"); for (var i=0;i=97 && c<=122) { c = 65 + (c - 97); words[i] = String.fromCharCode(c) + words[i].substring(1); } } } name = words.join(" "); } else { // It's just a Javascript file name = "Load "+name; } return name; } var links = document.getElementsByTagName("A"); //// We used to process backwards (for less height recalculation). //// But this was messing up maxStaticsToRequest. //// But now backwards processing is restored, to avoid producing multiple bookmarks! for (var i=links.length;i--;) { //for (var i=0;i