2013-07-08 39 views
0

下面是一个使用jQuery UI的拖放代码示例:http://jsfiddle.net/kwMpH/7/jQuery UI的.detach()appendTo()DOM没有更新拖累内马上落

的“查看审批级别”试图展示其用户气泡落入哪些框中。它似乎工作,但有一种情况下,我可以打破它:

  1. 将一个元素拖到第一个审批级别。
  2. 点击“添加批准等级”
  3. 采取不同的元素,并将其从2级添加到新创建的 审批级次
  4. 移动泡沫比1平,然后迅速点击“查看审批级别”

值得注意的是,之所以我使用的分离和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(); 
} 
+0

克隆和原始而克隆仍在淡出都被计算在内。 –

回答

0

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

在开始:

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

在计数代码:

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

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

+0

jQuery UI本身会向助手添加一个类,这个助手是'ui-draggable-dragging',可以用来代替,但我可能倾向于坚持我自己处理自己的类。 –

+0

工作正常!很好的解释!你是一个拯救生命的人。 – doug78