jQuery UI .detach()。appendTo()DOM在拖放过程中不会立即更新

时间:2013-07-08 17:54:17

标签: jquery jquery-ui drag-and-drop

以下是使用jquery ui拖放的代码示例:http://jsfiddle.net/kwMpH/7/

“显示批准级别”按钮会尝试显示哪些用户的气泡属于哪些框。它似乎有效但有一种情况我可以打破它:

  1. 将一个元素拖到第一个批准级别。
  2. 点击“添加审批级别”
  3. 获取不同的元素并将其添加到新创建的元素中     审批级别
  4. 将气泡从第2级移至第1级,然后快速单击“显示批准级别”
  5. 值得注意的是,我使用detach和appendTo的原因与此旧帖子的“表单提交”要求相同:

    以下是代码:

        <div class="container">
        <div class="topInstructions">Drag and Drop a one or more categories of users to one or more approval levels.</div>
        <div class="workFlowNameArea">
            <div class="workFlowNameSubArea">
                <div style="font-weight:bold;">Work Flow Name</div>
                <div>
                    <input type="text" name="workFlowName" id="workFlowName" maxlength="100" width="50" />
                </div>
            </div>
            <div class="workFlowNameSubArea" style="margin-left: 20px; margin-top: 17px;">
                <input id="saveButton" type="button" value="Save" />
            </div>
            <div class="workFlowNameSubArea" style="margin-left: 20px; margin-top: 17px;">
                <input id="addApprovalLevel" type="button" value="Add Approval Level" />
            </div>
            <div class="workFlowNameSubArea" style="margin-left: 20px; margin-top: 17px;">
                <input id="showState" type="button" value="Show State" />
            </div>
            <div class="workFlowNameSubArea" style="margin-left: 20px; margin-top: 17px;">
                <input id="appLevel" type="button" value="Show approval Levels" />
            </div>
        </div>
        <div class="dropGroup">
            <div id="approval1" class="approvalText">Approval Level 1
                <div id="deleteApproval1" class="deleteApproval" style="visibility: hidden;">
                    <img src="/images/redX.gif" />
                </div>
                <div id="droppable1" class="droppable"></div>
            </div>
            <div id="arrow1" class="arrow">
                <img src="/images/arrow_in_circle_down.png" />
            </div>
            <div id="ellipsis1" class="ellipsis">
                <img src="/images/ellipsis.png" />
            </div>
        </div>
        <div class="choices">
            <div class="approvalText">Categories</div>
            <div class="draggable" title="click and drag to an approval level" style="background: #CC0000; color: #fff;">System Administrators</div>
            <div class="draggable" title="click and drag to an approval level" style="background: #FF9933; color: #000;">Administrators</div>
            <div class="draggable" title="click and drag to an approval level" style="background: #FFFF00; color: #000;">Managers</div>
            <div class="draggable" title="click and drag to an approval level" style="background: #99FF66; color: #000;">Instructors</div>
            <div class="draggable" title="click and drag to an approval level" style="background: #66CCFF; color: #000;">School Administrators</div>
            <div class="draggable" title="click and drag to an approval level" style="background: #6600FF; color: #fff;">Users</div>
            <div class="clonable" title="click to create a custom group" style="background: #999; color: #fff;">Custom</div>
        </div>
    </div>
    .draggable {
        width: 100px;
        height: 35px;
        display: inline-block;
        margin-top: 10px;
        margin-bottom: 10px;
        border: 2px solid #000;
        border-radius: 15px;
        -webkit-border-radius: 15px;
        -khtml-border-radius: 15px;
        -moz-border-radius: 15px;
        text-align: center;
        line-height: normal;
        vertical-align: middle;
        font-weight: bold;
        font-family: arial;
        font-size: 12px;
        cursor: pointer;
    }
    .clonable {
        width: 100px;
        height: 35px;
        display: inline-block;
        margin-top: 10px;
        margin-bottom: 10px;
        border: 2px solid #000;
        border-radius: 15px;
        -webkit-border-radius: 15px;
        -khtml-border-radius: 15px;
        -moz-border-radius: 15px;
        text-align: center;
        line-height: normal;
        vertical-align: middle;
        font-weight: bold;
        font-family: arial;
        font-size: 12px;
        cursor: pointer;
    }
    .droppable {
        width: 150px;
        height: 75px;
        margin: 10px;
        border-color: #999;
        color: #999;
        border-style: dashed;
        margin-left: auto;
        margin-right: auto;
    }
    .topInstructions {
        position: relative;
        float: top;
        margin-top: 5px;
        margin-bottom: 10px;
        text-align: center;
        font-family: arial;
        font-size: 16px;
    }
    .dropGroup {
        position: relative;
        float: right;
        margin-right: 100px;
        color: #999;
        text-align: center;
        width: 300px;
        height: 450px;
        margin-top: 5px;
    }
    .choices {
        position: relative;
        text-align: center;
        float: left;
        width: 150px;
        height: 430px;
        margin-left: 75px;
        margin-top: 5px;
    }
    .approvalText {
        color: #999;
        font-family: arial;
        font-size: 12px;
    }
    .deleteApproval {
        color: red;
        display: inline-block;
        cursor: hand;
        cursor: pointer;
    }
    .workFlowNameArea {
        position: relative;
        float: top;
        width: 680px;
        margin-left: 75px;
        margin-bottom: 15px;
    }
    .workFlowNameSubArea {
        display: inline-block;
        float: left;
    }
    .container {
        width: 680px;
        position: relative;
    }
    var globalElement;
    
    $(document).ready(function () {
    
        $(".draggable").draggable({
            helper: "clone",
            revert: true,
            containment: "document",
            start: function (event, ui) {
                globalElement = $(this);
            },
            stop: function (event, ui) {
                globalElement = null;
            }
        });
    
        $(".droppable").droppable({
            accepts: ".draggable",
            tolerance: "intersect",
            drop: function (event, ui) {
                dropFunction($(this), event, ui);
            }
        }).hover(function () {
            if ($(this).find(".draggable").length < 1) {
    
            }
        });
    
        $(".choices").droppable({
            accepts: ".draggable",
            tolerance: "intersect",
            drop: function (event, ui) {
                dropFunction($(this), event, ui);
            }
        });
    
        $(".clonable").click(function () {
            //TODO pop up for user list
        });
        $(".startOverButton").click(function () {
            // is this possible?
        });
        $("#addApprovalLevel").click(function () {
            addNextApprovalLevel();
        });
        $("#saveButton").click(function () {
            saveWorkflow();
            console.log("approval levels\n");
            $(".droppable").each(function (index) {
                console.log((index + 1) + ":" + $(this).find(".draggable").length + ":" + $(this).find(".draggable").text());
            });
        });
        $("#showState").click(function () {
            alert(state);
        });
        $("#appLevel").click(function () {
            // this does not work in drop function but does work here... maybe because drop is not completely done?
            //console.log("approval levels");
            for (i = 0; i < 1000; i++){}
            var str = "approval levels";
            $(".droppable").each(function (index) {
                str += "" + (index + 1) + ":" + $(this).find(".draggable").length + ":" + $(this).find(".draggable").text() + "\n";
            });
            alert(str);
    
        });
    
    });
    
    var state = new Array();
    
    
    function dropFunction(jObj, event, ui) {
    
        if (globalElement != null) {
            ui.helper.fadeOut();
            globalElement.detach().appendTo(jObj);
            $(jObj).css("border-color", "#999");
    
            drpGroup = $(".dropGroup").height();
            net = 0;
            $.each($(".droppable"), function (i, drp) {
                oldHeight = $(drp).height();
                newHeight = ($(drp).find(".draggable").length * 45) + 75;
                $(drp).css("height", newHeight);
                net += newHeight - oldHeight;
                //console.log("old = " + oldHeight + ", new = " + newHeight + ", net = " + net);
            });
            drpGroup += net;
            $(".dropGroup").css("height", drpGroup);
            //console.log("new drop group height = " + $(".dropGroup").height());
        } else {
            //console.log("too fast!");
        }
    }
    
    function addNextApprovalLevel() {
        var curHighest = $(".droppable").length;
        $("#ellipsis" + curHighest).remove();
        var nextLevelNum = curHighest + 1;
        var newApprovalText = "<div id='approval" + nextLevelNum + "'>Approval Level " + nextLevelNum + "&nbsp;&nbsp;<div id='deleteApproval" + nextLevelNum + "' class='deleteApproval'><img src='/images/redX.gif' /></div>" + "</div>";
    
        var newApprovalBox = $("<div id='droppable" + nextLevelNum + "' class='droppable'>" + "</div>");
        //$("#droppable" + curHighest).clone().attr("id", "droppable" + nextLevelNum);
    
    
        $(newApprovalBox).droppable({
            accepts: ".draggable",
            tolerance: "intersect",
            drop: function (event, ui) {
                dropFunction($(this), event, ui);
                //$("#droppable1").css("height", $("#droppable1").find(".draggable").length * 75);
                //console.log($("#droppable1").find(".draggable").length + "\n" +
                //      $("#droppable1").find(".draggable").text() );
            }
        });
        $("#arrow" + curHighest).css("margin-bottom", "5px");
        $(".dropGroup").append(newApprovalText);
        $(".dropGroup").append(newApprovalBox);
        var newArrow = "<div id='arrow" + nextLevelNum + "' class='arrow'><img src='/images/arrow_in_circle_down.png' /></div>";
        var newEllipsis = "<div id='ellipsis" + nextLevelNum + "' class='ellipsis'><img src='/images/ellipsis.png' /></div>";
        $(".dropGroup").append(newArrow);
        $(".dropGroup").append(newEllipsis);
        $(".dropGroup").css("height", $(".dropGroup").height() + 170);
    
        $("#deleteApproval" + nextLevelNum).click(function () {
            if ($("#droppable" + nextLevelNum).parent().find(".draggable").length >= 1) {
                alert("A user category must first be removed before an approval level can be deleted.");
            } else {
                deleteApprovalBox($(this));
            }
        });
    }
    
    function deleteApprovalBox(jqAppBox) {
        level = parseInt($(jqAppBox).attr("id").substring("deleteApproval".length));
        $("#approval" + level).remove();
        $("#droppable" + level).remove();
        $("#arrow" + level).remove();
        level++;
        while ($("#approval" + level).length) {
            $("#approval" + level).html("Approval Level " + (level - 1) + "&nbsp;&nbsp;<div id='deleteApproval" + (level - 1) + "' class='deleteApproval'><img src='/images/redX.gif' /></div>");
            $("#approval" + level).attr("id", "approval" + (level - 1));
            $("#droppable" + level).attr("id", "droppable" + (level - 1));
            $("#arrow" + level).attr("id", "arrow" + (level - 1));
    
            $("#deleteApproval" + (level - 1)).click(function () {
                if ($("#droppable" + (level - 1)).parent().find(".draggable").length >= 1) {
                    alert("A user category must first be removed before an approval level can be deleted.");
                } else {
                    deleteApprovalBox($(this));
                }
            });
            level++;
        }
        level--;
        if ($("#ellipsis" + level).length == 1) {
            $("#ellipsis" + level).attr("id", "ellipsis" + (level - 1));
        }
    }
    
    function saveWorkflow() {
    
    
        // validate the name    
        var alphaNum = new RegExp(/^([\sa-zA-Z0-9_-]+)$/);
        if ($("#workFlowName").val().length < 1) {
            alert("Work flow name must be between 1 and 100 characters.");
            return false;
        }
        if (!alphaNum.test($("#workFlowName").val())) {
            alert("Invalid Work flow name.  Must have numbers or letters.");
            return false;
        }
    
        // check if there are no empty
    
        // check if any approval levels are empty
        if ($(".droppable").length > 1) {
            $.each($(".droppable"), function (i, drp) {
                //console.log(i + ":" + $(drp).find(".draggable").length);
                if ($(drp).find(".draggable").length < 1) {
                    $(drp).css("border-color", "red");
                    alert("Approval Level " + (i + 1) + " is empty.  Delete?");
                    // TODO, implement an approval level delete method hooked into the NO of the YES/NO             
                    return;
                }
            });
        }
    
        //var findResult = $("#droppable1").find(".draggable");
    
        // remove ellipis... do we need to do this?
        //var curHighest = $(".droppable").length;
        //$("#ellipsis" + curHighest).remove();
    }
    

1 个答案:

答案 0 :(得分:0)

您正在使用helper: clone并在删除后淡出帮助程序。当这个淡入淡出正在进行时,帮助程序将被计数(在原始框中)以及原始元素(在新框中计算)。这导致拖动的元素在两个框中计数。您需要从容器中删除帮助程序或以某种方式不计算它。一种选择是向助手添加一个类,以将其与真实元素区分开来。像这样:

开始时:

ui.helper.addClass("ui-helper");

在计数代码中:

$(this).find(".draggable").not(".ui-helper").length

http://jsfiddle.net/kwMpH/10/