Thursday, October 28, 2010

How to support drag’n’drop with Silverlight on Mac

Silverlight 4 introduced support for drag and drop. That is, developers have access to files like images or videos that are dropped into Silverlight-based web application.

Unfortunately, as discussed in this thread, this capability does not work very well on a Mac. The issue is described briefly in this MSDN article but this post will provide a easily to implement (and painless) workaround.

These changes only affect the HTML page hosting the Silverlight control.  You do not need to make any change to your Silverlight project.

To start, add the text highlighted below.

<body>
    <form id="form1" runat="server" style="height:100%">
   
<div id="silverlightControlHost">
       
<object id="plugin" data="data:application/x-silverlight-2," ...
            <param name="source" value="..."/>
           
<param name="onError" value="onSilverlightError" />
           
<param name="onLoad" value="onSilverlightLoad" />
           
<param name="background" value="white" />
           
<param name="minRuntimeVersion" value="4.0.50826.0" />
           
<param name="autoUpgrade" value="true" />
           
<a href="http://go.microsoft.com/fwlink/...
               
<img src="http://go.microsoft.com/fwlink/...
           
</a>
       
</object><iframe id="_sl_historyFrame" style=...
   
</form>
</body>
</html>

Next, immediately below the boilerplate “onSilverlightError” JavaScript function, append the following six functions.

function onSilverlightLoad(sender, args) {
    if (window.navigator.userAgent.indexOf('Safari') >= 0) {
        var objControl = document.getElementById('plugin');
        objControl.addEventListener('dragenter',
            onSilverlight_HandleDragEnter, false);
        objControl.addEventListener('drop',
            onSilverlight_handleDropEvent, false);
        objControl.addEventListener('dragover',
            onSilverlight_HandleDragOver, false);
        objControl.addEventListener('dragleave',
            onSilverlight_HandleDragLeave, false);
    }
}
function onSilverlight_HandleDragEnter(oEvent) {
    // Prevent default operations in DOM
    oEvent.preventDefault();
    var flag = oEvent.target.dragEnter(oEvent);
    // If handled, then stop propagation of event in DOM
    if (flag) { oEvent.stopPropagation(); }
}
function onSilverlight_HandleDragOver(oEvent) {
    // Prevent default operations in DOM
    oEvent.preventDefault();
    var flag = oEvent.target.dragOver(oEvent);
    // If handled, then stop propagation of event in DOM
    if (flag) { oEvent.stopPropagation(); }
}
function onSilverlight_HandleDragLeave(oEvent) {
    // Prevent default operations in DOM
    oEvent.preventDefault();
    var flag = oEvent.target.dragLeave(oEvent);
    // If handled, then stop propagation of event in DOM
    if (flag) { oEvent.stopPropagation(); }
}
function onSilverlight_handleDropEvent(oEvent) {
    // Prevent default operations in DOM
    oEvent.preventDefault();

    var newEvent = Silverlight_clone(oEvent);
    newEvent.clientX = 80;
    newEvent.clientY = 80;
    newEvent.x = 80;
    newEvent.y = 80;
    newEvent.offsetX = 80;
    newEvent.offsetY = 80;

    var flag = oEvent.target.dragDrop(newEvent);
    // If handled, then stop propagation of event in DOM
    if (flag) { oEvent.stopPropagation(); }
}
function Silverlight_clone(o) {
    var c = {};
    var p, v;
    for (p in o) {
        if (o.hasOwnProperty(p)) {
            v = o[p];
            c[p] = v;
        }
    }
    return c;
}
 

You are now good to go!

This code is based primarily on the solution provided by Olego in this forum.

3 comments:

  1. I tried this method but the Drop event is not firing for me in Mac OSX 10.6.8, Safari 2.0.4. When i drop a file, the action which should happen is not happening for me. Is there anything else i should do?

    ReplyDelete
  2. Please read the forum posting associated with the last link in the post. It contains a detailed discussion about OSX/Safari support. It could be that you have encountered a new issue with OSX/Safari.

    ReplyDelete
  3. The drop event is not firing on MacOSX safari. Any solution available?

    ReplyDelete