Calling Content Script function on chrome.browserAction.onClicked - javascript

My question is fairly simple and I just want to figure out the easiest way to do this.
The current iteration of my chrome extension injects a DIV into the webpage with a button, which, when pressed, will execute a function.
I want to do this without injecting DIVs, by executing a function within one of my content scripts when the browser button is pressed in the toolbar. What's the simplest way to go about this? I believe I have to use the background page, and the only thing I see in documentation is registering some listening events on both ends. If this is the only/simplest way, how do I go about doing this?

Yes, contacting a content script from a browser or page action button is done using messages sent back and forth between the background script and the content script(s)
First step: Tell the background script what to do on browserAction/pageAction button click
chrome.browserAction.onClicked.addListener(function(tab) {
...
});
Step 2: Inside the browserAction.onClicked event listener you can then send a message to the content script (in fact to any code listening!):
chrome.tabs.sendMessage(tab.id, {<YOURMESSAGEPAYLOAD>});
Step 3: Inside the content script, you add a listener for incoming messages
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
// request contains the YOURMESSAGEPAYLOAD sent above as a Javascript object literal
});
You can also go the other way round and send messages from the content script to the background script by using the following inside the content script
chrome.runtime.sendMessage({<YOURMESSAGEPAYLOAD>});
and then use the onMessage listener inside the background script the same way as mentioned above.

devnull69 is correct, you need to use message passing. Also consider checking out chromeps. It's a small pubsub library I wrote for chrome extensions. Removes a lot of the overhead when writing message passing code.

Related

dynamicaly change an element if it is changed by a different script

I am writing a script that modifies the content on a page. The content is generated from a different script that I am unable to modify. My code works fine when the page is initially loaded. But when the user clicks a link (which causes the other script to run) then all my content modifications are lost. I am able to catch the event that causes the change by using $(a.pagination_button).on("click",function(){ code }) But whatever code I put in is not having any effect. It seems the other script is running after my .on function. What can I do to make my code execute after the other script so that my changes will be seen by the user?
Just listen on the document for clicks:
$(document).on("click","a.pagination_button",function() {
alert("exec code");
});

Find script what sets button on focus

