实现textarea拖放

时间:2017-07-20 12:42:26

标签: javascript jquery knockout.js



<div class="wrapper">
  <div class="container">
    <div class="content">
      Some text
    </div>
  </div>
</div>
&#13;
(function() {
  'use strict';

  var data = JSON.stringify({
    "tags": [{
      "id": 1,
      "name": "HELPDESKPHONE",
      "value": "{{helpdeskphone}}",
      "description": null
    }, {
      "id": 3,
      "name": "HELPDESKEMAIL",
      "value": "{{helpdeskemail}}",
      "description": null
    }, {
      "id": 4,
      "name": "CODE",
      "value": "{{code}}",
      "description": null
    }, {
      "id": 7,
      "name": "CALLBACKURL",
      "value": "{{callbackurl}}",
      "description": null
    }],
    "templates": [{
      "id": 1,
      "key": "securitycode",
      "description": null,
      "content": "<p>Your credentials have been identified in the system and a request to authenticate your account by email has been made.</p><p>To continue the  2-Factor Authentication process, enter this single-use code on the verification page.</p>{{code}}<p>PLEASE NOTE THAT THIS CODE EXPIRES WITHIN 1 HOUR OF SENDING THIS EMAIL.</p><p>If you did not initiate this request, please contact the Helpdesk via email at {{helpdeskemail}} or by calling (toll-free) {{helpdeskphone}}</p>",
      "subject": "Security Code"
    }, {
      "id": 3,
      "key": "resetpassword",
      "description": null,
      "content": "<p>A request to change your password has been made. To continue the password change process, click on the link below.</p><a href=\"{{callbackurl}}\">Click here to reset your password.</a></p>\n<p>PLEASE NOTE THAT THIS LINK EXPIRES WITHIN 1 HOUR OF SENDING THIS EMAIL.</p><p>If you did not initiate this request, please contact the Helpdesk via email at {{helpdeskemail}}; or by calling (toll-free) {{helpdeskphone}}</p> ",
      "subject": "FWIMS Password Change Request"
    }]
  });

  var Tag = function(id, name, value, description) {
    var self = this;
    self.id = ko.observable(id);
    self.name = ko.observable(name);
    self.value = ko.observable(value);
    self.description = ko.observable(description);
  };

  var Template = function(id, key, description, content, subject, tags) {
    var self = this;
    self.id = ko.observable(id);
    self.key = ko.observable(key);
    self.description = ko.observable(description);
    self.content = ko.observable(content);
    self.subject = ko.observable(subject);
  };

  var ViewModel = function(data) {
    var self = this;

    self.templates = ko.observableArray(data.templates.map(function(item) {
      return new Template(
        item.id,
        item.key,
        item.description,
        item.content,
        item.subject
      );
    }));

    self.tags = ko.observableArray(data.tags.map(function(item) {
      return new Tag(
        item.id,
        item.name,
        item.value,
        item.description
      );
    }));

    self.makeDraggable = function() {
      $("li").draggable({
        helper: 'clone'
      });
    };

    self.makeDroppable = function(elements) {
      $(".txtDropTarget").droppable({
        accept: "li",
        drop: function(ev, ui) {
          $(this).insertAtCaret(ui.draggable.text());
        }
      });
    };


    $.fn.insertAtCaret = function(myValue) {
      return this.each(function() {
        //IE support
        if (document.selection) {
          this.focus();
          sel = document.selection.createRange();
          sel.text = myValue;
          this.focus();
        }
        //MOZILLA / NETSCAPE support
        else if (this.selectionStart || this.selectionStart == '0') {
          var startPos = this.selectionStart;
          var endPos = this.selectionEnd;
          var scrollTop = this.scrollTop;
          this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
          this.focus();
          this.selectionStart = startPos + myValue.length;
          this.selectionEnd = startPos + myValue.length;
          this.scrollTop = scrollTop;
        } else {
          this.value += myValue;
          this.focus();
        }
      });
    };
  };

  var viewModel = new ViewModel(ko.utils.parseJson(data) || []);
  ko.applyBindings(viewModel);
}());
&#13;
.move-pointer {
  cursor: move;
}
&#13;
&#13;
&#13;

我正在设计用于使用淘汰赛编辑和创建电子邮件模板内容的UI。

我实现了这个:

我有一个textarea和一个预览div。当文本添加到文本区域时,它会显示在预览区域中。在textarea下是可接受的标签,哪些行为有占位符。此占位符将在运行时替换为实际值。

我现在遇到的问题是,如果将标记拖入textarea,<div data-bind="foreach: {data: templates, afterRender: makeDroppable } "> <div class="card"> <div class="d-flex justify-content-between align-content-center"> <textarea rows="10" style="height: auto" aria-label="Content" class="txtDropTarget form-control m-3" aria-describedby="Template Content" data-bind="textInput: content"></textarea> <div data-bind="html: content" class="m-3"></div> </div> <div class="d-flex justify-content-between align-content-center"> <ul class="dragList nav" data-bind="foreach: { data: $parent.tags, afterRender: $root.makeDraggable }"> <li data-bind="text: value" class="nav-item m-3 h5 move-pointer"></li> </ul> </div> </div> </div> observable不会立即更新,我必须输入文本区域以触发可观察的更新。

content

我已经尝试了<textarea rows="10" style="height: auto" aria-label="Content" class="txtDropTarget form-control m-3" aria-describedby="Template Content" data-bind="textInput: content"></textarea> 绑定和textInput事件,但这些都没有效果

1 个答案:

答案 0 :(得分:3)

这样做

$(this).insertAtCaret(ui.draggable.text()).change();
拖动后

我编辑了您的示例 - https://jsfiddle.net/qskxzh0e/3/

 self.makeDroppable = function(elements) {
      $(".txtDropTarget").droppable({
        accept: "li",
        drop: function(ev, ui) {
          $(this).insertAtCaret(ui.draggable.text()).change();
        }
      });
    };