How can I type text after dropped content

◇◆丶佛笑我妖孽 提交于 2020-01-05 06:32:30

问题


I'm using jQuery UI draggable component to add to content editable

.This code works to find and I have little issues. The problem is when I dropped the draggable component as the last word of the paragraph. I cannot type text after that dropped component.

and the second issue is, I need to disable contentEditable option from words (span with removable option), to achieve that I add this code ($('.b').attr('contentEditable', false);) inside $("p.given").blur event. It works fine. I need to do the same thing when the page load. how can I do it? can I add contentEditable = false attribute to which only have removeble option.

Note: the current functionalities cannot be a break.

My code as follows:

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

回答1:


Issue 1

To allow typing text after the dropped element, change this line:

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

to:

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

You may even add multiple spaces, like + "&nbsp;&nbsp;&nbsp;" which would make it even easier to find the spot where the caret can be put.

Issue 2

The apply contenteditable = false to the "buttons" already present in the text when the page loads, add the line you already use in the load script, for instance after this line:

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

...so it becomes:

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

Additional suggestion

I find it confusing that the cursor is a pointer when hovering over the editable paragraph. I would suggest removing this line from the CSS specs for p.given:

cursor: pointer !important;

And I would add this CSS definition, so there is a cursor difference when you hover over a "button":

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

Snippet

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


来源:https://stackoverflow.com/questions/58939505/how-can-i-type-text-after-dropped-content

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!