Run userscripts on page fetched with GM_xmlhttpRequest

153 views
Skip to first unread message

Kia

unread,
May 12, 2007, 5:23:20 PM5/12/07
to greasemonkey-users

In a script that I'm developing I'm fetching pages in a search result
using GM_xmlhttpRequest. I was wondering if I can make other
userscripts compatible with my script, by automatically run them on
the pages i fetch? Like this (pseudo code):


{

editPage(document); // current document gets edited
myTrigger();

function editPage(doc) {
// I make my modifications to doc
}

function myTrigger() {
// if user press key 'n', inject next page in the search result
var result = getPage(nextPage);
// now, instead of calling this.editPage(result) I would like to
call
// Greasemonkey.run(result);
// that command would call all the userscripts, including this,
on the result
}

}

Henrik Nyh

unread,
May 13, 2007, 4:32:46 AM5/13/07
to greasemon...@googlegroups.com
On 12/05/07, Kia <kia.nis...@gmail.com> wrote:
>
> In a script that I'm developing I'm fetching pages in a search result
> using GM_xmlhttpRequest. I was wondering if I can make other
> userscripts compatible with my script, by automatically run them on
> the pages i fetch?

No, but I suppose you could load the pages into an iframe rather than
use GM_xmlhttpRequest, and manipulate what's inside the iframe.
Cross-domain limitations of frames might be a showstopper though.

Kia Niskavaara

unread,
May 14, 2007, 6:10:24 AM5/14/07
to greasemon...@googlegroups.com

Great idea! I've tried it and it almost works. Except that Greasemonkey doesn't get executed on the
content loaded by the iframe... Maby a Greasemonkey bug?

Kia Niskavaara

unread,
May 14, 2007, 6:36:15 AM5/14/07
to greasemon...@googlegroups.com

Does anyone know how to suppress the "busy"/hourglass cursor that appears when a hidden iframe is
loading?

RodMcguire

unread,
May 14, 2007, 7:13:06 AM5/14/07
to greasemonkey-users
On May 14, 6:10 am, Kia Niskavaara <kia.niskava...@gmail.com> wrote:
> Great idea! I've tried it and it almost works. Except that Greasemonkey doesn't get executed on the
> content loaded by the iframe... Maby a Greasemonkey bug?

It seems that there is some bug that depends on how the IFRAME is
visible/invisible. See this thread

http://groups.google.com/group/greasemonkey-users/browse_frm/thread/7035292e7ef764bb/ffd542e2ec6a352c#ffd542e2ec6a352c

where Mortimer says

"First, let me explain how I do it: I add an iframe to my document,
with dimension 1px, 1px so it's hidden but script in it are still able
to execute (having the iframe with display=none messes with scripts in
the frame apparently)."

Somebody needs to track down this bug and the particulars on how
Greasmonkey doesn't work with IFRAMEs.

I suspect it may be a Firefox bug such that Firefox does not generate
the DOMContentLoaded in certain cases.

Kia Niskavaara

unread,
May 14, 2007, 8:25:32 AM5/14/07
to greasemon...@googlegroups.com

Thanks! It solved my problem.

Kia

Kia Niskavaara

unread,
May 14, 2007, 8:37:40 AM5/14/07
to greasemon...@googlegroups.com

As soon as the iframe is loaded and I've parsed its content, I always remove the iframe. Shouldn't
the busy/hourglass dissapear at some point?

Kia

RodMcguire

unread,
May 14, 2007, 9:06:41 AM5/14/07
to greasemonkey-users
On May 14, 8:37 am, Kia Niskavaara <kia.niskava...@gmail.com> wrote:

> Kia Niskavaara wrote:
> As soon as the iframe is loaded and I've parsed its content, I always remove the iframe. Shouldn't
> the busy/hourglass dissapear at some point?

In the past I've posted bizarre errors that show up with iframes/
greasemonkey/Firebug - one being persistent hourglasses.

If you are running Firebug, try disabling it. If this works please let
us know.

Kia Niskavaara

unread,
May 14, 2007, 10:07:34 AM5/14/07
to greasemon...@googlegroups.com

It didn't help. I've also tried changing the style of the cursor. That worked. But the ff tab still
says "loading". Crazy :)

RodMcguire

