【问题标题】:jQuery Droppable: Only allow element to drop, if there is no other element in that dropzonejQuery Droppable:如果该放置区域中没有其他元素,则仅允许放置元素
【发布时间】:2018-01-17 17:17:00
【问题描述】:

我正在写一个谜题,你必须将一个项目拖到正确的放置区中。

问题:我希望你只能将一个项目拖到一个拖放区中,如果该拖放区不包含任何其他项目。如何检查该放置区中是否没有其他项目?

这是我当前拼图的 GIF:

这是一个显示问题的 gif:

如您所见,我可以将多个项目拖到同一个放置区中。

如果放置区已经包含一个项目,用户应该不能将另一个项目放入该放置区。我如何做到这一点?

到目前为止我的脚本:

        $( ".draggable" ).draggable({ revert: 'invalid', snap: ".dropfield", snapTolerance: 30, snapMode: "inner"});

        $( ".dropfield" ).droppable({
            accept: ".dropling",
            drop: function( event, ui ) {

              if(some-condition){ // if correct word got dragged into the correct dropzone
                  var id = ui.draggable.attr('id');
                  $("#" + id).draggable( 'disable' );
                  $(this).droppable( 'disable' );
                  $("#" + id).css( "background-color", "#7FFF00");
            }
        });

HTML-摘录:

<div id="liebe" class="dropling draggable text-center">
  Liebe
</div>

   <span class="dropfield" value="scheitern">

    </span>

PS:Stack-Overflow 上已经有几个主题相同的问题。但是,我不够聪明,无法将建议的答案应用于我的案例。请帮帮我。

编辑1

这是一个 gif,显示了我的首选行为:

我将一个错误的单词拖入了放置区。但是只要那个dropzone被一个词占据,就没有其他词可以被拖放到那个dropzone中。

我当前的代码:

            if(some-condition){ //correct word


                $("#" + id).draggable( 'disable' );
                $(this).droppable( 'disable' );
                $("#" + id).css( "background-color", "#7FFF00");

                }
            } else { //wrong word
                console.log("wrong word dropped");
                $(this).droppable( 'disable' );
            }

一旦我将错误的单词拖出 dropzone,dropzone 应该会再次启用。但是我怎样才能做到这一点呢?

【问题讨论】:

  • 你可以在物品掉落后禁用.droppable()
  • @Twisty 这可以通过这样做来完成:$(this).droppable('disable');但是我怎样才能再次启用 droppable 呢?文档提到了“out”选项(将可拖动对象移出 dropzone),但效果并不好。首先,出于某种原因,out-function 有时不会触发,其次,如果您将可拖动项目移动到另一个放置区域上,而不放置它,则启用该放置区域,即使它仍然有一个项目。但也许我做错了。你能给我一些指示吗?
  • 我发布了一个答案。我怀疑它不会把你带到你想去的地方。它会让您前进,并可能帮助您实现目标。

标签: jquery-ui jquery-ui-draggable jquery-ui-droppable


【解决方案1】:

我建议将其分解为他们自己的功能。这样,您可以重复启用和禁用 drop。根据您提供的示例,不确定要触发项目再次变为可拖动和可放置的内容。根据您提供的内容,我可以提供以下示例。

$(function() {
  function enableDrop($target) {
    console.log("Enabled Drop");
    $target.droppable({
      accept: ".dropling",
      classes: {
        "ui-droppable-hover": "drop-target"
      },
      drop: function(event, ui) {
        var $that = $(this),
          dragWord = ui.draggable.text().trim(),
          $item = ui.draggable;
        if (checkWord(dragWord)) {
          console.log("Accepted: " + $item.attr("id"));
          $item.
          removeClass("draggable")
            .draggable('disable')
            .attr("style", "")
            .appendTo($that);
          disableDrop($that);
          $that.css("background-color", "#7FFF00");
        } else {
          return false;
        }
      }
    });
  }

  function disableDrop($target) {
    console.log("Disabling Drop on " + $target.attr("class"));
    $target.droppable("destroy");
  }

  function checkWord(w) {
    var result = false;
    console.log("Checked Word: " + w);
    if (w == "Liebe") {
      result = true;
    }
    return result;
  }

  $(".draggable").draggable({
    revert: 'valid',
    snap: ".dropfield",
    snapTolerance: 30,
    snapMode: "inner"
  });

  enableDrop($(".dropfield"));
});
p .dropfield {
  border: 1px solid #ccc;
  border-radius: 3px;
  display: inline-block;
  width: 4em;
  height: 1.5em;
  margin-bottom: -.25em
}

p .drop-target {
  border: 1px dashed #ccc;
  background-color: #ccc;
}

.text-center {
  text-align: center;
}

