<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/
TR/html4/strict.dtd">
<html lang="en">
<head>
<title>An IE iframe bug tester for the event manager</title>
<script type="text/javascript" src="js/scroll.js"></script>
<script type="text/javascript" src="js/event.js"></script>
<script type="text/javascript">
FORK.Event.addListener(window,'load',
function(e){
var d=this.frames[0].document;
FORK.Event.addListener(d,'click',bugger);
});
function bugger(e){
// clicks on documents different from top document
// will not produce the correct event reference;
// inline events are affected, not attachEvent
alert(e);
}
</script>
</head>
<body>
<iframe id="test" name="test">A Test IFRAME</iframe>
</body>
</html>
An initial fix is going to be sent to Peter for review.
Diego Perini
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/
TR/html4/strict.dtd">
<html>
<head>
<title>An event smashing tester for the event manager</title>
<script type="text/javascript" src="js/scroll.js"></script>
<script type="text/javascript" src="js/event.js"></script>
<script type="text/javascript">
FORK.Event.addListener(document,'click',bugger);
FORK.Event.addListener(document,'click',starter);
FORK.Event.addListener(document,'click',failover);
function bugger(e){
// remove myself from the listeners chain
// actually removing a listener from the chain
// while inside the for loop which executes them
FORK.Event.removeListener(this,e.type,arguments.callee);
}
var done=false;
function starter(e){
done=true;
alert('Test Passed !');
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue=false;
};
}
function failover(e){
if(!done){
alert('Test NOT Passed !');
// alert has failed even after first click
FORK.Event.removeListener(document,e.type,starter);
}
}
</script>
</head>
<body>
<p><b>Click on the document to test events.</b></p>
</body>
</html>
I am sending you copy of these test and possible fixes.
Diego Perini
The above line raises a red flag for me.
The following is from http://developer.apple.com/internet/webcontent/iframe.html
<blockquote>
Sadly, referencing the IFRAME's document object is no simple task,
since IE5, IE5.5, IE6, and NS6 all provide different ways to access
it. IE5, both on the Mac and PC, provides the simplest method: IFRAMEs
in this browser show up in the document.frames array and have a
document property. In IE5.5, IE6 and NS6, you can retrieve the IFRAME
element object with document.getElementByID(), then, in NS6, use the
object's contentDocument property, and in IE 5.5+, use the document
property of the IFRAME object's contentWindow property. That's quite a
mouthful, isn't it? Thankfully, it's quite a bit simpler in the actual
code:
<code> if (IFrameObj.contentDocument) {
// For NS6
IFrameDoc = IFrameObj.contentDocument;
} else if (IFrameObj.contentWindow) {
// For IE5.5 and IE6
IFrameDoc = IFrameObj.contentWindow.document;
} else if (IFrameObj.document) {
// For IE5
IFrameDoc = IFrameObj.document;
} else {
return true;
}</code>
</blockquote>
> FORK.Event.addListener(d,'click',bugger);
> });
>
> function bugger(e){
> // clicks on documents different from top document
> // will not produce the correct event reference;
> // inline events are affected, not attachEvent
> alert(e);
> }
>
> </script>
> </head>
> <body>
>
> <iframe id="test" name="test">A Test IFRAME</iframe>
>
> </body>
> </html>
>
> An initial fix is going to be sent to Peter for review.
Perhaps the event is not being registered properly because of issue
discussed on the apple page?
Peter
I agree this is a bug. I imagine not one that people would encounter
often either.
The suggested fix is to change the following line in event.js
var lls = arguments.callee.legacyListeners;
to
var lls = arguments.callee.legacyListeners.slice();
I don't think this fix will work in general because if one event
handler runs and removes an event handler which hasn't yet run, then
the fresh copy of the array will not be modified. That means the event
handler that has not yet run but that has been removed will actually
run. That would be wrong...maybe. I will make some tests to determine
how browsers handle this with DOM2 events.
Thanks,
Peter
The event is registered, but we need to get the event from the correct
window.
Again this is another INLINE events problem, so only for "onclick"
events in Fork.
Diego Perini
On Apr 24, 4:45 am, "Peter Michaux" <petermich...@gmail.com> wrote:
> On 4/23/07, Diego Perini <diego.per...@gmail.com> wrote:
>
>
>
>
>
> > This does not work using FORK.Event, perhaps there ways to do it
> > passing the "scope" but I am too fresh to FORK, and I am probably just
> > using it in the wrong way. Comments welcome...
>
> > <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/
> > TR/html4/strict.dtd">
> > <html lang="en">
> > <head>
> > <title>An IE iframe bug tester for the event manager</title>
> > <script type="text/javascript" src="js/scroll.js"></script>
> > <script type="text/javascript" src="js/event.js"></script>
> > <script type="text/javascript">
>
> > FORK.Event.addListener(window,'load',
> > function(e){
> > var d=this.frames[0].document;
>
> The above line raises a red flag for me.
>
> The following is fromhttp://developer.apple.com/internet/webcontent/iframe.html
If at some point in the chain, one of the listeners removes one of the
remaining
pending listeners, I would not expect that listener to be removed in
this chain run
but in the next chain run.
If one of the listeners removes itself from the chain, like this:
function event_handler(e) {
removeEvent(this, e.type, arguments.callee, false);
...remaining code...
}
should "...remaining code..." be run or not ?
If "...remaining code..." SHOULD NOT be run the you are probably
right...
It seems that the specifications are poor on this, so the decision
is obviously a matter of taste and needs.
>From my tests it seems that "...remaining code..." will be always
executed in all browsers (also have no access to a MAC).
This problem is strictly bound to INLINE events behavior so in the
case
of "Fork" this problem is visible only in the "onclick" handlers, for
which
you build a chain of listeners to be executed by an INLINE event
handler
(you sure had a good reason to do that but I don't know it).
However in many other libraries all the events are setup by using
INLINE events, and that
is done for cross-browser solutions, to fix incorrect event behaviors
or to add missing event
properties. That's good, but these kind of problems must be known and
handled in some way...
And yes this is not often to encounter just because few remove their
events, partially because
some browsers implement a good garbage collection, partially because
everybody needs is at
most a couple of click and a drag drop operation, but in a WEB 2.0
world this has to change.
Diego Perini
On Apr 24, 5:00 am, "Peter Michaux" <petermich...@gmail.com> wrote:
On 4/24/07, Diego Perini <diego....@gmail.com> wrote:
>
> also your way of finding the document is correct my post was not about
> IFRAMES specifically, I choosed an IFRAME in the test because is
> easier,
> however a "window.open" with an "onclick" on it will give the same
> results.
I still don't understand this bug report, what the problem is and what
you are trying to do to fix it. Can you make an extremely short test
case with window.open and post it as an attachment to a new ticket?
http://dev.forkjavascript.org/trac/report/1
Thanks,
Peter
On 4/24/07, Diego Perini <diego....@gmail.com> wrote:
>
> I like to think that when a chain of event listeners is scheduled to
> be run,
> let's say it contains 5 listeners, I should get exactly 5 listeners
> executed.
>
> If at some point in the chain, one of the listeners removes one of the
> remaining
> pending listeners, I would not expect that listener to be removed in
> this chain run
> but in the next chain run.
IE and Opera implementations agree with you and the implementation is simple.
Safari, Firefox and the DOM2 specs are the opposite which makes the
implementation a little more complex.
From http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget-removeEventListener
"This method allows the removal of event listeners from the event
target. If an EventListener is removed from an EventTarget while it is
processing an event, it will not be triggered by the current actions.
EventListeners can never be invoked after being removed."
I will implement the Safari/Firefox/DOM2 behavior in the next version of Fork.
It is great that you brought up this bug so that it can be fixed.
Thanks,
Peter
Sorry for not being clear, English is not my native language so...I
include here the
example this time with "window.open" and without using FORK to show
that this
is an IE BUG that must be taken care of in FORK.Event.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/
TR/html4/strict.dtd">
<html lang="en">
<head>
<title>An IE event source bug tester for the event manager</title>
<script type="text/javascript">
// open some other document from the same domain
var win =
window.open('./','MyWindow','top=400,left=400,width=200,height=200');
win.attachEvent('onload',
function (e) {
win.document.onclick=bugger;
}
);
function bugger (e) {
// wrong way of getting the event object
alert( e || window.event );
// correct way of getting the event object
alert( e || ((this.ownerDocument || this. document ||
this).parentWindow || window).event );
}
</script>
</head>
<body>
<p>Click in the popup Window</p>
</body>
</html>
When multiple windows/documents are present and a unique event manager
is used to
add/remove events in their elements, the event must be grabbed from
the correct window.
The line:
event = event || window.event:
presumes there is only one fixed window, while actually we may have
two ore more of them.
We have to grab event directly from it's source element, stepping the
DOM chain up to it's
containing window, then reading the event object from that window like
in this line:
event = event || ((this.ownerDocument || this.document ||
this).parentWindow || window).event;
I believe there should be no drawbacks and incompatibility introduced
by a change like this,
still few people use IFRAMES and WINDOWS extensively in their apps, I
believe this will become
more common in the near future.
Since the FIX uses the "this" keyword it is required that the event
manager fixes it in advance.
There is an attachment showing this as an IE only BUG (or so
presumed), nothing to do with FORK really,
but FORK should fix this to make the behavior consistent among
browsers.
Cheers,
Diego
On Apr 26, 6:39 pm, "Peter Michaux" <petermich...@gmail.com> wrote:
> Hi Diego,
>
IMPORTANT
The behavior shown in the test we used will be incorrect respect to
the DOM2 specs
only when working (adding and/or removing events) on the same event
chain.
Modification in one chain type will only affect events of that same
type.
You noticed that IE/Opera behaves differently from other browser in
respect to this test.
However you may have not noticed that IE and Opera themselves will
fail the test
for two different reasons, since Opera uses DOM2 event registration
while IE doesn't.
Opera behave differently from Firefox even if it uses DOM2 event
registration.
IE behaves differently for another reason, that is the order of
execution of events
are not the same between IE and all other browsers, so if you want to
remove some
event you really don't know at which stage they will be removed.
It is clear we are pushing things to the limit here, and these
situation/capabilities are not
often to encounter in real world, but these are some common use I
could easily find:
- one shot events; these must fire and remove themselves
- cascade/chained events; these must be able to add/remove themselves
and/or other events
- events which may be called several times between start and final
state: load (if capturing),
readystatechange (on any element in IE and on XMLHttpRequest in all
browsers), and
on Mutation Events (DOMNodeInserted, DOMSubtreeModified etc.)
and these addition removal must be handled while the for/loop chain is
running other events...
It is obvious we cannot pretend FORK and similar API to fix all the
different browsers
implementations/behaviors or worst fix their bugs, but trying to bring
them all to a common
behavior does not let me feel bad... :-) Also sorry for the extra
work, hope it can yield back.
Thank you for listening/checking,
Diego
On Apr 27, 3:46 am, "Peter Michaux" <petermich...@gmail.com> wrote:
> Hi Diego,
>
> On 4/24/07, Diego Perini <diego.per...@gmail.com> wrote:
>
>
>
> > I like to think that when a chain of event listeners is scheduled to
> > be run,
> > let's say it contains 5 listeners, I should get exactly 5 listeners
> > executed.
>
> > If at some point in the chain, one of the listeners removes one of the
> > remaining
> > pending listeners, I would not expect that listener to be removed in
> > this chain run
> > but in the next chain run.
>
> IE and Opera implementations agree with you and the implementation is simple.
>
> Safari, Firefox and the DOM2 specs are the opposite which makes the
> implementation a little more complex.
>
> Fromhttp://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarge...
http://dev.forkjavascript.org/trac/ticket/33
http://dev.forkjavascript.org/trac/changeset/296/trunk/public/javascripts/fork/event.js
Thanks to another interaction in the code, the correct DOM2 behavior
was automatic. That is, a listener that is removed but that has not
yet run will not run.
Peter
On Apr 23, 8:00 pm, "Peter Michaux" <petermich...@gmail.com> wrote: