【问题标题】:how drag and drop component as first word如何将组件拖放为第一个单词
【发布时间】:2020-03-08 09:51:46
【问题描述】:

我正在使用 jQuery UI 可拖动组件来添加可编辑的内容

。此代码可以找到,但我有一个小问题。问题是我不能将可拖动组件作为第一个单词拖放,我该如何解决这个问题?请帮我解决这个问题。

注意:当前功能不能中断。

我的代码如下:

$(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");
      },
      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));
    console.log(w);
    $(this).html(chunkWords(w));
    makeDropText($("p.given span.w"));
  });

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

【问题讨论】:

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


    【解决方案1】:

    您可以执行以下操作:

    1。判断是否插入之前第一个元素

    在拖动过程中:

    • 当可拖动元素悬停在文本中的第一个单词上时进行监控。
    • 如果是,请检查它是否更多地悬停在单词的左侧或右侧
    • 如果左边更多,则去掉第二个单词的高亮
    • 如果更靠右,则恢复第二个单词的高亮

    因此,此视觉指示将指示该单词是插入在第一个单词之后(2 突出显示)还是在它之前(1 突出显示)。

    2。相应地执行 drop

    当用户放下元素时:

    • 检查第一个单词是否突出显示,而不是其他。
    • 如果是这样,在当前单词之前插入新元素
    • 如果没有,则在当前单词之后插入新元素(就像已经完成一样)

    因此,您需要对代码进行两处更改才能使其正常工作:

    添加以下代码来实现第一部分:

    document.addEventListener("mousemove", function() {
        var $draggable = $(".ui-draggable-dragging");
        if (!$draggable.length) return; // nothing is being dragged
        var $highlighted = $(".ui-state-highlight");
        if (!$highlighted.length || $($highlighted).index() > 0) return; // first word is not highlighted
        // Get center x coordinate of the item that is being dragged
        var dragX = $draggable.offset().left + $draggable.width() / 2;
        // Get center x coordinate of the first word in the paragraph
        var firstX = $highlighted.offset().left + $highlighted.width() / 2;
        // If draggable is more on the left side of the first word, then only the first word should be highlighted
        if ((dragX < firstX) === ($highlighted.length < 2)) return; // Situation is as it should be
        // Toggle the highlight on the second word of the paragraph
        $highlighted.first().next("span.w").toggleClass("ui-state-highlight");
    });
    

    修改drop处理程序以实现第二部分:

    drop: function(e, ui) {
        var txt = ui.draggable.text();
        // Use proper jQuery to create a new span element
        var newSpan = $("<span>").addClass('w b').text(txt);
        // Determine if the element is being dropped on the first word, and only that one
        if (!$(".ui-state-highlight").last().index()) {
            $(this).before(newSpan, "&nbsp;"); // ...then prepend
        } else {
            $(this).after("&nbsp;", newSpan); // normal case
        }
        makeBtn(newSpan);
        makeDropText(newSpan);
        $("span.w.ui-state-highlight").removeClass("ui-state-highlight");
    },
    

    修复chunkWords

    由于某种原因,您在chunkWords 中硬编码了第一个单词(在索引 0 处)不能被删除——它总是被解释为纯文本(标记为粗体)。这也是您当前代码中的一个错误,您可以按如下方式重现它:

    • 在前两个单词之间插入一个单词
    • 编辑文本并删除第一个单词,使删除的单词成为第一个单词
    • 退出可编辑区域
    • 现在第一个单词不再是一个被删除的元素,而是一个带有“按钮”标记(方括号)的单词。

    您写道,现有行为不应中断,但从 cmets 我了解到您没有预料到这种行为。

    另一个问题是该函数中的以下条件:

    if (words[0].indexOf(".")) {
    

    ...想一想:为什么第一个词中的一个点会影响你的短语中另一个词的间距?你肯定打算这样做:

    if (words[i].indexOf(".")) {
    

    无论如何,我建议完全不要使用textWrapper,并在最后的join 中添加空格。以前没有。

    解决这两个问题,chunkWords 最终应该是这样的:

      function chunkWords(p) {
        var words = p.split(" "), b;
        for (var i = 0; i < words.length; i++) {
          if (/\[.+\]/.test(words[i])) {
            b = makeTextBox(words[i].slice(1, -1));
          } else {
            b = $("<span>").addClass("w").text(words[i]);
          }
          // do not pad the value with "&nbsp;" at this moment:
          words[i] = b.prop("outerHTML");
        }
        return words.join("&nbsp;"); // add the spaces here
      }
    

    由于这些更改 textWrapper 不再使用,您可以删除该功能。

    查看this fiddle中应用的更改

    【讨论】:

    • 谢谢你的回答先生,但现在问题是当我将一个单词作为第一个单词放到段落中时,我点击段落的外侧(blur event),第一个删除其行为的单词(其显示[ ] 大括号),请参阅此图像i.imgur.com/KvZFoXp.png。其他丢弃的组件完美地显示了行为。
    • 这是您的函数已经具有的行为。重现如下:在前两个词之间放一个词,然后编辑并删除第一个词,然后模糊。我在答案中添加了一个部分来改变这种行为。
    • 先生,我需要你的一个小主意。我需要从单词中禁用 contentEditable 选项(带有可移动选项的跨度),以实现我在 $("p.given").blur 事件中添加此代码($('.b').attr('contentEditable', false);)。它工作正常。页面加载时我需要做同样的事情。我该怎么做。我可以将contentEditable', false 属性添加到具有可移除选项的&lt;span&gt;。请提出想法
    • $(function() { 代码中直接使用相同的代码。
    • 这不起作用,先生,我认为这是因为b class 在 JS 函数中添加。所以我想我需要添加 sttribute adter 将 b 类添加到span
    猜你喜欢
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多