【问题标题】:How can I type text after dropped content删除内容后如何输入文本
【发布时间】:2020-03-15 07:04:43
【问题描述】:

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

。这段代码可以找到,我有一些小问题。问题是当我将可拖动组件作为段落的最后一个单词放置时。我无法在删除的组件之后键入文本。

第二个问题是,我需要从单词中禁用 contentEditable 选项(带有可移动选项的跨度),以实现我在 $("p.given").blur 事件中添加此代码 ($('.b').attr('contentEditable', false);)。它工作正常。页面加载时我需要做同样的事情。我该怎么做?我可以添加只有可移除选项的contentEditable = false 属性吗?

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

我的代码如下:

<link rel="stylesheet" href="http://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>
<style>
p.given {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
  display: flex;
  flex-wrap: wrap;
  cursor: pointer !important;

}

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;
}

.w ui-droppable{

cursor: pointer !important;
}

.w.b.ui-droppable {
  background: #FF8;
  color: #000;
}

.given.btn-flat {
  display: inline-block;
  padding: 0.25em 0.5em;
  border-radius: 1em;
  background: #A72020;
  color: #FFF;
  cursor: pointer;
}

.ui-draggable-dragging {
  background: #FFD700 !important;
}
</style>
<div class="row">
  <p id="doc_navc" 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 id="walkinDiv" 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">FirstName</span>
            <span class="given btn-flat white-text red lighten-1" rel="4">LastName</span>
          </div>
        </div>
      </div>
    </div>
  </section>
</div>

<input name="Go" id="btnPass" class="tstHeck" type="button" value="Go" onclick=""/>
<input name="Go" id="btnTxt" class="tstHeck" type="button" value="Go" onclick=""/>



<script language="javascript" type="text/javascript">

$(function() {

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");
});

   function chunkWords(p) {
   console.log("sasasa");
    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
  }


    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);
    $('span.b').attr('contentEditable', false);
  }

  function makeTextBox(txt) {
    var sp = $("<span>", {
      class: "w b"
    }).html(txt);
    $('.b').attr('contentEditable', false);
    makeBtn(sp);
    return sp;
  }

  function makeDropText(obj) {
    return obj.droppable({
        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");
        },
      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"));
    $('.b').attr('contentEditable', false);
  });


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

  makeDropText($("p.given span.w"));
});


</script>

【问题讨论】:

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


    【解决方案1】:

    问题 1

    要允许在放置的元素后输入文本,请更改此行:

    return words.join("&nbsp;");
    

    到:

    return words.join("&nbsp;") + "&nbsp;";
    

    您甚至可以添加多个空格,例如+ "&amp;nbsp;&amp;nbsp;&amp;nbsp;",这样可以更轻松地找到可以放置插入符号的位置。

    问题 2

    contenteditable = false 应用于页面加载时文本中已经存在的“按钮”,添加您在加载脚本中已经使用的行,例如在此行之后:

    $("p.given").html(chunkWords($("p.given").text()));
    

    ...所以它变成:

    $("p.given").html(chunkWords($("p.given").text()));
    $('span.b').attr('contentEditable', false);
    

    补充建议

    当鼠标悬停在可编辑段落上时,我发现光标是一个指针,这让我感到困惑。我建议从 p.given 的 CSS 规范中删除这一行:

    cursor: pointer !important;
    

    我会添加这个 CSS 定义,所以当您将鼠标悬停在“按钮”上时会有一个光标差异:

    p.given span.b {
      cursor: default;
    }
    

    片段

    $(function() {
    
      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");
      });
    
      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;") + "&nbsp;"; // add the spaces here
      }
    
    
      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);
        $('span.b').attr('contentEditable', false);
      }
    
      function makeTextBox(txt) {
        var sp = $("<span>", {
          class: "w b"
        }).html(txt);
        $('.b').attr('contentEditable', false);
        makeBtn(sp);
        return sp;
      }
    
      function makeDropText(obj) {
        return obj.droppable({
          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");
          },
          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.b').attr('contentEditable', false);
    
      $("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"));
        $('.b').attr('contentEditable', false);
      });
    
    
      $("span.given").draggable({
        helper: "clone",
        revert: "invalid"
      });
    
      makeDropText($("p.given span.w"));
    });
    p.given {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      flex-wrap: wrap;
    }
    
    p.given span.w span.ui-icon {
      cursor: pointer;
    }
    
    p.given span.b {
      cursor: default;
      # add this
    }
    
    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;
    }
    
    .w ui-droppable {
      cursor: pointer !important;
    }
    
    .w.b.ui-droppable {
      background: #FF8;
      color: #000;
    }
    
    .given.btn-flat {
      display: inline-block;
      padding: 0.25em 0.5em;
      border-radius: 1em;
      background: #A72020;
      color: #FFF;
      cursor: pointer;
    }
    
    .ui-draggable-dragging {
      background: #FFD700 !important;
    }
    <div class="row">
      <p id="doc_navc" 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 id="walkinDiv" 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">FirstName</span>
                <span class="given btn-flat white-text red lighten-1" rel="4">LastName</span>
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
    
    <input name="Go" id="btnPass" class="tstHeck" type="button" value="Go" onclick="" />
    <input name="Go" id="btnTxt" class="tstHeck" type="button" value="Go" onclick="" />
    
    <link rel="stylesheet" href="http://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>

    【讨论】:

    • 在您的建议之后仍然出现第二个问题先生,我想我需要添加 contentEditable = false 属性同时添加添加 b class。我把它放在p.given blur 事件中,它工作正常。问题是页面加载时
    • 我添加了这个var newSpan = $("&lt;span contentEditable = 'false'&gt;").addClass('w b').text(txt);,它只适用于删除新组件时。但需要为初始加载做同样的事情(已经 droppe 组件)
    • 我通过将点击事件添加为` $("p.given").click(function() { $('span.b').attr('contentEditable', false); }); ` 这是好事吗:)
    • 我在写之前测试了我的答案。它有效:那些特殊的“按钮”得到contentEditable: false。我在答案中添加了一个 sn-p 并检查加载的元素,它有它。我不明白你为什么说“第二个问题仍在发生”。请检查我添加的 sn-p,并验证 span "Ipsum" 的 contentEditable 属性设置为 false。我也不明白你说你是如何通过添加点击事件来解决它的,因为这与页面加载无关。
    • 是的,先生,我检查过了,但是您的帮助对我来说非常重要。感谢您为我所做的一切
    猜你喜欢
    • 1970-01-01
    • 2014-01-28
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多