How do I include a remote javascript file in a Greasemonkey script? - javascript

I'm trying to write a Greasemonkey script, and would like to use the jQuery library to do so, but I'm not quite sure how I would include jQuery from a web address to get rolling.
How would I include jQuery (from Google's web server) into the greasemonkey script so that I can just go:
$(document).ready(function(){
// Greasemonkey stuff here
});
I'd prefer to get it from this source:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
Update: Thanks for the help, the answers were very informative. I did, however, utilize my GoogleFu a little more and came across this solution: http://joanpiedra.com/jquery/greasemonkey/
Works like a charm.. just update the source to google's hosted version of jQuery to complete.

The recommended way in recent versions of greasemonkey is to use the #require comment tag.
E.g.
// ==UserScript==
// #name Hello jQuery
// #namespace http://www.example.com/
// #description jQuery test script
// #include *
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
// ==/UserScript==
However... be aware that jQuery 1.4.1 and 1.4.2 are incompatible with this method
Thanks Paul Tarjan, for pointing this out. See jQuery forum thread.
Also be aware of these #require semantics
At the time that the user script is installed, Greasemonkey will download and keep a locally cached copy of the remote file that can be read almost instantly. The cached copy is kept in the same folder as your installed user-script. The remote file is not monitored for changes.
Please be aware that, at the time of writing this answer, this #require tag is only read at install-time. If you edit an existing user script to add this tag, it will be ignored. You need to uninstall and re-install your user script to pick up the change.

From here:
// ==UserScript==
// #name jQueryTest
// #namespace http://www.example.com/
// #include *
// ==/UserScript==
// Add jQuery
var GM_JQ = document.createElement('script');
GM_JQ.src = 'http://jquery.com/src/jquery-latest.js';
GM_JQ.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);
// Check if jQuery's loaded
function GM_wait() {
if(typeof unsafeWindow.jQuery == 'undefined')
{ window.setTimeout(GM_wait,100); }
else { $ = unsafeWindow.jQuery; letsJQuery(); }
}
GM_wait();
// All your GM code must be inside this function
function letsJQuery() {
alert($); // check if the dollar (jquery) function works
// the next call fails
$("<div id='example' class='flora' title='This is my title'>I'm in
a dialog!</div>").dialog({
buttons: {
"Ok": function() {
alert("Ok");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
}
It works perfectly, but you may want to limit the sites it runs on or host the jQuery js file on your own site so as not to steal their bandwidth.

You could try dynamically creating a script element:
var script = document.createElement("script");
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js";
document.getElementsByTagName("head")[0].appendChild(script);
You may need to delay for a bit while the script loads (setTimeout?)

Based on Chris's answer, I adjust to my own needs like following.
// ==UserScript==
// #description require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.jss
// #name Baidu Mask
// #namespace http://tampermonkey.net/
// #version 0.1
// #description try to take over the world!
// #author You
// #match https://www.ibm.com/developerworks/cn/opensource/os-cn-greasemonkey/index.html
// #match *://www.baidu.com/*
// #match *://baike.baidu.com/*
// #match *://zhidao.baidu.com/*
// #match *://www.weather.com.cn/*
// #grant none
// ==/UserScript==
(function () {
'use strict';
// Your code here...
var $j;
function GM_wait() {
if (typeof jQuery === 'undefined') {
window.setTimeout(GM_wait, 100);
}
else {
$j = jQuery.noConflict();
doJob();
}
}
function loadJquery() {
// Check if jQuery's loaded
if (typeof jQuery === 'undefined') {
// Add jQuery
var GM_JQ = document.createElement('script');
GM_JQ.src = 'https://code.jquery.com/jquery-1.12.4.min.js';
GM_JQ.type = 'text/javascript';
GM_JQ.id = 'jquery-lyz';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);
GM_wait();
} else {
doJob();
}
}
loadJquery();
function doJob() {
if (typeof $j === 'undefined') {
$j = $;
}
var url_arr = [
{'name': "baidu", 'value': "www.baidu.com"},
{'name': "baike", 'value': "baike.baidu.com"},
{'name': "zhidao", 'value': "zhidao.baidu.com"},
{'name': "weather", 'value': "http://www.weather.com.cn"},
];
var url = location.href;
var siteObj = {};
$j(url_arr).each(function (i, item) {
if (url.indexOf(item.value) > -1) {
siteObj = item;
return false;
}
});
var delay_arr = [];
var timerCount = 1;
function hideTimer() {
timerCount++;
if (timerCount > 20) {
return;
}
delay_arr = $j.grep(delay_arr, function (_selector, i) {
var $ele = $j(_selector);
var visible = $ele.is(':visible');
console.log($ele, visible);
if (visible) {
$ele.hide();
return false;
}
return true; // keep the element in the array
});
if (delay_arr.length > 0) {
setTimeout(hideTimer, 500);
}
}
setTimeout(hideTimer, 500);
var $frms;
switch (siteObj.name) {
case 'baidu':
$j('#content_right').hide();
break;
case 'baike':
$j('.topA, .lemmaWgt-promotion-slide, .union-content, .right-ad, .lemmaWgt-promotion-vbaike, .nav-menu').hide();
delay_arr.push('#side_box_unionAd');
break;
case 'zhidao':
$j('.widget-new-graphic, #union-asplu, .jump-top-box').hide();
delay_arr.push('.wgt-daily');
delay_arr.push('.shop-entrance');
delay_arr.push('.cms-slide');
delay_arr.push('.nav-menu');
$frms = $j('iframe');
$frms.hide();
break;
case 'weather':
$j('.right, .hdImgs, .tq_zx, #di_tan, #zu_dui').hide();
//delay_arr.push('.wgt-daily');
$frms = $j('iframe');
$frms.hide();
break;
}
}
})();
My script need to work on different sites, while some has jquery included and some not, so I have to test out. The "require" way not work here.

Related

I am trying to write a web replace tampermonkey script,but it dosen't work on the second website. What mistake I made in my script?

I wrote a tampermonkey script to redirect some website to another ,but everytime the second target website won't work ,I had changed the target website twice but it still don't work.So I think it may be some mistake or bug in my script .
here is my code,but on the pixiv it didn't work.Can anybody help me?
// ==UserScript==
// #name New sf
// #namespace http://tampermonkey.net/
// #version 0.1
// #description try to take over the world!
// #author You
// #match *://*/*
// #icon none
// #grant none
// ==/UserScript==
var url = window.location.host;
if (url.match("//krunker.io") === null) {
url = window.location.href;
if (url.match("//krunker.io") !== null){
url = url.replace("//krunker.io", "//youtube.com");
}
else {
return;
}
}
else if (url.match("//www.pixiv.net") === null ) {
url = window.location.href;
if (url.match() !==null) {
url= url.replace("//www.pixiv.net","//youtube.com");
}
else {
return;
}
}
console.log(url);
window.location.replace(url);
Is there anywrong with my script?
if there is some master pleace answer me,thank you so much

How do I replace unsafeWindow when migrating a pre-Firefox 30 Greasemonkey script to GM4+?

I'm trying to get a reference to the version of jQuery that exists on my webpage in a Greasemonkey script that worked until Firefox 30. In comments below my definition are the two other references I could find, but I just get ReferenceError: $ is not defined or ReferenceError: jQuery is not defined when I try to access jQuery on the window object.
var $ = unsafeWindow.jQuery;
//var jQuery = window.jQuery; // From https://stackoverflow.com/questions/24802606/binding-to-an-event-of-the-unsafewindow-in-firefox-30-with-greasemonkey-2-0
//var jQuery = $ || window.wrappedJSObject.$; // https://github.com/greasemonkey/greasemonkey/issues/2700#issuecomment-345538182
function addAccountNameToTitle(jNode) {
$('title').text(session.name + " | " + $('title').text());
}
waitForKeyElements (".page-breadcrumb", addAccountNameToTitle, false);
/*--- waitForKeyElements(): A handy, utility function that
does what it says.
*/
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) {
/*--- 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.
actionFunction (jThis);
jThis.data ('alreadyFound', true);
}
} );
btargetsFound = 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
);
},
500
);
controlObj [controlKey] = timeControl;
}
}
waitForKeyElements.controlObj = controlObj;
}
I'm using FF 59.0.2 and Greasemonkey 4.3
unsafeWindow.jQuery was never a good idea and rarely worked. Also, see Error: Permission denied to access property 'handler'.
The smart thing to do with the question code is to use #require, like so:
// ==UserScript==
// #name _Changing the title text on some page.
// #match *://YOUR_SERVER.COM/YOUR_PATH/*
// #require https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// #require https://gist.github.com/raw/2625891/waitForKeyElements.js
// #grant GM_addStyle
// #grant GM.getValue
// ==/UserScript==
//- The #grant directives are needed to restore the proper sandbox.
waitForKeyElements (".page-breadcrumb", addAccountNameToTitle);
function addAccountNameToTitle (jNode) {
$('title').text (session.name + " | " + $('title').text() );
}
Advantages:
Short, simple, and clear.
Not vulnerable to side effects from changing javascripts on target page. Especially, if the target page changes jQuery versions.
Uses speedy, local versions of jQuery and waitForKeyElements. They are stored on the local disk and often cached in memory. No server fetches nor delays.
Note: if session is a target page global variable, you may need to access it like unsafeWindow.session.name. See: How to access `window` (Target page) objects when #grant values are set?.
You state that you want to use the page's jQuery instance or version. There is seldom a good reason to do that. And the code, shown in this question, certainly wouldn't benefit from that.
But, if your userscript doesn't use any GM functions, you can do that via #grant none mode like:
// ==UserScript==
// #name _Changing the title text on some page.
// #match *://YOUR_SERVER.COM/YOUR_PATH/*
// #require https://gist.github.com/raw/2625891/waitForKeyElements.js
// #grant none
// ==/UserScript==
waitForKeyElements (".page-breadcrumb", addAccountNameToTitle);
function addAccountNameToTitle (jNode) {
$('title').text (session.name + " | " + $('title').text() );
}

Intercept and alter a site's javascript using greasemonkey

Suppose there is a site that includes an external .js file in an html script tag like so:
<script src="somescript.js">
I want greasemonkey to intercept each of such scripts, and alter some of the values in them before they execute. For example, I want to change all occurrences of the value "400" to "300" within them, then continue to load the page as if the scripts used those values instead of the original ones. Currently I'm using the following code in greasemonkey:
function replaceTargetJavascript (scriptNode) {
var scriptSrc = scriptNode.textContent;
scriptSrc = scriptSrc.replace (
/'400'/,
"'300'"
);
addJS_Node (scriptSrc);
}
document.addEventListener("beforescriptexecute", function(e) {
checkForBadJavascripts ( [
[false, /'400'/, replaceTargetJavascript]
] );
}, true);
Which according to my sources is the right way to do it, but it is not working. Can anyone please help me figure this out?
Old question, but I needed to do this recently.
Here's how I did it using GreaseMonkey.
You add the beforescriptexecute listener, and wait for your target script to be loaded, checking the src tag to identify the correct script.
Then you stop that script from loading and get the script source yourself using GM_xmlhttpRequest.
Then you are free to modify the script as you please and insert it back into the DOM.
// ==UserScript==
// #name Test
// #namespace Test
// #description TEST
// #include http://the.website.com/*
// #version 1
// #grant GM_xmlhttpRequest
// #run-at document-start
// ==/UserScript==
function addScript(text) {
text = text.replace(/replaceThis();/g, "");
var newScript = document.createElement('script');
newScript.type = "text/javascript";
newScript.textContent = text;
var head = document.getElementsByTagName('head')[0];
head.appendChild(newScript);
}
window.addEventListener('beforescriptexecute', function(e) {
src = e.target.src;
if (src.search(/script_to_modify\.js/) != -1) {
e.preventDefault();
e.stopPropagation();
GM_xmlhttpRequest({
method: "GET",
url: e.target.src,
onload: function(response) {
addScript(response.responseText);
}
});
}
});

How can I block remove or stop anonymous functions in jquery with Greasemonkey

How can block the following jquery function.
I've test different scripts and own scripts but noting works.
$(document).ready(function () {
$(window).on('beforeunload', function() {
return "\
Are you sure you want to leave this page....";
});
});
#
Sorry but both scripts don't stop the leave dialog
// ==UserScript==
// #name Test
// #namespace
// #description Disable - remove the annoying onbeforeunload event
// #include *
// #author test
// ==/UserScript==
(function() {
unsafeWindow.onbeforeunload = null;
unsafeWindow.onunload = null;
//unsafeWindow.alert = null;
//unsafeWindow.confirm = null;
//unsafeWindow.prompt = null;
//unsafeWindow.open = null;
//$(window).off('beforeunload'); //don't work
$(window).on('beforeunload',function() {/* override function that does nothing*/});
})();
I believe off is what you're looking for:
$(window).off('beforeunload');

