Drag and drop problems in HTA frames
During our
recent migration to
HTA we discovered a problem dragging hyperlinks within frames (either <FRAMESET> or <IFRAME>). The problem was that dragging the contents of an <A> element onto a frame caused the link to be loaded in the frame - it was as if the hyperlink were being clicked.
The problem occurs when a drag ends inside a frame, regardless of whether the drag started outside the frame, within another frame, or within the same frame.
The contents of the <A> element don't seem to make any difference either: we first noticed the problem with image hyperlinks but then discovered that text behaved the same way.
The way we've solved the problem is using the ondragstart event. By handling the event it is possible to prevent the user dragging:
ondragstart="return false"
The ondragstart event occurs for both the <BODY> and the <A> involved, so there's some flexibility in where you attach the event handler. If the HTA is using an <IFRAME> then the ondragstart can be attached to the <BODY> of the parent document (the page containing the <IFRAME>). If the system is using a <FRAMESET> then the parent document will not have a <BODY> - there is no solution at the parent level in this case.
With both the <IFRAME> and <FRAMESET> variations you can attach the ondragstart to either the <BODY> or <A> of the child document (the page within the frame), though on large pages you may notice that attaching to the <A> element slows the browser down - using <BODY> is probably a safer bet.
| Dragging not possible |
N/A |
| Use <BODY> ondragstart |
Use <BODY> or <A> ondragstart |
| No solution |
Use <BODY> or <A> ondragstart |
If you opt to put the ondragstart on the child document then you'll probably want to consider a way of applying it universally, so it affects all pages shown in the frame. In ASP.NET this could be done with a base page class, but the option we took was to use an HTC attached using an existing stylesheet: all our pages use a standard stylesheet, so this was modified to include a reference to the HTC file:
body
{
behavior: url(PreventDrag.htc);
}
The htc file simply attaches a function to the ondragstart event:
<public:attach event="ondragstart" handler="preventDrag" />
<script type="text/javascript">
function preventDrag() {
event.returnValue = false;
}
</script>
One thing to be careful of with the HTC reference in the stylesheet is it's path: the path is from the page using the stylesheet. The safest way to define it is probably as an absolute path or root relative path.
I suspect this solution will need modifying if we ever want to implement AJAX-style drag and drop, but for the moment it's solved our problem.