//WEBCOMpro CMS © Patrick Heyer, www.webcompro-cms.com

var dd_registry      = new Array();
var dd_object        = null;
var dd_vehicle       = null;
var dd_touched       = null;
var dd_callback      = null;
var dd_onselectstart = null;
var dd_left          = 0;
var dd_top           = 0;
var dd_nofx          = false;
var dd_flag          = false;
var dd_no_cropping   = false;
var dd_scroll_flag   = false;
var dd_scroll_x      = 0;
var dd_scroll_y      = 0;

function dd_register(object,
                     type,
                     accept) //arguments: 3 => fixed, 4 => no effect
{
        if (typeof object != "object")
        {
                object = document.getElementById(object);
                if (typeof object != "object") return false;
        };

        //property
        object.dd_type       = type;
        object.dd_accept     = accept;
        object.dd_fixed      = (dd_register.arguments.length > 3) &&
                               (dd_register.arguments[3] == true);
        object.dd_nofx       = (dd_register.arguments.length > 4) &&
                               (dd_register.arguments[4] == true);

        //event
        object.ondragstart   = new Function("return false;");
        object.onmousedown   = new Function("return false;");
        object.onselectstart = new Function("return false;");

        //add object
        var zindex           = dd_registry.length;
        dd_registry[zindex]  = object;
};
//................................
/*
 * set callback function
 *
 * example:
 * function my_callback_function(my_event, my_source, my_target) { ... };
 * dd_set_callback(my_callback_function);
 *
 * possible values for my_event:
 * "activate",        "dblclick", "select",
 * "beforedragstart", "dragstart",
 * "dragover",        "drag",
 * "dropon",          "drop"
 */
