I'm writing a Chrome extension, in my background.html page, it is injecting a js file with this command:
chrome.tabs.executeScript(null, {file: "mod.js"});
All of the code from this file is running on the page just fine, except for one function not being defined for an onclick property.
I am changing the innerHTML of Facebook's main page, the div that contains "top news" and "most recent"
I'm inserting this html:
"<a href='#' onclick='thisIsUndefined()'>
<span class='someClass'>
Better feed
</span>
</a>"
And right in the js file that is injected, thisIsUndefined is perfectly stated as:
function thisIsUndefined () {
alert("is it working yet?");
}
I even have another function in the file that I am using, but whenever I click the link that's inserted, the I get an error saying that it's undefined.
Exact error:
Uncaught ReferenceError: thisIsUndefined is not defined
Here's the whole file for reference:
http://texthmu.com/Devin/HMU%20ext/mod.js
Could you recommend any keywords like 'global' or 'var' that could fix the definition?
Scripts on the page and content scripts are isolated. They interact with the same DOM, but not directly with each other's variables. When you add onclick, it's going to look for that function in the site's scripts. The best way to do it would be to use document.createElement and then use onclick or addEventListener to attach your function. If you want to go the innerHTML route, append it to the DOM first, then find it and attach your event.
http://jsfiddle.net/EjYpQ/
You're a bit out of luck on that one due to Chrome's execution model:
Content scripts execute in a special
environment called an isolated world.
They have access to the DOM of the
page they are injected into, but not
to any JavaScript variables or
functions created by the page. It
looks to each content script as if
there is no other JavaScript executing
on the page it is running on. The same
is true in reverse: JavaScript running
on the page cannot call any functions
or access any variables defined by
content scripts.
(emphasis in bold)
Source: http://code.google.com/chrome/extensions/content_scripts.html#execution-environment
This is the best solution I found:
$("#elementID").click(function() {
myFunc();
});
Related
The picture shows a print screen of right-clicked view source page in Chrome browser. With a search in the full context of source, I only found one reference of method freshPage. I didn't found the definition. So I'm puzzled how the script is executed by the browser, since the freshPage method seems didn't like a builtin Javascript function. I didn't see any other script during the page loading.
How can I mimic the action to get return value of the function?
I realized I had missed the more.js files responded from the server, with the aid of the comments and replies. I found the definition in the file.
There are only two real possibilities:
The freshPage function is provided by a script on the page. That may be a <script src="..."></script> which refers to a separate resource (seems likely), or an inline <script>/*code here*/</script>, or
That call will throw a ReferenceError.
In this case, it's #1: The page loads more.js via this script tag: <script type="text/javascript" src="http://app.vmall.com/js/all/more.js?version=2.9.5.20150418"></script> which declares the function.
How can I mimic the action to get return value of the function?
Just...call it. That can be from a script you inject in the page, a bookmarklet, or the console.
It's not the case here, but note that it's entirely possible to remove a script after it's been executed. For instance:
<script id="foo">
function doSomething() {
// ...
}
setTimeout(function() {
var script = document.getElementById("foo");
script.parentNode.removeChild(script);
}, 0);
</script>
Once the page containing that was loaded, there would be a doSomething function defined at global scope, and no script tag defining it present on the page anymore. ("View source" should show it, but not the live DOM inspector shown in your screenshot.)
But again, the page you linked doesn't do that. The script tag is perfectly easy to find, in both "view source" and the DOM inspector.
I have a existing file ajax,js in my website that makes an ajax request and creates a global JSON object, searchResult using that response. Now I am creating a Chrome plugin, that requires this JSON Object inside it. I have a content script for the plugin viz. plugin.js and I want to include the object inside plugin.js file.
When I try to log window.searchResult from within plugin.js, it shows as undefined.
but when I use browser console, it shows the value as expected.
Please help me with this.
Problem
Chrome content scripts and the page's own scripts live in isolated worlds.
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page.
Your code works in the console, since you execute it by default in the page's context. To see what the extension sees, you need to switch it.
Solution 1a
First, the generic solution (works even if you don't control the webpage)
There is a way around this, by injecting some code directly into the page's "world" (or properly called, context).
After injecting the code, your page-level script needs to communicate with the content script to pass the data. It's possible with custom DOM events (as, as you remember, DOM is shared). The page-level script sends an event with the data in the event's details.
Alternatively, you can just attach the data to some DOM node, say, an invisible <div>.
Solution 1b
Since you said it's your page, you can skip the inject-into-the-page step and have a listener ready in the page's own code.
The content script sends a custom event to request the data, and the page answers passes the data back as described in 1a.
Solution 2
In theory, you don't even need a content script.
You can use the "externally_connectable" mechanism to speak with the page directly.
Note though that the page has to initiate the conversation.
I am trying to create a Chrome extension using CrossRider and am struggling with how to create a global variable.
My extension is essentially going to dynamically append a few JavaScript files to the page if a button is clicked, and I need it to also create a global variable and set some properties.
I tried the following:
appAPI.ready(function($) {
console.log('inside crossrider extension ready()');
window.foobar = 'barfoo';
return;
});
When I refresh the page, the message inside crossrider extension ready() is printed out to the console, so I know the extension is loaded and working, but when I try executing window.foobar or foobar in the console an error is thrown saying it's undefined.
This is my first time creating an extension, so what am I missing here? Why isn't the global variable I create inside of CrossRider's appAPI.ready() function available outside of it?
I can't find a duplicate target, so I'll explain what's happening.
I don't know the Crossrider terminology, but when a Chrome extension executes code in a page, this is called a Content Script.
However, the code does not execute in the same context as the page itself. It's called an isolated world and means, among other things, that the window object is not shared.
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.
So if you want to set a variable accessible to the page, you need to set it in the page context. How? There are many ways, but they all amount to inserting a <script> element into the page.
var script = document.createElement('script');
script.textContent = "window.foobar = 'barfoo';";
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
All of that assumes that you don't control the page in question. If you do, there are other ways of communicating the the page, because DOM is shared. You can, for instance, raise a custom DOM event if the page listens to it.
If I'm loading a script using something like
document.getElementsByTagName("head")[0].appendChild(scriptElement);
…what code can I put inside of that loaded JS file to get the URL of itself?
In other words: I use dom injection to load http://foo.com/foo.js. From within foo.js, how do I get the URL http://foo.com/foo.js?
If you have included the scriptElement object in your dom, then you should know the "scriptElement.src" - so inside foo.js you should know the source:
alert(scriptElement.src);
I've found a solution that works for me here:
javascript - get node reference to script tag that calls a function
The answer that requires you to throw an error in the loaded file, catch it, and then pass it to the global function in the loading page did the trick. (It doesn't work in IE, but for my current project that is not a concern.)
I have already written a Hello World example extension. Now I am trying to write a Chrome extension to get a certain JavaScript variable's value, if it is declared.
So let's say there is a
var test = 'a';
in the source code. I would like to get that a value.
UPDATE: I do not have access to the "original" website's code, but I know that this variable is always there, and has a certain value, always different.
An alert would do. (Can I alert, from the extension's page?)
I saw that there are things like "permission" and "tabs" and I am not sure what might I be missing.
I tried to search, found something similar, but this example just doesn't do anything when I click on the link.
From a content script, you can't have access to a variable declared on the page.
Taken from the documentation:
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page.
The only way I see is to load the script source via XHR in the background page and parse it. Then you may use message passing if you want to send the result to your content script. Note that this solution won't work if the value of the variable has been changed by a subsequent script.
If you have control over that page you could put that value into a hidden HTML element on the page which your extension can then extract with a content script.
on the website:
var test a = 'a';
document.documentElement.dataset["a"] = a;
in the extension's content script:
var a = document.documentElement.dataset["a"];
Just make sure that the content script is executed after the script on the page (e.g. by adding "run_at": "document_end"in your manifest)