unread,
May 14, 2007, 10:46:44 AM5/14/07
to greasemonkey-users
On May 14, 10:07 am, Kia Niskavaara <kia.niskava...@gmail.com> wrote:
> > If you are running Firebug, try disabling it. If this works please let
> > us know.
>
> It didn't help. I've also tried changing the style of the cursor. That worked. But the ff tab still
> says "loading". Crazy :)

I just checked one of my scripts that loads stuff into iframes. I
works fine with no persistent hourglass. It contained the lines:

iframe.contentWindow.close(); // may not be needed but may help.
spContent.removeChild(iframe);

I tried commenting out the .close() and it still works fine. Of course
I ran this with Firebug disabled. FWIIW the above gets processed in
the callback:

iframe.addEventListener('load', function(){iframeLoaded(iframe);},
false);

RodMcguire

unread,
May 14, 2007, 10:56:51 AM5/14/07
to greasemonkey-users
On May 14, 10:46 am, RodMcguire <mcgu...@telerama.com> wrote:

I forgot to add, that my script adds a <div id="GreasedMonkey"> to the
I frame's DOM and only processes the iframe when that id is found.
Which means I also use timeouts if that ID is not present.

SuckDelay = SuckDelay*1.5;
SuckTimeout = setTimeout(convertSubPages, SuckDelay);

Kia Niskavaara

unread,
May 15, 2007, 2:37:27 AM5/15/07
to greasemon...@googlegroups.com

Could you please give an example? Are you saying that the div should be a parent to the iframe? And
how do I add the delay?

My code:

var iframe = document.createElement("iframe");
iframe.width = 1;
iframe.height = 1;
document.body.appendChild(iframe);
iframe.addEventListener("load", function() {
// do stuff with content here
iframe.contentWindow.close();
document.body.removeChild(iframe);
}, false);
iframe.src = "http://www.domain.com/page";

There is also another problem with this approach. It seems as if FF does't always generate the
DOMContentLoaded for the iframe. My guess is that the surrounding document needs to be completely
loaded first. If adding a iframe before the document is loaded, then no DOMContentLoaded. Maby your
delay fixed that problem? But wouldn't it be better to somehow add a event listener to the document?

Thanks for your help!

Kia

Kia Niskavaara

unread,
May 15, 2007, 6:06:32 AM5/15/07
to greasemon...@googlegroups.com

Solved:

iframe.addEventListener("load", function() {
// do stuff with content here

iframe.src = ""; <---- solution
iframe.contentWindow.close();
document.body.removeChild(iframe);
}, false);

and the second problem was solved by starting the script when the document was loaded. then there is
always DOMContentLoaded.

RodMcguire

unread,
May 15, 2007, 11:18:07 AM5/15/07
to greasemonkey-users
On May 15, 2:37 am, Kia Niskavaara <kia.niskava...@gmail.com> wrote:
> Could you please give an example? Are you saying that the div should be a parent to the iframe? And
> how do I add the delay?
>
> My code:
...

> There is also another problem with this approach. It seems as if FF does't always generate the
> DOMContentLoaded for the iframe. My guess is that the surrounding document needs to be completely
> loaded first. If adding a iframe before the document is loaded, then no DOMContentLoaded. Maby your
> delay fixed that problem? But wouldn't it be better to somehow add a event listener to the document?

Actually, my 'delay' is not so much a delay but may be a way to avoid
a delay. I came up with it when trying to deal with problems I now
think were caused by FireBug. My current guess on timing is:

1) adding "iframe" to the top-document DOM starts the sub-document
loading.
2) when the sub-document's DOM is loaded, its DOMContentLoaded event
is generated, and GM scripts run on that document.
3) When all of the sub-document' IMGs, IFRAMEs, etc. finish loading,
the "load" event is generated for both the sub-document and "iframe".

My script does not care about IMGs (or advertisements) in sub-
documents, so I figured if I could process "iframe" after time (2) I
might be able to abort loading some stuff I didn't care about. Thus I
have code like the following (the actual code loads multiple IFRAMEs
and has handled up to 60 of them)

SuckDelay = 500; // start at .5 second
SuckTimeout = null;

function processIframe (){
if (SuckTimeout) clearTimeout(SuckTimeout);
SuckTimeout = null;
var iframe = XPFirst(document, '//iframe');
if (!iframe) return;
var doc = iframe.contentDocument;
if (!doc || !doc.getElementById('greaseMonkeyed')) {
SuckDelay = SuckDelay*1.5;
SuckTimeout = setTimeout(processIframe, SuckDelay);
return;
}
// do something to content here
iframe.parentNode.removeChild(iframe);
}

