Skip to content
Snippets Groups Projects
DragAndDrop.js 8.92 KiB
/**
 * @author Benjamin Baer <benjamin.baer@math.uzh.ch>
 */

/* global $ */
/* global EventEmitter */
/* @depend QfqEvents.js */
/* @depend Alert.js */
/* @depend ElementUpdate.js */

/**
 * Qfq Namespace
 *
 * @namespace QfqNS
 */
var QfqNS = QfqNS || {};

(function (n) {
    'use strict';

    /**
     *
     */
    n.DragAndDrop = function ($hook) {
        this.$container = $hook;
        this.eventEmitter = new EventEmitter();
        this.dropZones = [];
        this.elements = [];
        this.active = false;
        this.api = $hook.data("dnd-api");
        this.draggedId = "";
        this.lastChild = "";
        this.$tempObject = {};
    };

    n.DragAndDrop.prototype.on = n.EventEmitter.onMixin;

    n.DragAndDrop.prototype.buildDropArea = function(position, relatedId, otherPos) {
        var that = this;
        var $dropArea = {};

        if (this.$container.data("columns")) {
            $dropArea = $("<tr />", {
                class: "qfqDropTarget"
            });
            var $fluff = $("<td />", {
                class: "qfqDropTarget",
                colspan: this.$container.data("columns")
            });
            $fluff.appendTo($dropArea);
        } else {
            $dropArea = $("<div />", {
                class: "qfqDropTarget"
            });
        }

        $dropArea.data("position", position);
        $dropArea.data("related", relatedId);
        $dropArea.data("other-pos", otherPos);
        $dropArea.on("dragenter", function(e) {
            e.preventDefault();
            $dropArea.addClass("qfqTargetDisplay");
        });
        $dropArea.on("dragover", function(e) {
            e.preventDefault();
            e.originalEvent.dataTransfer.dropEffect = "move";
        });
        $dropArea.on("drop", function(e) {
            e.originalEvent.preventDefault();
            that._moveObjectBefore(e, $dropArea);
        });

        return $dropArea;
    };

    n.DragAndDrop.prototype.setDropZones = function($objects) {
        var that = this;

        $objects.each(function() {
            var $dropZone = $(this);
            $dropZone.on("dragenter", function(e) {
                e.preventDefault();
                $dropZone.addClass("qfqTargetDisplay");
                e.Effect = "all";
                that._handleDragEnter(e);
            });
            $dropZone.on("dragleave", function(e) {
                e.preventDefault();
                $dropZone.removeClass("qfqTargetDisplay");
                that._handleDragLeave(e);
            });
            $dropZone.on("dragover", function(e) {
                e.preventDefault();
                e.stopPropagation();
            });
            $dropZone.on("drop", function(e) {
                e.preventDefault();
                e.stopPropagation();
                that._dropHandler(e);
            });
            $dropZone.css("z-index", 5);
            that.dropZones.push($dropZone);
        });
    };

    n.DragAndDrop.prototype.setElements = function($objects) {
        var that = this;

        $objects.each(function() {
            var $element = $(this);
            $element.prop("draggable", true);
            $element.on("dragstart", function(e) {
                that.draggedId = $element[0].id;
            });
            that.elements.push($element);
        });
    };

    n.DragAndDrop.prototype._handleDragEnter = function(event) {
        var $tempObject = $("#" + this.draggedId).clone();
        $tempObject.css("opacity", 0.5);
        $tempObject.css("z-index", 0);
        $tempObject.off();
        if (this.$tempObject[0]) {
            if ($tempObject[0].id !== this.$tempObject[0].id) {
                this.$tempObject = $tempObject;
                this.$tempObject.appendTo($("#" + event.currentTarget.id));
            }
        } else {
            this.$tempObject = $tempObject;
            this.$tempObject.appendTo($("#" + event.currentTarget.id));
        }
    };

    n.DragAndDrop.prototype._handleDragLeave = function(event) {
        if(this.$tempObject[0]) {
            this.$tempObject.remove();
            this.$tempObject = {};
        }
    };

    n.DragAndDrop.prototype.makeBasketCase = function() {
        var dzSelector = this.$container.data("dnd-dropzone") || false;
        var elSelector = this.$container.data("dnd-element") || false;

        if (elSelector) {
            this.setElements($("." + elSelector));
        }
        if (dzSelector) {
            this.setDropZones($("." + dzSelector));
        }
    };

    n.DragAndDrop.prototype._dropHandler = function(event) {
        if(this.$tempObject[0]) {
            this.$tempObject.remove();
            this.$tempObject = {};
        }
        $("#" + this.draggedId).appendTo($("#" + event.currentTarget.id));
    };

    n.DragAndDrop.prototype._buildOrderDropZones = function($object, e) {
        this.removeDropAreas();

        //if ($object[0].id !== this.draggedId) {
            //if ($object.data("dnd-position") !== $("#" + this.draggedId).data("dnd-position") + 1) {
                var $dropArea = this.buildDropArea("before", $object.data("dnd-id"), $object.data("dnd-position"));
                //$dropArea.hide();
                $object.before($dropArea);
                //$dropArea.slideDown(500, 'swing');

                var $lastDrop = this.buildDropArea("after", $object.data("dnd-id"), $object.data("dnd-position"));
                //$lastDrop.hide();
                $object.after($lastDrop);
                //$lastDrop.slideDown(500, 'swing');
                //$lastDrop.appendTo(this.$container);
            //}

            /*if ($object[0].id === this.lastChild) {
                var $lastDrop = this.buildDropArea("after", $object.data("dnd-id"), $object.data("dnd-position"));
                $lastDrop.appendTo(this.$container);
            }*/
        //}
    };

    n.DragAndDrop.prototype.removeDropAreas = function() {
        if (this.$container.data("column")) {
            this.$container.children(".qfqTempTable").remove();
        }

        this.$container.children(".qfqDropTarget").remove();
    };

    n.DragAndDrop.prototype.removeDropTarget = function(e) {
        console.log(e);
    };

    n.DragAndDrop.prototype.makeSortable = function() {
        var that = this;
        var numberOfChildren = this.$container.children().length;
        var count = 0;

        this.$container.children().each( function() {
            count++;

            var child = $(this);
            if (numberOfChildren === count) {
                that.lastChild = child[0].id;
            }
            child.data("dnd-position", count);
            child.prop("draggable", true);
            child.on("dragstart", function(e) {
                e.originalEvent.dataTransfer.setData("text", child[0].id);
                that.draggedId = child[0].id;
                that.active = true;
                e.originalEvent.dataTransfer.effectAllowed = "move";
            });
            child.on("dragenter", function(e) {
                if (that.active) {
                    that._buildOrderDropZones($(this), e);
                }
            });
            child.on("dragend", function() {
                that.active = false;
                that.removeDropAreas();
            });
        });
    };

    n.DragAndDrop.prototype._moveObjectBefore = function(e, $hook) {
        var id = e.originalEvent.dataTransfer.getData("text");
        var $object = $("#" + id);
        var posTo = $hook.data("position");

        if (posTo === "after") {
            this.lastChild = $object[0].id;
        }

        $hook.before(document.getElementById(id));
        this._buildOrderUpdate($object, $hook.data("position"), $hook.data("related"), $hook.data("other-pos"));
        this.removeDropAreas();
    };

    n.DragAndDrop.prototype._buildOrderUpdate = function($object, position, otherId, otherPos) {
        var jObject = {};
        jObject.dragId = $object.data("dnd-id");
        jObject.dragPosition = $object.data("dnd-position");
        jObject.setTo = position;
        jObject.hoverId = otherId;
        jObject.hoverPosition = otherPos;
        this._sendToAPI(jObject);
    };

    n.DragAndDrop.prototype._sendToAPI = function(object) {
        var that = this;
        $.getJSON(this.api, object, function(data) {
            that._successHandler(data);
        });
    };

    n.DragAndDrop.prototype._successHandler = function(data) {
        if (data.status === "error") {
            var alert = new n.Alert({
                type: data.status,
                message: data.message,
                modal: true,
                buttons: [{
                    label: "Ok", eventName: "ok"
                }]
            });
            alert.show();
            console.error(data.message);
        } else {
            console.log("status:" + data.status + " message: " + data.message);
            if (data['element-update']) {
                var configuration = data['element-update'];
                n.ElementUpdate.updateAll(configuration);
            }
        }
    };

})(QfqNS);