jQuery Droppable:如果该dropzone中没有其他元素,则只允许元素丢弃

时间:2018-01-17 17:17:00

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

我正在编写一个拼图,你必须将一个项目拖到正确的dropzone中。

问题:我希望您只能将项目拖放到dropzone中,如果该dropzone不包含任何其他项目。如何查看该dropzone中是否没有其他项目?

这是我当前谜题的GIF: enter image description here

这是一个显示问题的gif:

enter image description here

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

如果dropzone已经包含某个项目,则该用户不应该将另一个项目放入该dropzone中。我如何实现这一目标?

到目前为止我的脚本:

        $( ".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上已有几个主题有相同的问题。但是,我不够聪明,无法将建议的答案应用到我的案例中。请帮帮我。

EDIT1

这是一个显示我喜欢的行为的gif:

enter image description here

我把一个错误的单词拖进了一个dropzone。但只要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就会再次启用。但是我怎么能实现呢?

2 个答案:

答案 0 :(得分:1)

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

$(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>

答案 1 :(得分:0)

这里最简单的方法可能是以更通用的方式解决整个问题。为此,我将向各自的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>