Loading external scripts with Userscript works with Fx 4, but fails in Fx 3.6

Here's the code, not abridged (it's shortish):
// ==UserScript==
// #name Manga ChapterReader
// #license MIT/X11 + Attribution (passcod)
// #namespace http://www.mangareader.net
// #include http://www.mangareader.net/*
// #description Displays full chapters from MangaReader.net in a simpler interface.
// #author passcod
// #version 10.331
// ==/UserScript==
// version format: y.z
function START(array_of_scripts_to_load, callback) {
document.documentElement.innerHTML = '<head></head><body></body>';
for ( i in array_of_scripts_to_load) {
var script = document.createElement('script');
script.src = array_of_scripts_to_load[i];
var evl = new Object();
evl.handleEvent = function (e) {
callback();
};
script.addEventListener('load', evl, true);
document.getElementsByTagName('head')[0].appendChild(script);
}
}
var regular = /mangareader\.net\/[a-z0-9\-]+\/[0-9]+(\/.+)?/i, old = /mangareader\.net\/[0-9\-]+\/([a-z0-9\-]+)\/chapter-([0-9]+)\.htm/i;
if ( regular.test(window.location) ) {
//START(['http://lib/libstore/jquery.js','http://scrap.book/userscripts/mangareader/index.js'],
START(['http://code.jquery.com/jquery-1.4.2.min.js','https://bitbucket.org/passcod/scrap.book/raw/tip/userscripts/mangareader/index.js'],
function() {
$$$();
});
}
else if ( old.test(window.location) ) {
var parts = old.exec(window.location);
window.location = 'http://www.mangareader.net/'+parts[1]+'/'+parts[2];
}
This works perfectly in Firefox 4.0b7 (Windows) and nightly (Linux), but it fails with Fx 3.6.x (Reports from 3.6, 3.6.2, and 3.6.12).
I can't see why.
Oh, wait... I use Scriptish on Fx 4... maybe this has to do with something?
But apart from that, I'm totally at loss. The scripts don't get loaded. It even looks like the document.documentElement.innerHTML = '...' line doesn't work... did it in Firebug and it erases the document to <html></html>, but nothing more happens afterward.
Any ideas?
I fixed this by changing the loaded scripts to execute immediately:
(function () { /* ... */ })();
and then removing the callbacks.
There was no problem with the browser, but in the reaction time. For some reason, the userscript finished too early in Fx 4.

Categories

Resources