javascript: call an embedded function from a GM script - javascript

On a webpage there's
<script>
function fn982734()
{
// some code
}
</script>
In my Greasemonkey script, I have the following code:
var fn = fields[5].getElementsByTagName("a")[0].getAttribute('onclick').substr(7,11);
console.log(fn); // outputs fn982734 to the firebug console
window[fn]();
This code does not work, and spawns an error in the error console: window[fn] is not a function. However, typing directly into firebug:
var fn = 'fn982734';
window[fn]();
works perfectly. What's going on?

The Greasemonkey script is inside a sandbox and Firebug is not.
See: "Avoid Common Pitfalls" (in Greasemonkey).
Your GM script would access that function via unsafeWindow. Like so:
unsafeWindow.fn982734();
.
Alternatively,
var fn = 'fn982734';
unsafeWindow[fn]();
Also works -- from inside the Greasemonkey script.

I realise that I'm a little late to this question but Please do not encourage the use of unsafeWindow - it is named unsafe for a reason.
The correct alternative would be to use the "location hack" as described on Greasemonkey's Greasepot Wiki. This code should correctly call the function described in the original post:
location.href = "javascript:void(fn982734())";

Related

How to set a breakpoint in standard/native JavaScript functions?

Can I set a breakpoint on a standard JavaScript function? For example, can I pause the debugger every time context.beginPath() is called? Or every time that String.replace() is called?
UPDATE: What I meant by standard JavaScript function is functions built-in into the JavaScript engines.
Yes you can do this by overriding the original functionality by performing the following two steps:
Make a copy(reference really) of the original function:
mylog = console.log;
Override the original with your copy inserting the debugger statement:
console.log = function(){
debugger;
mylog.apply(this, arguments);
}
Now when called console.log will perform a breakpoint. (Note you'll have to handle different function arguments differently depending on the function be overriden)
Here is another example using an instance methods, for example String.prototype.replace:
let originalFunction = String.prototype.replace;
String.prototype.replace = function(...args) {
debugger;
return originalFunction.call(this, ...args);
}
console.log('foo bar baz'.replace('bar', 'BAR'));
Are you looking for the debugger statement?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger
There are 3 ways to set up a breakpoint and debug the code.
1. Chrome dev-tools / Firebug:
Using Chrome developer tools or firebug to locate the line of
JavaScript, then set the breakpoint with the mouse. In chrome, you
should first open(ctrl+shirt+I) to open developer tools.
Select the script tab or click on (ctrl+P) to open then desired file.
Search the line on which you wanted to set a breakpoint and set a
breakpoint.
Whenever you execute your code next time in a browser, the breakpoint
is fired. In watch section, you may see every expression, all
variables in scope, and the call stack too.
2. Debugger
Using debugger statement, it fires every time and it helps when it
hard to find the execution of code.
debugger;
3. Webstorm IDE / Visual Studio Code
Webstorm IDE/Visual Studio Code have the facility to debug a code from
IDE.
Javascript is a really flexible language and probably following the way to override existing javascript and debug method then please use following a way of debugging.
var fnSetAttribute = Element.prototype.setAttribute;
Element.prototype.setAttribute = function(name, value) {
if (name == 'clone') {
debugger; /* break if script sets the 'clone' attribute */
}
fnSetAttribute.call(this,name,value); /* call original function to
ensure those other attributes are set correctly */
};
For more reference please review https://alistapart.com/article/advanced-debugging-with-javascript
Works in Google Chrome Console:
debug(console.log) // sets a breakpoint on "console.log" builtin
console.log("Hello")
It shows the Sources pane and says
🛈 Paused on debugged function

Call a page-specific function on an opened page

In a Firefox extension I am currently developing using the addon builder, I open a page in a new tab and I would like to call a JS function defined in a script on this page. For this I use this code:
var toOpenTab = require("tabs");
toOpenTab.on('open', function(tab){
toOpenTab.on('ready', function(tab){
tab.attach({
contentScript:
"function showFile(){PageSpecificFunction()};window.onload=showFile();"
});
});
});
I implement the window.onload event to be sure that the script containing the PageSpecificFunction() definition is loaded in the page, even though I don't think it is necessary (because I use the toOpenTab.onReady event).
The problem is: PageSpecificFunction() is not defined. I know the function is correctly defined and works fine because I can call it in the firebug console and it works perfectly.
Is there a way to make my extension call this function once my page is opened ?
You need to use the global unsafeWindow object:
unsafeWindow.PageSpecificFunction();
However this is a security risk

I have function but in firebug console it says its not a function where I am calling it?

I am using a function in two sites but when I want to implement it to third site it does not work. When I look into firebug console it says its not a function. My function is in a separate file called profilter.js look like this:
jQuery.fn.sfProductFilter = function (options) {
options = options || {};
return this.each(function () {
var pf = new SFProductFilter(this, options)
})
}
and I am calling it from a page and code is:
$(document).ready(function(){
console.log($("ul.productSmall"));
$('ul.productSmall').sfProductFilter(); //says not a function.
});
I have checked through console.log followings
1- jQuery is included already
2- If I console.log from the js file it works but inside any code block it does not
3- ul.productSmall shows right results in console.log
I can provide link of site but just not providing it so moderator wont thinks its a spam.
I have struggled a lot please let me know where I am making mistake?
(Copied from comment above.)
You are including jQuery twice, the second load happens far below the inclusion of profilter.js and destroys your custom function.
Are you including the jquery ui script? Looks like .button() is called in
function myChecks(){
$("#checkboxcontainer input[type='checkbox']").button();
}
I have a hunch this will do the trick.

Call JavaScript function on a page automatically with Chrome?

When I load a particular webpage, I'd like to call a Javascript function that exists within their page. I could use a bookmarklet with javascript:TheFunction();, but I'd like to know if there's an easier way to do it, either with a Chrome extension or otherwise.
With chrome, you can either install a grease monkey script directly or get the Blank Canvas script handler plugin (the latter of which I use).
Chrome extensions run in a sandbox so you cannot call a function directly from the webpage code how you want. you either have to use javascript:fuction(); and set document.location, or you can create script elements on the page with a callback to your own extension. check out how this guy did it:
https://convore.com/kynetx/kbx-writing-durable-code/
i am refering to this post, and the one above and below it specifically
var anewscript = document.createElement("script");
anewscript.type = 'text/javascript';
anewscript.innerHTML=' callback_tmp= function (mydata){ ' +
' document.getElementById("someElement").onclick(mydata);' +
'}';
document.getElementsByTagName("head")[0].appendChild(anewscript);
An alternative option is to modify the javascript function to make it globally accessible from the [Chrome] debug console.
Change the function from for example
function foo(data)
to
foo = function(data)
then using the debug console, call the method with the attributes required
data = {my: "data"}
foo(data)

Javascript error

I'm getting a JS error on displaying a page: Nothing concrete is specified but the line where it seems to be thrown. When looking into the source code of the page, I see the error is thrown inside the following script, but I can't understand why! It's only about loading images!
<SCRIPT language=JavaScript>
<!--
function newImage(arg) {
var rslt = new Image();
rslt.src = arg;
return rslt;
}
function changeImages(a, b) {
a.src = b;
}
newImage("\/_layouts\/images\/icon1.gif");
newImage("\/_layouts\/images\/icon2.gif");
// -->
</SCRIPT>
The error I am getting is when clicking on a drop down context menu on a page, for this line:
newImage("\/_layouts\/images\/icon1.gif");
The object doesn't accept this property or method
Code: 0
I really don't see what could happen... Any tips on what may be happening here?
Have you tried loading your scripts into a JS debugger such as Aptana or Firefox plugin like Firebug?
Why are you escaping the forward slashes. That's not necessary. The two lines should be:
newImage("/_layouts/images/icon1.gif");
newImage("/_layouts/images/icon2.gif");
It is hard to answer your question with the limited information provided:
You are not showing the complete script
You never said what the exact error message is, or even what browser is giving the error.
Which line number is the error supposedly coming from?
I'd recommend using Firebug in firefox for debugging javascript if you aren't already. IE tends to give bogus line numbers.
And as others have already said, the language attribute for script tags is deprecated.
Write proper xml with the " around attributes.
<script type="text/javascript">
function newImage(arg) {
var rslt = new Image();
rslt.src = arg;
return rslt;
}
function changeImages(a, b) {
a.src = b;
}
newImage("/_layouts/images/icon1.gif");
newImage("/_layouts/images/icon2.gif");
</script>
should your script block not be:
<script type="text/javascript">
?
For starters, start your script block with
<script type="text/javascript">
Not
<script language=JavaScript>
That's probably not the root of your problem, but since we can't see your script, that's about all we can offer.
You probably need to enlist the help of a Javascript debugger. I've never figured out how to make the various debuggers for IE work, so I can't help you if you're using IE.
If you're using Firefox or you CAN use Firefox, make sure you have a Tools / Javascript Debugger command. (If you don't, reinstall it and be sure to enable that option.) Next, open up the debugger, rerun the problem page, and see what comes up.
How are you calling changeImages? It looks as though you are not saving a reference to the images returned by newImage. You probably want to save the results of newImage and pass that to the changeImages routine. Then changeImages should look like this:
function changeImages(a, b) {
a.src = b.src;
}
You also may want to ensure that the images have finished loading before calling changeImages.
You've posted the routine that throws the error, without posting the error or showing us how you are calling it. If none of the answers posted fix your problem then please post some detail about how you are calling the method, which specific line the error is on, and what the error message is.
You firebug to debug.
http://www.mozilla.com/en-US/products/download.html?product=firefox-3.0.10&os=win&lang=en-US
https://addons.mozilla.org/en-US/firefox/addon/1843
JSLint is also a nice resource.
http://www.jslint.com/
Using CDATA instead of the <!-- // -->
http://www.w3schools.com/XML/xml_cdata.asp
<script type="text/javascript">
<![CDATA[
]]>
</script>

Categories