如何使用 jQuery 拖放段落元素

How to use jQuery drag and drop with paragraph element

我需要使用 JQuery UI 创建一个可自定义的段落。

这是我的代码。

$(document).ready(function() {
  var given = $("p.given").text();

  var new_given = given.replace(/blank/g, '  <div class="blanks"></div>  ');
  $("p.given").html(new_given);

  function updateDroppables() {
    $("div.blanks").droppable({
      accept: "span.given",
      classes: {
        "ui-droppable-hover": "ui-state-hover"
      },
      drop: function(event, ui) {
        var dragedElement = ui.draggable.text();
        var dropped = ui.draggable;
        console.log(dropped);
        dropped.hide();
        console.log(dragedElement);
        $(this).replaceWith(
          " <span class='answers'><b class='blue-text' rel='" +
          ui.draggable.attr("rel") +
          "'>" +
          dragedElement +
          "</b> <a href='#' class='material-icons cancel md-16'>highlight_off</a></span> "
        );
      }
    });
  }

  updateDroppables();

  $("span.given").draggable({
    helper: "clone",
    revert: "invalid"
  });

  $(document).on("click", "a.cancel", function(e) {
    e.preventDefault();
    var rel = $(this).prev().attr('rel');
    console.log(rel);

    $(this)
      .parent()
      .replaceWith("<div class='blanks'></div>");
    updateDroppables();
    $('.btn-flat[rel=' + rel + ']').show();
  });
});
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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<p><b><i>In the text below some words are missing. Drag words from the box below to the appropriate place in the text. To undo an answer choice, drag the word back to the box below the text.</i></b></p>

<div class="row">
  <p class="given">
    He wants to get a better [blank] and earn more money. Managers set objectives, and decide [blank] their organization can achieve them. A defect can be caused [blank] negligen ce by one of the members of a team.
  </p>
</div>

<div class="divider"></div>
<br>
<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">the Santee, thDakota</span>
            <span class="given btn-flat white-text red lighten-1" rel="2">America</span>

            <span class="given btn-flat white-text red lighten-1" rel="3">Qatar</span>

            <span class="given btn-flat white-text red lighten-1" rel="4">Philippines</span>

          </div>
        </div>
      </div>
    </div>
  </section>
</div>

这行得通,但问题是在上面的代码中,可拖动组件只能添加到 [blank] 区域。我需要在段落的任意位置添加可拖动组件 <p> 我该怎么做?这是code pen sample,你可以玩看看上面的代码是如何工作的

简单我把上面的代码改成如下,

$("p.given").droppable({
  accept: "span.given",
  classes: {
    "ui-droppable-hover": "ui-state-hover"
  }

但它用拖动的组件替换了整个段落 <p>。如何将可拖动组件添加到段落 <p> 标记的任何位置。

  1. 用单词创建数组。
  2. 创建新片段:https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment#JavaScript
  3. 使用 forEach() 和 append 每个单词迭代数组 <span data-index="indexNumber">arrayWord</span> 到片段。
  4. 迭代后,将片段附加到您的 <p>
  5. 然后你会得到带有单独单词的句子。
  6. 为每个 span 元素添加 data-dropped-value 属性。
  7. on drop 拖动的元素将更新跨度,它将是 data-dropped-value="your dragged value".
  8. 然后您可以将此值附加到此范围。

  1. 放置时将文本追加到悬停的跨度上。
  2. 不需要

由于你要完成的事情很多,你需要准备的东西很多。这是一个非常粗略的例子。

$(function() {
  function textWrapper(str, sp) {
    if (sp == undefined) {
      sp = [
        0,
        0
      ];
    }
    var 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++) {
      if (words[0].indexOf(".")) {
        words[i] = textWrapper(words[i], [1, 0]);
      } else {
        words[i] = textWrapper(words[i], [1, 1]);
      }
    }
    return words.join("");
  }

  function makeBtn(tObj) {
    var btn = $("<span>", {
      class: "ui-icon ui-icon-close"
    }).appendTo(tObj);
    btn.click(function(e) {
      $(this).parent().remove();
    });
  }

  function makeDropText(obj) {
    return obj.droppable({
      drop: function(e, ui) {
        var txt = ui.draggable.text();
        var newSpan = textWrapper(txt, [1, 0]);
        $(this).after(newSpan);
        makeBtn($(this).next("span.w"));
        makeDropText($(this).next("span.w"));
        $("span.w.ui-state-highlight").removeClass("ui-state-highlight");
      },
      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()));

  $("span.given").draggable({
    helper: "clone",
    revert: "invalid"
  });

  makeDropText($("p.given span.w"));
});
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;
}
<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 simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, Lorem Ipsum is simply dummy text of the printing and typesetting industry.</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">the Santee, thDakota</span>
            <span class="given btn-flat white-text red lighten-1" rel="2">America</span>
            <span class="given btn-flat white-text red lighten-1" rel="3">Qatar</span>
            <span class="given btn-flat white-text red lighten-1" rel="4">Philippines</span>
          </div>
        </div>
      </div>
    </div>
  </section>
</div>

这会获取 <p> 中的当前文本,并使用不间断 Space 将每个单词换行。它试图遵守句子语法。

既然每个单词都被包裹起来了,我们就可以让每个单词都可以放下了。这假设一个词将落在前面的词上并突出显示它会落在中间的两个词。删除后,将创建一个新的 <span> 并附加到目标之后。我添加了一个 'x' 按钮来删除它。