.draggable {
  border: 1px solid #ccc;
  border-radius: 3px;
  display: inline-block;
  width: 4em;
  height: 1em;
  padding: .25em 0;
  margin-bottom: -.25em
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<p>Diese Schlussfolgerung ist <span class="dropfield" value="scheitern"></span>: Ee kann doch nicht sein, dass es gut ist, </p>

<div id="liebe" class="dropling draggable text-center">Liebe</div>
<div id="absurd" class="dropling draggable text-center">absurd</div>

【讨论】:

    【解决方案2】:

    这里最简单的方法可能是以更通用的方式解决整个问题。为此,我将向相应的 Dom 元素(数据计数)添加一个属性,然后检查包含多少个字符以及仍然允许多少个字符:

    请参阅/** ADDED **/ 了解我所做的事情:

    $(function() {
      function textWrapper(str, sp, btn) {
        if (sp == undefined) {
          sp = [0, 0];
        }
        var txt = "";
        if (btn) {
          txt = "<span class='w b'>" + str + "</span>";
        } else {
          txt = "<span class='w'>" + str + "</span>";
        }
    
        if (sp[0]) {
          txt = "&nbsp;" + txt;
        }
    
        if (sp[1]) {
          txt = txt + "&nbsp;";
        }
    
        return txt;
      }
    
      function chunkWords(p) {
        var words = p.split(" ");
        words[0] = textWrapper(words[0], [0, 1]);
        var i;
        for (i = 1; i < words.length; i++) {
          var re = /\[.+\]/;
          if (re.test(words[i])) {
            var b = makeTextBox(words[i].slice(1, -1));
            words[i] = "&nbsp;" + b.prop("outerHTML") + "&nbsp;";
          } else {
            if (words[0].indexOf(".")) {
              words[i] = textWrapper(words[i], [1, 0]);
            } else {
              words[i] = textWrapper(words[i], [1, 1]);
            }
          }
        }
        return words.join("");
      }
    
      function unChunkWords(tObj) {
        var words = "";
        $(tObj).contents().each(function(i, el) {
          if ($(el).hasClass("b")) {
            words += "[" + $(el).text() + "]";
          } else {
            words += $(el).text();
          }
        });
        return words.replace(/\s+/g, " ").trim();
      }
    
      function makeBtn(tObj) {
        var btn = $("<span>", {
          class: "ui-icon ui-icon-close"
        }).appendTo(tObj);
      }
    
      function makeTextBox(txt) {
        var sp = $("<span>", {
          class: "w b"
        }).html(txt);
        makeBtn(sp);
        return sp;
      }
    
      function makeDropText(obj) {
        return obj.droppable({
          drop: function(e, ui) {
            var txt = ui.draggable.text();
            var newSpan = textWrapper(txt, [1, 0], 1);
            $(this).after(newSpan);
            makeBtn($(this).next("span.w"));
            makeDropText($(this).next("span.w"));
            $("span.w.ui-state-highlight").removeClass("ui-state-highlight");
            
            update()
          },
          over: function(e, ui) {
            $(this).add($(this).next("span.w")).addClass("ui-state-highlight");
          },
          out: function() {
            $(this).add($(this).next("span.w")).removeClass("ui-state-highlight");
          }
        });
      }
    
      $("p.given").html(chunkWords($("p.given").text()));
    
      $("p.given").on("click", ".b > .ui-icon", function() {
        $(this).parent().remove();
      });
    
      $("p.given").blur(function() {
        var w = unChunkWords($(this));
        $(this).html(chunkWords(w));
        makeDropText($("p.given span.w"));
      });
    
      $("span.given").draggable({
        helper: "clone",
        revert: "invalid"
      });
    
      makeDropText($("p.given span.w"));
    
      /** ADDED **/
      // update at beginning
      update();
      // register update events
      $("p.given").on('click keydown keyup drag drop', update);
      
      
      function update(e) {
        var templateText = unChunkWords($("p.given"));
        var templateTextWithoutParameters = templateText.replace(/\[(.+?)\]/g, "");
        var templateTextWithoutParametersLenght = templateTextWithoutParameters.length;
    
        // calc total length
        var totalLength = templateTextWithoutParametersLenght;
        // since 'helper: clone' we have to ignore it!
        $("[data-count]:not(.ui-draggable-dragging)").each(function(index, item) {
          var count = $(item).attr("data-count")
          var text = "[" + $(item).text() + "]";
          var length = templateText.split(text).length - 1;
          totalLength += count * length;
        }); 
    
        // 46,8 keycodes for delete & backspace
        var maxLength = 200;
        if (totalLength >= maxLength && e && e.keyCode !== 46 && e.keyCode !== 8) {
          e.preventDefault();
        }
    
        // disable data counts
        var remaining = maxLength - totalLength;
        $("[data-count]:not(.ui-draggable-dragging)").each(function(index, item) {
          var count = $(item).attr("data-count");
          if (parseInt(count) > remaining) {
            $(item).attr("disabled", true);
            $(item).draggable().draggable('disable');
          } else {
            $(item).attr("disabled", false);
            $(item).draggable().draggable('enable');
          }
        })
    
        $(".output").text(totalLength);
      }
    });
    p.given {
      display: flex;
      flex-wrap: wrap;
    }
    
    p.given span.w span.ui-icon {
      cursor: pointer;
    }
    
    div.blanks {
      display: inline-block;
      min-width: 50px;
      border-bottom: 2px solid #000000;
      color: #000000;
    }
    
    div.blanks.ui-droppable-active {
      min-height: 20px;
    }
    
    span.answers>b {
      border-bottom: 2px solid #000000;
    }
    
    span.given {
      margin: 5px;
    }
    
    /** ADDED **/
    [disabled] {
      color: grey
    }
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <div class="row">
      <p class="given" contenteditable="true">Lorem Ipsum is [Test] Ipsum has been the industry's [America] standard dummy text ever since the 1500s, </p>
    </div>
    
    <div class="divider"></div>
    <div class="section">
      <section>
        <div class="card blue-grey ">
          <div class="card-content white-text">
            <div class="row">
              <div class="col s12">
                <span class="given btn-flat white-text red lighten-1" rel="1" data-count="50">Test</span>
                <span class="given btn-flat white-text red lighten-1" rel="2" data-count="30">America</span>
                <span class="given btn-flat white-text red lighten-1" rel="3" data-count="20">Qatar</span>
                <span class="given btn-flat white-text red lighten-1" rel="4" data-count="10">Philippines</span>
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
    
    
    <div class="divider"></div>
    Count: <span class="output"></span>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-18
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多