foist javascript into another frame, and evaluate it in the target context

P

Phlip

Javascripters:

I have an outer page and an inner iframe. The outer page calculates some
javascript, and wants the inner frame to run it. The inner frame should hit
a page on the same (private) web server, so this is not a cross-site
scripting attack. But I would prefer not to taint the target page with any
extra logic to do this. (I will if I must.)

The calling page has these elements:

<script src="/javascripts/prototype.js" type="text/javascript" />...
<span id='update_me'>yo2</span>
<iframe id='grinder' src='sample.html' >
</iframe>

So here's most of the page which the iframe hits:

<script src="/javascripts/prototype.js" type="text/javascript" />...
<body bgcolor='silver'>
<span id='update_me'>yo</span>
</body></html>

Note that both the outer and inner page have a span with the same ID.

This question will resemble a JavaScript FAQ - how to evaluate Javascript on
the fly, or how to reload a JS file. The answers on the web generally do not
transport the JS across a frame boundary, so they don't address the bug I
encountered, and I can't tell if prototype.js or IE is at fault.

The outer page calls Ajax goodies that generate some JS looking like this:

Element.update("update_me", "here I B");

The page sends that, as a string, into this JS (in application.js):

function update_grinder(sauce)
{
var grinder = $('grinder');

if (grinder)
{
var doc = grinder.contentDocument;
if (!doc) doc = grinder.document;
if (doc)
{
evaluate(doc, sauce);
return;
}
}
document.write("your browser sucks");
}

So that contains enough logic to find the iframe's document, and it works
for Firefox, IE, Konqueror, and Opera. The code calls evaluate() with the
document where we need the evaluation context, and the string with our
source.

Here's evaluate():

function evaluate(doc, sauce)
{
var s = doc.createElement('script');
//s.defer = true; // <-- no effect
s.text = sauce;
var body = doc.getElementsByTagName('body').item(0);

if (body)
{
body.appendChild(s);
return;
}
body = doc.body;
if (body)
{
body.appendChild(s);
return;
}
}

That creates a <script> block, sticks our string in as its contents, and
pushes the block to the end of our <body> tag. Now here's the bug:

Firefox updates the inner <span id='update_me'>, and IE updates the outer
one.

If I remove the outer <span id='update_me'>, then IE simply can't find it
and throws an error. Even though it evaluates a script block clearly in the
context of the inner iframe.

I have tried calling the script from setTimeout, and from a button's onclick
handler.

Is there some script.aculo.us way to fix (yet another) bug in IE? Or is this
a bug in prototype.js?
 
P

Phlip

Randy said:
It's not a bug in IE.


Possibly.

Yet another of the frictions you have brought to this discussion is your
phobia for prototype.js. I'm sure it has issues, but my result with
frame.src=javascript:void(function(){...}()) shows prototype.js works when
the browser runs it in the right context. Same prototypical code in ... ,
different hand-written JS to deliver it, different results.

So it was a bug in IE, and once again you are... you-know-what. ;-)
 
R

Randy Webb

Phlip said the following on 12/16/2006 7:16 PM:
Yet another of the frictions you have brought to this discussion is your
phobia for prototype.js.

My "phobia of prototype.js"? That is, indeed, a powerful assumption on
your part. I have not expressed a phobia of prototype, I have barely
commented on it. You wanted to know if it was a bug in IE and I said no.
You asked if it was a bug in prototype and I said Possibly. And from
that you induced that I have a phobia of prototype. It wouldn't matter
if it was prototype.js, Yahoo!'s Library, one of Matt Kruse's libraries
or anybody else's, my response would have been the same. It is just as
likely that it isn't as it is a bug in prototpye.
I'm sure it has issues, but my result with
frame.src=javascript:void(function(){...}()) shows prototype.js works when
the browser runs it in the right context. Same prototypical code in ... ,
different hand-written JS to deliver it, different results.

