I modified the HTML wrapper to use the JavaScript DnD and File API (if available) to listening for “dragenter”, “dragover” and “drop” events on the FlashPlayer container.
<markers>
<marker x="45" y="45" label="M 1" info="This is M1"/>
<marker x="-45" y="-45" label="M 2" info="This is M2"/>
</markers>
On dragenter, I stop the event propagation and prevent the default behavior. On dragover, I do the same and in addition, I update the drop effect to show a “+” icon over the drop area. And finally, on drop, I iterate over the list of dropped files, whereupon I read as text each file using the FileReader API. When the file is read (remember, this is all asynchronous), I hand over the content to the Flex application. On creation completion of the Flex application, the “drop” callback is registered using the EternalInterface enabling the host javascript wrapper to invoke the internal dropHandler function.
var DnD = {
loadHandler:function () {
var dropContainer = document.getElementById("DnDApp");
dropContainer.addEventListener("dragenter", function (event) {
event.stopPropagation();
event.preventDefault();
}, false);
dropContainer.addEventListener("dragover", function (event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}, false);
dropContainer.addEventListener("drop", function (event) {
event.stopPropagation();
event.preventDefault();
var files = event.dataTransfer.files, len = files.length;
for (var i = 0; i < len; i++) {
var file = files[i];
var fileReader = new FileReader();
fileReader.onload = function (event) {
dndApp.drop(event.target.result);
}
fileReader.readAsText(file);
}
}, false);
}
};
if( window.File && window.FileReader){
window.addEventListener("load", DnD.loadHandler, false);
} else {
alert('Your browser does not support File/FileReader !');
}
The latter accepts a String argument that is converted into an XML instance, and using E4X, each child marker element is converted to a Graphic that is added to a graphic layer graphic provider array collection. Cool, eh ? Note that the graphic layer has it infoWindowRenderer property defined, is such a way that if you click on any of its graphics, a info window content will be displayed whose content is an instance of the defined component. Like usual all the source code is available here. Have fun DnD’ing.
private function this_creationCompleteHandler(event:FlexEvent):void
{
ExternalInterface.call("setObjectID",
ExternalInterface.objectID);
ExternalInterface.addCallback("drop", dropHandler);
}
private function dropHandler(text:String):void
{
const doc:XML = new XML(text);
for each (var markerXML:XML in doc.marker)
{
const mapPoint:MapPoint = new WebMercatorMapPoint(
markerXML.@x,
markerXML.@y);
arrcol.addItem(new Graphic(
mapPoint,
null, {
label: markerXML.@label,
info: markerXML.@info }));
}
}
You can see the application in action by download the markers.xml file, and drag and drop it on the application running here.
PS: As of this writing, the two JS APIs work in Google Chrome 16 and later, Firefox 3.6 and later, Safari 6 will support the standard File API and our favorite (Not!) Internet Explorer 10 (Preview 2+). One of these days, will come back to this and use something like Dojo DnD to abstract me from all this - that will be a nice post!