BHO render event - javascript

I am developing IE extensions using BHO. Currently I am using OnDocumentComplete event which fires when the page loading is completed. I want to inject my JavaScript while rendering HTML such that I can update HTML on the fly.
Simple example:
I want to replace HREF attribute. But on OnDocumentComplete event user can click the link and can access the actual link. But if he/she waits till the page load complete then he/she will be redirected to the updated link.
Please provide your valuable inputs such that DOM can be updated while rendering.
Thanks,
Maitrey

While page is loading you can use:
<script>
window.onload = function(){
/* DOM handling */
}
</script>
to execute Javascript, is this what you meant?

you can execute your javascript using IHTMLWindow2::execScript called on the window object inside the OnDocumentComplete handler:
public void OnDocumentComplete(object pDisp, ref object URL)
{
HTMLDocument document = (HTMLDocument)webBrowser.Document;
IHTMLWindow2 parentWindow = document.parentWindow;
parentWindow.execScript("alert('your javascript')");
}
where webBrowser is the object of the WebBrowser class that you've set in SetSite

Related

How a page can be determined if it's loaded

I'm going to use postMessage method to send a text to an opened window right after opening the window on ther origin.
I tried the following:
let ref = window.open("<address>", "name", "resizable,scrollbars,status");
ref.postMessage("Some Message");
A listener is defined on the other page to get the posted message, but it doesn't work, since the posted message is being sent before the page loading is completed.
Is there any way to check that the page on the opened window is fully loaded?
You can implement an "handshake" mechanism, so it would be like,
parent adds an event listener to catch child messages (window.addEventListener('message', () => {}))
parent opens child window
child window sends "I'm a live" message to parent (parent.window.opener.postMessage('ImALive', '<url address of parent>'))
parent sends it's data to child
Something like that.
You can try simple Javascript trick as below to see if DOM is loaded, you can use this function which will get execute after DOM gets load.
document.addEventListener('DOMContentLoaded', function(event) {
//alert("hello"); your code
})
Have you tried $(window).load(function(){}).
You can write your code in this event and then try it.
This question on SO might help.

How can I access a newly-opened tab's window object? [in a firefox extension]

I'm attempting to convert a Greasemonky script to an extension for Firefox and I'm trying to make my extension automatically attach a simple script to any webpage when a new tab is opened. I'm converting the script from Greasemonkey because I'd like to take advantage of advanced preferences and menu options.
I access the tab using this:
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", tabAdded, false);
function tabAdded(event) {
var newtabwindow = event.target.____ //I don't know what goes here
//attach script to newtabwindow
}
and my goal is to append the script to the document in the new tab once it loads using this function:
function scriptrunner(targetwindow) {
var myScript = targetwindow.content.document.createElement('script');
myScript.type = 'text/javascript';
myScript.setAttribute('src','chrome://addonname/content/addonscript.js');
targetwindow.content.document.getElementsByTagName('head')[0].appendChild(myScript);
}
This function works fine to attach the script to the current page when attached to a toolbar button with oncommand="scriptrunner(window)", but I don't know how I could access the window in the newly opened tab, or if I should cut out the window from the equation and access the document another way.
You are looking for contentWindow, which is a property of the browser element.
Given a tab, call gBrowser.getBrowserForTab to acquire the browser element associated with the tab. Then access either contentDocument or contentWindow property of the browser element (these are equivalent to the document and window objects you should already be familiar with).
Also -- if I'm not mistaken -- you'll need to listen for the "load" event of the contentWindow in addition to listening to events for the tab.

Which XUL element to use when a url is entered and loaded for calling JS?

I am developing a Firefox add-on using XUL Overlay and want to call a specific js when the current page loads after entering the URL. I want to know which XUL element would be affected and should be used to call said JS, such as page or tab or window or ??? Also, which event would be best for the element? Or is my logic wrong?
Also,the js's function is to record tab title and/or url so i need to know when to call js and with corresponding event. Thanks.. :)
The XUL element you should be watching is the tabbrowser. In the browser window (which means also in overlays applied to the browser window) it can be accessed via the global gBrowser variable. If you want to know when a page finishes loading you can listen to the DOMContentLoaded event. Something like this (untested code):
// Declare an own namespace for extension's functions to avoid
// name conflicts with other extensions.
var MyExtension = {};
MyExtension.init = function()
{
gBrowser.addEventListener("DOMContentLoaded", MyExtension.onPageLoad, false);
};
MyExtension.onPageLoad = function(event)
{
// Get the document that loaded
var doc = event.originalTarget;
// Ignore frames that load
if (doc.defaultView != doc.defaultView.parent)
return;
// Ignore if this isn't the active tab
var browser = gBrowser.getBrowserForDocument(doc);
if (browser != gBrowser.selectedBrowser)
return;
alert("Page loaded in current tab: " + doc.defaultView.location.href);
};
// Wait for the browser window to finish loading before adding event listeners
window.addEventListener("load", MyExtension.init, false);
If you want to get notified earlier, when the address displayed in the URL bar changes, you can use a progress listener instead. You want to implement the method onLocationChange of the progress listener and leave the other methods empty. Note that this method is also called when the user switches to a different tab (this also causes a location bar change). Also: the parameter aURI passed to onLocationChange is an nsIURI instance. If you want the URL as a string you should look at aURI.spec.