That alone indicates a flaw in prototype.js. Your tests, your results,
and you get different results from prototype.js (where it doesn't work)
and from doing it manually (where it works). So you yourself have shown
that it was possibly a prototype issue and not an IE issue.
So it was a bug in IE,

No it isn't.
 
P

Phlip

Randy said:
My "phobia of prototype.js"? That is, indeed, a powerful assumption on
your part. I have not expressed a phobia of prototype

Besides calling it, what, "protocrap"? Was that just the exception?
That alone indicates a flaw in prototype.js. Your tests, your results, and
you get different results from prototype.js (where it doesn't work) and
from doing it manually (where it works). So you yourself have shown that
it was possibly a prototype issue and not an IE issue.

Once again you show no evidence of grasping the experiment. I wrote code to
use your technique, and it worked in FireFox and failed in IE. (Inserting
code that, unlike alert(), required the correct context to run.) Then I
wrote the code to use iframe.src=javascript:void etc., and it worked in both
browsers. No doing anything manually.

To make your grid of experiments more useful, you need to A> add the
javascript:void trick, and B> make the inserted code do something relevant,
not just alert().
 
R

Randy Webb

Phlip said the following on 12/16/2006 11:13 PM:
Besides calling it, what, "protocrap"? Was that just the exception?

Yep, that is what I called it. But I have no phobia of it, its crap. If
people want to use it, then let them.
Once again you show no evidence of grasping the experiment.

Hmmm, ok. The problem is you can't make it inject script across frames
and get it to execute in the context of the IFrame. And since you can't,
you call it a "bug in IE". To which I say you are dead wrong. Proof below.
I wrote code to use your technique, and it worked in FireFox and failed in IE.

If the code I wrote didn't work in IE then something else you are doing
is causing that failure as the code I wrote works flawlessly in IE,
Firefox, Opera and about 8 other browsers that I don't care to type the
names of.
(Inserting code that, unlike alert(), required the correct context to run.)

You mean code that will change the innerHTML of an element on a page
where the same ID is present in both the parent document and the child
document?
Then I wrote the code to use iframe.src=javascript:void etc., and it
worked in both browsers. No doing anything manually.

I will have to take your word for that as you haven't shown any code
using iframe.src=.....
To make your grid of experiments more useful, you need to A> add the
javascript:void trick, and B> make the inserted code do something relevant,
not just alert().

I made it do just that. It changes the innerHTML of an element in a
child page and - guess what - it doesn't use any javascript:void hack.
You have been reading too much VK.

Here are your two test pages:

parent.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<title>Blank Page with an IFrame</title>
<style type="text/css">
</style>
<script type="text/javascript">
function insertScriptTextAcrossFrames(frameID,scriptString){
frameRef = window.frames[frameID]
var newScript = frameRef.document.createElement('script');
newScript.type = "text/javascript";
newScript.text = scriptString
frameRef.document.getElementsByTagName('head')[0].appendChild(newScript);
}
</script>
</head>
<body>
<div id="divToModify"></div>
<iframe name="myIFrame" src="child.html"></iframe>
<button
onclick="insertScriptTextAcrossFrames('myIFrame','document.getElementById(\'divToModify\').innerHTML=\'This
is new text\'')">Insert script text across frames</button>
</body>
</html>


The button code will have to be unwrapped before testing.


And child.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<title>Blank Page2 to Modify</title>
<style type="text/css">
</style>
</head>
<body>
<div id="divToModify"></div>
</body>
</html>

Both of them have a div with the id of divToModify as you say your
document does. It uses the exact function I gave you to use. Now, what
is it about the "concept of the problem" is it that you think I don't
understand?
 
R

Randy Webb

Phlip said the following on 12/17/2006 12:29 AM:
It worked in Firefox. In IE, the update went to the SPAN in the outer frame.
Bug. The possibility of invalid HTML encodings doesn't excuse the bug.


No, change the innerHTML period. The matching ID has nothing to do with the
bug; I just used it to illustrate the symptom.

And I posted code that does what you want it to do but it works,
flawlessly, in IE, so, where is the "bug"?
Do I have to find you in person and dial your browser to the post of 10:20
AM PST containing this?

function update_grinder(sauce)
{
var grinder = $('grinder');
grinder.src='javascript:void(function(){'+sauce+'}())';
}

I never told you to use the .src attribute though, use the .text property.
Your capacity to ignore and misunderstand my posts, then blame me, is
astounding.

Your inability to explain the problem right is more astounding.
No idea who that is, but my project requires protocrap.js as an external
constraint.

Then you can load it in the IFrame.

function loadJSFile(fileURL){
var frameRef = window.frames['frameName']
var newScript = frameRef.document.createElement('script');
newScript.type = "text/javascript";
newScript.src = fileURL;
frameRef.document.getElementsByTagName('head')[0].appendChild(newScript);
}

loadJSFile('pathToPrototype')

Then, prototype will be executed in the context of the IFrame and make
all it's "goodies" available to the IFrame.
Feel free to say it shares the bug with IE.

The bug isn't in IE though.
Thanks for upgrading your experiment, but for completeness you
could consider adding the javascript:void technique.

I didn't need it, I only made it to prove that it wasn't a bug in IE
which is what I said to start with.
Not sure why you call something that works on
many more browsers with many fewer lines of code a "hack"...

eval works also, do you use that over-extensively as well?
Yes, now that you have changed your position a great deal since my first
post, there are indeed fewer areas of misalignment.

That didn't answer the question though. I am still curious what it is
you think I don't understand with regards to the problem.
 
P

Phlip

Randy said:
And I posted code that does what you want it to do but it works,
flawlessly, in IE, so, where is the "bug"?

Forget the duplicate ID. FireFox updated the SPAN that Element.Update
targetted. IE threw an exception in the same situation. So there's a bug in
IE or prototype.js.
I never told you to use the .src attribute though, use the .text property.

This is amazing. When I was using the createElement trick, I was using the
..text property. 'grinder' is the IFRAME itself; I'm doing the equivalent of
writing javascript:alert('yo') in your browser's address bar.
Then you can load it in the IFrame.

Once again, nobody is asking how to get prototype.js into the IFrame. It's
already there. Post of 12:20 AM: "That also includes prototype.js..."
eval works also, do you use that over-extensively as well?

All the time. And in C++ I abuse #define macros, in Perl I refuse to bless
hashes, in SQL I use DISTINCT and LIMIT, in Python I use tabs, in VB6 I use
concrete virtual base classes, in Ruby I, uh, also eval() a lot, in Fortran
I use 7-letter identifiers, and my Smalltalk selectors don't reveal intent.

Are you off your high-horse yet??
 
R

Randy Webb

Phlip said the following on 12/17/2006 12:59 AM:
Forget the duplicate ID. FireFox updated the SPAN that Element.Update
targetted. IE threw an exception in the same situation. So there's a bug in
IE or prototype.js.

If hard coding it doesn't produce an exception but using Element.Update
produces that exception, then it points to the flaw being in
Element.Update, don't you think?
 
P

Phlip

Randy said:
If hard coding it doesn't produce an exception but using Element.Update
produces that exception, then it points to the flaw being in
Element.Update, don't you think?

Hard coding what??
 
R

Randy Webb

Phlip said the following on 12/17/2006 2:30 AM:
Hard coding what??

<eyeroll> If writing code to update an Element doesn't produce an
exception, yet trying to use Element.Update to update an Element
produces an exception, then the flaw is in Element.Update
 
R

Richard Cornford

Phlip said:
"Phobia" means "hatred". Its popular usage is "unreasoning
fear". Same difference.
<snip>

The deprecation of Prototype.js is not unreasoning. The library started
off being needlessly non-cross browser (failing on IE versions 5-5.5 for
no good reason and inconstant in its behaviour on Opera browsers), was
written in breach of the only naming convention stated in the language
specification, and recent modifications have rendered the library not
even ECMAScript compliant (so there should be no expectation of its ever
working outside of a known and limited set of nameable environments
(which defeats the whole drive towards standardisation in web
technologies)). It is also crazily convoluted in design and completely
interdependent, to the point that no novice stands a chance of
understanding how it works internally (partly as a result of having to
understand everything before they can understand anything), massively
inefficient and very much working against the strengths of javascript.
It worked in Firefox. In IE, the update went to the SPAN in
the outer frame. Bug. The possibility of invalid HTML
encodings doesn't excuse the bug.

Its behaviour in IE was accounted for entirely by your assumption that
the - document - property of an IFRAME element would refer to the
document contained in the IFRAME instead of the document containing the
IFRAME. That assumption was false and the consequences of your making
false assumptions cannot be attributed to bugs in IE.
function update_grinder(sauce)
{
var grinder = $('grinder');
grinder.src='javascript:void(function(){'+sauce+'}())';

Be aware that executing a javascript pseudo-protocol URL on IEs 4-6
changes the state of the browser's execution environment in many ways
and much of what was reliable before doing so will not be reliable
afterwards. (This issue may have been removed from IE 7 as the most
visible symptoms of the state change are no longer observed there).

That means that if you do this in IE 6 all bets are off as to what you
may be able to do afterwards.

Also, there is no public specification that states that assigning to
the - src - attribute of an IFRAME will result in changes to the
contained document (and the implication of what the HTML DOM
specification actually does say is that it will not). Generally, if you
wanted to navigate (which is what this is attempting, in a not actually
navigating way) then you would assign the URL to the location object of
the frame/window/global object of the contained frame.

Richard.
 
P

Phlip

Richard said:
The deprecation of Prototype.js is not unreasoning.

Yet its Phobia (true meaning, not popular usage) caused friction in this
benighted thread. At no time did I defend it, yet was repeatedly and
mindlessly attacked for suggesting it was an external constraint to my
quest.

And look! we found a bug in it! I only had to withstand getting flamed
numerous times to force that acknowledgement.

While you are such a font of knowledge, any idea why Konqueror doesn't work
there?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top