document.body.appendChild(iframe);
iframe.addEventListener("load", processIframe, null);
setTimeout(processIframe, SuckDelay);

The above code can let me process an IFRAME after its DOMContentLoaded
event but before its load event..

In trace logs I see the iframe processing triggered by both the
timeout and the load event, so this approach working doesn't depend on
the timeout.

I'm thinking of writing up the IFRAME complications for greasespot, so
maybe I should again check whether IFRAMEs generate a DOMContentLoaded
event or if there is some way to get one.

RodMcguire

unread,
May 15, 2007, 11:29:57 AM5/15/07
to greasemonkey-users
On May 15, 6:06 am, Kia Niskavaara <kia.niskava...@gmail.com> wrote:
> Solved:
>
> iframe.addEventListener("load", function() {
> // do stuff with content here
> iframe.src = ""; <---- solution
> iframe.contentWindow.close();
> document.body.removeChild(iframe);
>
> }, false);

Huzzah! Is there any chance you can identify the URLs for the page and
subpage where you experience your "persistant hourglass" problem? That
is so I or someone else can further track down the problem and write
it up in the Wiki. My scripts have never had this problem so I presume
it has something to do with those specific pages.

Kia Niskavaara

unread,
May 16, 2007, 3:34:30 AM5/16/07
to greasemon...@googlegroups.com

Sure. I'm trying to modify a userscript http://userscripts.org/scripts/show/8430 that use the google
search result.

I find that when I only add one (1) iframe to the page, then the tab doesn't say "loading" and the
cursor is the default. But when moving the mouse, the hourglass shows and won't go away.

When I add more than one iframe to the page the tab always say "loading" and the cursor turns into
the persistant hourglass right away.

Kia

Kia Niskavaara

unread,
May 16, 2007, 3:34:39 AM5/16/07
to greasemon...@googlegroups.com

Clever! I don't understand at what point you add the div 'greaseMonkeyed' to the iframe though. I'm
not the owner of the iframe source...

I think it's strange that you cannot use the DOMContentLoaded event. If possible, wouldn't that
solve the problem? What I don't understand is that other userscripts are processed on the iframe,
and they trigger on the DOMContentLoaded event. But maby I'm missing something here?

Kia

Mortimer

unread,
May 16, 2007, 7:13:16 AM5/16/07
to greasemonkey-users
Hello,

very interesting thread. I am also trying to code an auto pager for
flickr (well, I kind of finished now), this is why I had started other
threads on similar problems as yours.
You can see the code here:
http://6v8.gamboni.org/Flickr-Auto-Pagination.html


I get most of the other greasemonkey scripts working on the iframe
content, but I still have two problems that you might encounter:
1- some gm scripts puts stuff in the unsafeWindow and do references to
functions etc.. that are broken when moving the DOM from the iframe to
the window. There is a thread on that already. I couldn't find any
simple solutions to that and am currently working on some way to let
the other gm scripts tell me what I should take care of when moving
the DOM. But that will imply modifying the other scripts also :(
2- some gm scripts are not fully finished when the DOMContentLoaded
event is finished. In particular, they set up onload events on the
window (which is the iframe window). The auto page script relies on
this onload event of the iframe, and sometime, the auto page receives
its event notification before the other gmscript have finished dealing
with theirs.
To solve that, I tried the same strategy as RocMcguire proposes: set a
timeout to wait for a div with a specific ID. But that's not
sufficient, as there is no guaranty that this will be the last thing
taking place.

Tell me if you do better than me on these problems ;)

Pierre

Henrik Nyh

unread,
May 16, 2007, 8:34:02 AM5/16/07
to greasemon...@googlegroups.com
On 15/05/07, RodMcguire <mcg...@telerama.com> wrote:
> I'm thinking of writing up the IFRAME complications for greasespot, so
> maybe I should again check whether IFRAMEs generate a DOMContentLoaded
> event or if there is some way to get one.

That would be great. I was just about to suggest that someone who has
followed this thread closely (I'm afraid I haven't) write this up on
the wiki, to make the information more accessible.

Reply all
Reply to author
Forward
0 new messages