function dd_set_callback(callback)
{
        dd_callback = callback;
};
//................................
function dd_get_object()
{
        var object, parent, _object = null,
            x, y, z, _z = 0;

        for (var i = 0; i < dd_registry.length; i++)
        {
                object = dd_registry[i];

                if (
                     ((dd_object == null) || (dd_object != object))
                     &&
                     (fx_mouse_x >= (x = dd_no_cropping ? fx_left(object) : fx_offset_left(object)))
                     &&
                     (fx_mouse_y >= (y = dd_no_cropping ? fx_top(object)  : fx_offset_top(object)))
                     &&

                //check uncropped dimensions first to enhance performance
                     (fx_mouse_x <= (x + fx_width(object, true)))
                     &&
                     (fx_mouse_y <= (y + fx_height(object, true)))
                     &&

                //now check cropped dimensions if required
                     (
                       dd_no_cropping
                       ||
                       (
                         (fx_mouse_x <= (x + fx_width(object)))
                         &&
                         (fx_mouse_y <= (y + fx_height(object)))
                       )
                     )
                   )
                {
                        parent = object;
                        z      = 0;

                        while ((parent = parent.parentNode) != null) z++;

                        if ((_object == null) || (z > _z))
                        {
                                _object = object;
                                _z      = z;
                        };
                };
        };

        return _object;
};
//................................
function dd_scroll()
{
        dd_scroll_flag = true;

        if (dd_object == null)                        { dd_scroll_flag = false; return; };
        if ((dd_scroll_x == 0) && (dd_scroll_y == 0)) { dd_scroll_flag = false; return; };

        //store position
        var left = fx_page_left();
        var top  = fx_page_top();

        //scroll
        window.scrollBy(dd_scroll_x, dd_scroll_y);

        //check position change
        if (fx_page_left() == left) dd_scroll_x = 0;
        if (fx_page_top()  == top)  dd_scroll_y = 0;

        if ((dd_scroll_x == 0) && (dd_scroll_y == 0)) { dd_scroll_flag = false; return; };

        setTimeout("dd_scroll();", 100);
};
//................................
function dd_event(event)
{
        switch (event)
        {
        case "mousedown":
                var object = dd_get_object();
                if (object == null)     return; //no target

                //global
                dd_left    = fx_mouse_x;
                dd_top     = fx_mouse_y;
                dd_flag    = (fx_keyboard_key == 16) || //shift
                             (fx_keyboard_key == 17) || //ctrl
                             (fx_keyboard_key == 18);   //alt

                //set source
                dd_object  = object;

                if (dd_object.dd_fixed) return; //fixed
                break;

        case "mousemove":
                if (dd_object == null)  return; //no source
                if (dd_object.dd_fixed) return; //fixed

                //start drag action
                if (dd_vehicle == null)
                {
                        //element has not been moved away from initial position yet
                        if (Math.sqrt(Math.pow(fx_mouse_x - dd_left, 2) +
                                      Math.pow(fx_mouse_y - dd_top,  2)) <= 10.0)
                                return;

                        //callback
                        if (dd_callback != null) dd_callback("beforedragstart", dd_object, null);

                        //create vehicle
                        dd_vehicle           = document.createElement("div");
                        dd_vehicle.className = "dd_vehicle";

                        with (dd_vehicle.style)
                        {
                                height   = "auto";
                                overflow = "hidden";
                                position = "absolute";
                                width    = "auto";
                                zIndex   = "10000";
                                opacity  = "0.75";
                                filter   = "Alpha(opacity=75)";
                        };

                        document.getElementsByTagName("body")[0].appendChild(dd_vehicle);

                        //clone selected object
                        var clone = dd_object.cloneNode(true);

                        //clean up clone
                        while (true)
                        {
                                //remove script
                                if (clone.nodeName == "SCRIPT")
                                {
                                        while (clone.hasChildNodes()) clone.removeChild(clone.firstChild);
                                };

                                //remove id attribute
                                if (clone.nodeType == 1) clone.removeAttribute("id");

                                //get child
                                if (clone.hasChildNodes())
                                {
                                        clone = clone.firstChild;
                                        continue;
                                };

                                //fall back to parent if no more siblings
                                while ((clone.parentNode != null) && (clone.nextSibling == null))
                                        clone = clone.parentNode;

                                if (clone.parentNode == null) break; //root

                                //get next sibling
                                clone = clone.nextSibling;
                        };

                        //fill vehicle
                        dd_vehicle.appendChild(clone);
                        dd_vehicle.firstChild.style.position = "static";

                        //adjust dimension
                        width  = fx_width(dd_vehicle);
                        if (width > 300)  width  = 300;
                        dd_vehicle.style.width  = (width - 10) + "px";

                        height = fx_height(dd_vehicle);
                        if (height > 150) height = 150;
                        dd_vehicle.style.height = (height - 10) + "px";

                        //prevent content selection
                        dd_onselectstart       = document.onselectstart;
                        document.onselectstart = new Function("return false;");

                        //callback
                        if (dd_callback != null) dd_callback("dragstart", dd_object, null);
                }

                //perform drag action
                else
                {
                        //scroll at page border
                        var page_left = fx_page_left();
                        var page_top  = fx_page_top();

                        if (fx_mouse_x < (page_left + 100))
                                dd_scroll_x = -100 + fx_mouse_x - page_left;
                        else if (fx_mouse_x > (page_left + fx_window_width - 100))
                                dd_scroll_x = 100 - fx_window_width + fx_mouse_x - page_left;
                        else
                                dd_scroll_x = 0;

                        if (fx_mouse_y < (page_top + 100))
                                dd_scroll_y = -100 + fx_mouse_y - page_top;
                        else if (fx_mouse_y > (page_top + fx_window_height - 100))
                                dd_scroll_y = 100 - fx_window_height + fx_mouse_y - page_top;
                        else
                                dd_scroll_y = 0;

                        if (! dd_scroll_flag) dd_scroll();

                        var object = dd_get_object();

                        //clear touched element
                        if (
                             (dd_touched != null)
                             &&
                             (object != dd_touched)
                           )
                        {
                                if (! dd_nofx)
                                {
                                        dd_touched.style.border = "0px none";
                                        dd_touched.style.margin = "0px";
                                };

                                dd_touched = null;
                        };

                        //perform drag over action
                        if (
                             (object != null) //object found
                             &&
                             ((object.dd_accept & dd_object.dd_type) != 0) //potential target
                           )
                        {
                                //cursor style
                                document.getElementsByTagName("body")[0].style.cursor = "default";

                                //set touched element
                                if (object != dd_touched)
                                {
                                        dd_touched = object;
                                        dd_nofx    = object.dd_nofx;

                                        if (! dd_nofx)
                                        {
                                                dd_touched.style.border = "2px dotted #4c691e";
                                                dd_touched.style.margin = "-2px";
                                        };
                                };

                                //callback
                                if (dd_callback != null) dd_callback("dragover", dd_object, object);
                        }

                        //default
                        else
                        {
                                //cursor style
                                document.getElementsByTagName("body")[0].style.cursor = "move";

                                //callback
                                if (dd_callback != null) dd_callback("drag", dd_object, null);
                        };
                };

                //position
                fx_move(dd_vehicle, fx_mouse_x + 10, fx_mouse_y + 5);
                break;

        case "mouseup":
                if (dd_object == null) return; //no source

                //callback
                if (dd_callback != null)
                {
                        //element is at initial position
                        if (
                             (dd_vehicle == null)
                             ||
                             (Math.sqrt(Math.pow(fx_mouse_x - dd_left, 2) +
                                        Math.pow(fx_mouse_y - dd_top,  2)) <= 10.0)
                           )
                        {
                                if (dd_flag)
                                        dd_callback("select", dd_object, null);
                                else
                                        dd_callback("activate", dd_object, null);
                        }

                        //element was moved away from initial position
                        else
                        {
                                if (dd_object.dd_fixed) break; //fixed

                                var object = dd_get_object();

                                if ((object != null) && ((object.dd_accept & dd_object.dd_type) != 0))
                                        dd_callback("dropon", dd_object, object);
                                else
                                        dd_callback("drop", dd_object, null);
                        }

                };

                //cursor style
                document.getElementsByTagName("body")[0].style.cursor = "auto";

                //clear source
                dd_object = null;

                //clear vehicle
                if (dd_vehicle != null)
                {
                        document.getElementsByTagName("body")[0].removeChild(dd_vehicle);
                        dd_vehicle = null;
                };

                //clear touched element
                if (dd_touched != null)
                {
                        if (! dd_nofx)
                        {
                                dd_touched.style.border = "0px none";
                                dd_touched.style.margin = "0px";
                        };

                        dd_touched = null;
                };

                //reset content selection
                document.onselectstart = dd_onselectstart;
                break;

        case "dblclick":
                var object = dd_get_object();
                if (object == null)     return; //no target

                dd_callback("dblclick", object, null);
        };
};

fx_register_callback(dd_event);
