Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #7766 (new defect)

Opened 1 year ago

Last modified 3 months ago

Effects Break in Cross-Frame Cases

Reported by: Cookiebasher Assigned to: thomas@fesch.at
Priority: high Milestone: 2.x
Component: script.aculo.us Version:
Severity: normal Keywords: cross-frames, frames, draggable
Cc: mike@digitalhill.com

Description

Overview

I am currently working on an application that takes advantage of a frameset. Each frame serves a specific purpose. The top frame is the controller and script arbitrator. The bigger, lower frame could load any page from any website. The top frame's responsibility is to interpret the bottom document and use JavaScript to manipulate it. Now, when I dynamically created an element in the canvas, if you will, and made it draggable, there were some communication problems. These problems were symptomatic of referencing the root document, when in fact this script requires elements to be reached via parent.frame.document.

Progress

new Draggable(id, {root:parent.frame.document});

I was successful at getting the script to work again in IE by just creating a "root" option with a default of "document". Then, if I wanted to change the parent reference, all I had to do was use the code above. Then I simply changed the register and unregister functions of to reference "draggable.options.root" instead of simply "document". However, I am have extreme difficulty achieving success with every other browser.

Test Cases

I have created two test cases. The first one is the unmodified version (1.70). The second one is the modified version that works in IE. To locate the changes I made in dragdrop.js, please Find "[frame-support]:". I hope I was clear enough.

http://www.digitalhill.com/testcases/scriptaculous/original.html http://www.digitalhill.com/testcases/scriptaculous/modified.html

Change History

03/12/07 13:01:50 changed by Cookiebasher

Just a side note, the modified script that I used started to work for me one morning. I am not sure what I did. Once I determine that I will post it here. The test cases remain unfixed, though.

04/17/08 10:18:32 changed by jeremy_morley

Hi.

I'm trying to use Scriptaculous for some cross-frame effects very similar to those described in this ticket. I'm using Scriptaculous version 1.8.1 and the bug still seems to be in this version.

I've started to have a look at this myself and had similarly come to the conclusion that part of the problem is to do with dragdrop.js referring to "document" rather than finding the document which contains the draggable. I put in a fix which allows the drag to be registered properly, and now all browsers will pick up the mousedown and start the drag, and track the drag in the correct frame. However only Safari detects the mouseup properly and stops dragging (using my fix). I've been using Seamonkey 1.1.9 (PC & Mac), IE 7, Opera 9.27 (PC), and Safari 3.1 (Mac) for testing.


Test cases

My test cases can be found here:

http://iceds.ge.ucl.ac.uk/drag_test/ - uses original 1.8.1 http://iceds.ge.ucl.ac.uk/drag_test2/ - uses my fix to 1.8.1

There are two frames, nav (on the left) and layers (on the right). The start-up state loads a couple of buttons in nav which we'll come back to in a moment. The layers frame starts by loading an HTML page with Scripaculous embedded in it to define the list (and the sublist within it) as Sortables. This works fine.

Now press either the Test1 or Test2 buttons. Either of these rewrite the document in the layer frame by opening the document in Javascript and writing new content. (In these tests, that content is entirely fixed but in my actual application the content will be dynamic.) The content is another (shorter) list, and the idea is that again this list should be draggable. The problem seems to be in using Scriptaculous in the nav frame to control the elements in the layer frame. When re-writing frames in this way, none of the browsers will properly load and execute Javascript from an external file if included in the content being written into the target frame - i.e. I can't include Scriptaculous as a reference in the new page being written into the layer frame.

The Test1 and Test2 buttons differ slightly in how the new code in the layer frame access Scriptaculous in the nav frame to create the Sortable:

Test1 runs a line of Javascript in the layer frame to find the object relating to the list, and then calls the Sortable create method in the nav frame, parent.nav.Sortable.create();

Test2 calls an extra function in the nav frame called set_sortable() with the list id parent.nav.set_sortable("layer_list"); The set_sortable() function then finds the right object in the layer frame and calls the Sortable create method.

NOTE: it seems to be best to close the tab/window & open a new one after pressing Test1 or Test2 and before trying the other button as the page doesn't respond reliably after pressing either button. Nor does it always respond properly to the reload button.

The first page loaded in the layer frame works fine in all cases (loading an HTML page with Scriptaculous referenced, as part of the frameset).


Vanilla Behaviour:

Using the vanilla version of Scriptaculous (drag_test), there's no difference between the Test1 and Test2 buttons. Holding or clicking on a list item in the replacement list appears at first to do nothing. However if you move the mouse back to the nav frame on the left it's clear that the Sortable is responding to mouse movement in the nav frame. A double-click in the nav frame, or clicking another element in the list in the layer frame, unregisters the drag.

There's a difference between browsers in the final behaviour. On a double-click in the nav frame, IE drops the ghost, Seamonkey leaves only one copy of the dragged element in the new location and in Safari the ghost disappears leaving the element in its original location.


My patch:

I added two new functions to dragdrop.js as follows: //
// JGM new functions
// get_doc(draggable) accesses the element property and hands it into the
// recursive test_doc() function
//
// test_doc(o) either returns a #document nodeName, or recurses up to the
// parentNode
//
function get_doc(draggable) {

var o = draggable.element; return test_doc(o);

}

function test_doc(o) {

if (o.nodeName == "#document")

return o;

else

return test_doc(o.parentNode);

} // // end JGM new functions //

These I use to traverse up from the draggable to find its parent document. Then in the Draggables register & unregister methods I replace the reference to document with the document derived from the traversal functions, e.g. a fragment from the register method:

// JGM - find the correct document that this draggable belongs to
var correct_doc = get_doc(draggable);
Event.observe(correct_doc, "mouseup", this.eventMouseUp);


Patched behaviour:

Using my patched version of Scriptaculous (drag_test2), the script correctly starts the drag and tracks the mouse in the layer frame. Safari behaves entirely correctly - it detects the mouseup and drops the dragged element in the correct place in the list, reordering the elements neatly. Further dragging works fine.

IE detects the mouseup but drops a copy of the element and keeps dragging a ghost. Thereafter each click drops another copy. A double-click stops the dragging and adjusts all the copies to neat positions though not within the bounds of the original list. No further dragging can then be performed (no response - the ordinary selection behaviour of the browser is seen).

Seamonkey doesn't detect the mouseup. A double-click stops the drag and drops the element (no tidying, element dropped anywhere in the frame). Further drags work the same. The error console in Seamonkey shows a string of errors of three forms: "Error: this.element.getStyle is not a function Source File: http://iceds.ge.ucl.ac.uk/scriptaculous-js-1.8.1-JGM/src/dragdrop.js Line: 366"

"Error: element.getStyle is not a function Source File: http://iceds.ge.ucl.ac.uk/scriptaculous-js-1.8.1-JGM/lib/prototype.js Line: 2042"

"Error: element.hasClassName is not a function Source File: http://iceds.ge.ucl.ac.uk/scriptaculous-js-1.8.1-JGM/lib/prototype.js Line: 1817".

The first getStyle errors appears on the mousedown on the element. The hasClassName errors occur as the element is dragged over other list elements. The final getStyle error appears as the element is dropped (on a click).

Any help / recommendations as to where to go next would be welcome! My impression is that there's a problem with the event registration (hence in Prototype) but I'm not sure why Seamonkey reports the particular errors I've reported above. I haven't yet tracked the code using the Venkmann debugger for my patched test cases.

Thanks, Jeremy Morley