Communication between firefox extension and page javascript

I am developing a web-based javascript/html application with a sister firefox-extension.
The application's page-javascript performs a few XHR calls immediately after page-load, in order to bring in and display all the content that the page requires.
Is there a way, without polling the DOM, that my extension can know that the page's initialisation procedures are complete?
Interesting question indeed..
I've just found out through this post on MozillaZine's forum an easy way to accomplish this. The technique basically consists in defining a custom DOM element within the web page, filling it with some arbitrary attributes, and then using it as the target of a custom event. The event can than be captured and used to pass values from the webpage to the extension.
Web page (assumes jquery is available)
<script type="text/javascript">
$(document).ready(function(){
$.get("http://mywebsite.net/ajax.php",function(data){
//[...]process data
//define a custom element and append it to the document
var element = document.createElement("MyExtensionDataElement");
element.setAttribute("application_state", "ready");
document.documentElement.appendChild(element);
//create a custom event and dispatch it
// using the custom element as its target
var ev = document.createEvent("Events");
ev.initEvent("MyExtensionEvent", true, false);
element.dispatchEvent(ev);
});
});
</script>
Chrome code:
function myListener(e) {
alert("data:" + e.target.getAttribute("application_state"));
}
function on_specialpage_load(event) {
if (event.originalTarget instanceof HTMLDocument &&
event.originalTarget.location.href == "http://mywebsite.net/myspecialpage.html") {
var doc=event.originalTarget;
doc.addEventListener("MyExtensionEvent", myListener, false, true);
}
}
gBrowser.addEventListener("DOMContentLoaded",on_specialpage_load,false);
Notice that doc.addEventListener has a fourth parameter, indicating that it will accept events coming from untrusted code. However you can add this event listener selectively, so that only trusted pages from your site will be able to pass values to the extension.
You could hook into the XMLHttpRequest object from your extension and monitor the requests, similar to what this GreaseMonkey script does (description). Add a wrapper to onreadystatechange in the same way he's added a wrapper to open which notifies the extension when complete. Probably also want some code which makes sure you're only doing this when visiting your own page.
Firebug does similar stuff for its Net panel, the codebase for that is a bit more intimidating though :) I also had a look at the Firebug Lite watchXHR function, but that code is a bit too cunning for me, if you can work it out let me know.

In XUL, how do I know a browser-tag has finished loading?

I'm developing a firefox extension based on this tutorial which is a FF 2.0 extension (second part of the tutorial is at this url)
The main thing that is important is that it uses
<iframe id="contentview" src="http://www.ibm.com/developerworks/web" flex="2"/>
In the backend code, when clicking the GO button, this happens:
contentview.contentDocument.location.href = urlbox.value;
//Use Firefox XPath to get the raw text of the document
var doctext = contentview.contentDocument.evaluate(
"string(.)", document, null, XPathResult.STRING_TYPE, null).stringValue;
I get an error with the xpath, but that's not my question. The issue I have with FF 3.0 is that the contentDocument value refers to the old site loaded, not to the one loaded by the href-change.
So my question is: how can I create a similar window, but be notified someone when the loaded document is complete, so I can access its DOM?
Updated:
first you need to handle the load event of the window then you add an event listener to the iframe element
window.addEventListener("load",Listen,false);
function Listen()
{
var frame = document.getElementById("contentview");
frame.addEventListener("DOMContentLoaded", DomLoadedEventHandler, true);
}
function DomLoadedEventHandler() {
var frame = document.getElementById("contentview");
alert(frame.contentDocument.location.href);
}
replace "DomLoadedEventHandler" with your event handler name.
I recommend that you take a look at the official site of Mozilla to learn everything about Firefox extensions
http://developer.mozilla.com

Categories