On a Drupal page a button element gets focused before the page has been loaded completely.
I'm trying to locate where this happens but unfortunately I wasn't able to track down the script. I'm using Chrome and tried to set a break-point but no luck. Further I tried to locate the line where this happens with the profiler. Also no luck so far. Do anyone know how to debug this properly? Any help is much appreciated. Thanks.
When I replace with a div, the issue is gone, so its related to the button element itself (no class nor element id)
What you want to do is right-click on the element you think is going to trigger the event and on the context menu click inspect. The chrome developer bar will open and you should see the html tag for that element you clicked on. On this bar there are two section: one with html tags and the others with tabs named Style, Computed, Event Listeners, DOM Breakpoints and Properties.
The one you want is Event Listeners, so click on that tab. Now we see all the listener for that html element grouped event type. When open a group you should see the list of element on left with a link to that specific line of code for the event handler. If you click on the link, you will be switch to the file where the code is.
Now the hard part. As you will see in some web pages, there are a lot of handlers. Also the use of libraries like JQuery make it harder to find the piece of code that really does something and the code is probably minified.
So let's supposed you found the code that you want to debug. Often it's in a format like
var namespace = {
...
handler: function(event) {
/* Event handler code here */
},
...
In a case like that, this might work
(function () {
var old_handler = namespace.handler;
namespace.handler = function () {
debugger; // this make a breakpoint here and stops
old_handler.apply(this, arguments);
}
})();
When all fails, make a local copy of the file that contains the code and setup an Apache server so that you proxy the web site except for that file which you will reference locally. Then you can modify it however you like. This won't work on https web site.

Detect changes on the url

I need something to detect changes on the url but the page doesn't do post back, it changes dynamically adding just the div inside the html, so the URL page is something like this
http://www.examplepage/conversations/44455
and when I click on another section of the page it it is
http://www.examplepage/conversations/44874
it changes not only at the end but like this
http://www.examplepage/settings
without doing post back and reloading the javascript so my question is, is there a way to detect those changes? and event listener but how?
I search and everyone says hash event but I don't have any value after any hash so it doesn't work
EDIT
Just for the record I have no code of the page nor I have access, I'll explain better, I am doing a background google extension and I just added a slide out to an existing page, this page changes its url the way I explained above. the url changes like every page does, but they change the div inside the html so that the page doesn't have to charge everything again
You need to store the URL when the page loads as a starting point and setInterval to check for changes and modify based on that.
The following code does this check twice a second (500ms):
// store url on load
let currentPage = location.href;
// listen for changes
setInterval(function()
{
if (currentPage != location.href)
{
// page has changed, set new page as 'current'
currentPage = location.href;
// do your thing..
}
}, 500);
There is no "clean", event-based way to detect such URL changes from a content script.
They are done with history.pushState API - and using that API doesn't emit any DOM event.
Two possible indirect event-based approaches, besides the already mentioned poll-based one:
An extension can override history.pushState with an injected script to additionally emit a DOM event that can be listened to in a content script.
This approach is described in detail here.
The downside is that, depending on the code of the page in question, the injected script may need to be injected early, needing run_at: document_start which is suboptimal for page load performance.
Use a background page that listens to chrome.webNavigation.onHistoryStateUpdated event.
If you need to detect this in a background page — perfect,
you're done, without ever needing a content script.
If you need to detect this in a content script, you can use details.tabId in the event listener to send a message to the right content script.

Stop script in dynamically loaded content

at the moment I am working on replacing pop-up on a website I inherited. Those pop-ups used modal dialogs, which are on their way out and even were dropped by pop-up blockers on client side.
My approach was loading the HTML of the pop-up into an div on the main site, while hiding the original content, then emptying the div and switch the main content back to visible.
This works so fa, but the loaded content has scripts that run to check if someone is already using that function. The first time you use that function all is fine. The script runs, sees noone is using the function, I go through the stuff, empty the div and return to the main content. When trying to use the function a second time the script to still run (console shows the requests), even though I emptied the div, prompting the eternal "please wait till other user is finished" lines, since the first script is still checking for use, signalling the second script "I'm buisy".
So right now, I am looking for a way to stop the first script, since removing the HTML-content doesn't suffice it seems.
The code so far:
$("#dialog").load("stuffToLoad.htm",function(response, status)
{
if(status=="success"){
$(".fullTable").toggle();
$("#dialog").toggle();
};
})
to get the content. The in-use-check is done with a post-request, that is repeated by a window.setTimeout every second. That part seems to still run.
When everything is done, or the user runs into an error I tried:
function returnToProcVal()
{
$("#dialog").html("");
$("#dialog").toggle();
$(".fullTable").toggle();
}
to delete the function content and scripts, to stop them running. While the DOM says all is gone I can see the post requests being repeated in the console.
I'd be grateful for any pointer or perhaps even better methods to get the function running and returning the user, without the use of pop-ups.

How to access the DOM after a previous JQuery call

I'm not too familiar with JQuery so please be patient.
Essentially, I have two hyperlinks on a view that runs some JQuery script:
Delete</td>
.
.
Undo
So, each of these links access different parts of the same .js file. My "Delete" does some processing which does a soft delete in the database. The DOM loads and this works fine. I'm using firebug and, when I insert a console.log in .js I can see the id of the Customer I want to delete and the rest is straight forward.
$(container).find('a.deleteCustomer:first').click(function(e) {
console.log("CustomerId " + $(container).find('input[name=Customer_CustomerId]:first').val());
My "Undo", however, accesses the same .js on a different line and console.log in the 'undo' part of .js reveals that it's not being hit.
$(container).find('a.undoCustomer').click(function(e) {
console.log("CustomerId " + $(container).find('input[name=Customer_CustomerId]:first').val());
So, it appears that the DOM is not ready (?). If this is the case, how do I fix this? Do I have to reload the DOM manually? If so, how?
P.S. When I click 'Undo' first nothing seems to happen i.e. I don't get any console.logs in FireBug. However, if I refresh the browser, it runs as expected i.e. the undo jquery about executes.
Without the full code, it is difficult to tell. From your post, title and comments, I see two possible causes.
First, you might be running your code before the DOM is fully ready, then try to wrap all your javascript initialization script in:
$(function() {
... // your code here
});
Second, are you deleting the "input" when you click on delete? If this is the case, it would be normal that "find" does not recover it. The solution to have an undo in such case would be to hide the "input" and show it back when clicking "undo".

Categories