javascript - 从 contenteditable 填充并保存文本

标签 javascript jquery iframe designmode

我正要开始编写自己的富文本编辑器,但需要知道是否可以填充文本区域以及如何保存/使用其中的数据。

我目前正在使用 CKEditor,但它对于我想要的东西来说太笨重和太大。
我将使用它作为基础:http://jsfiddle.net/Kxmaf/6/
我还需要对数据进行某些检查以检查其长度。

如果需要代码:

// Stack Code Snippets does not work with Iframe. Here's the code anyways:

$(document).ready(function() {
  document.getElementById('textEditor').contentWindow.document.designMode = "on";
  document.getElementById('textEditor').contentWindow.document.close();
  
  $("#bold").click(function() {
    if ($(this).hasClass("selected")) {
      $(this).removeClass("selected");
    } else {
      $(this).addClass("selected");
    }
    boldIt();
  });
  $("#italic").click(function() {
    if ($(this).hasClass("selected")) {
      $(this).removeClass("selected");
    } else {
      $(this).addClass("selected");
    }
    ItalicIt();
  });
  $("#fonts").change(function() {
    changeFont($("#fonts").val());
  });
});

function boldIt() {
  var edit = document.getElementById("textEditor").contentWindow;
  edit.focus();
  edit.document.execCommand("bold", false, "");
  edit.focus();
}

function ItalicIt() {
  var edit = document.getElementById("textEditor").contentWindow;
  edit.focus();
  edit.document.execCommand("italic", false, "");
  edit.focus();
}

function changeFont(font) {
  var edit = document.getElementById("textEditor").contentWindow;
  edit.focus();
  edit.document.execCommand("FontName", false, font);
  edit.focus();
}
<a id="bold" class="font-bold">B</a>
<a id="italic" class="italic">I</a>
<select id="fonts">
  <option value="Arial">Arial</option>
  <option value="Comic Sans MS">Comic Sans MS</option>
  <option value="Courier New">Courier New</option>
  <option value="Monotype Corsiva">Monotype</option>
  <option value="Tahoma">Tahoma</option>
  <option value="Times">Times</option>
</select>
<br/>
<iframe id="textEditor" style="width:500px; height:170px;"></iframe>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

谢谢。

最佳答案

要创建右侧文本编辑器,您可以使用 contenteditable <div> 上的属性元素或通过 JS designMode 。您不需要<iframe> .

注意: while execCommand 适用于所有主要浏览器,但有其怪癖和差异 - 现在已弃用(但没有任何合理的解决方法,只能创建您自己的内联内容编辑软件或使用 Input-Events ),因此请谨慎使用。

让你从某个地方开始,

$(function() {

  var $editor = $('#textEditor');
  var $btn = $('span[data-cmd]');
  
  // EXECUTE COMMAND
  function execCmd(cmd, arg) {
    document.execCommand(cmd, false, arg);
  }

  $btn.mousedown(function(e) {
    e.preventDefault();
    $(this).toggleClass("selected");
    execCmd(this.dataset.cmd);
  });

  $("#fonts").change(function() {
    execCmd("FontName", this.value);
  });

});
* {margin: 0; padding: 0;}

#textEditorTab span {
  cursor: pointer;
  display: inline-block;
  padding: 0px 10px 0px 10px;
}

#textEditorTab span:hover {
  background: #eee;
}

#textEditorTab span.selected {
  background-color: orange;
}

#textEditor {
  width: 300px;
  height: 120px;
  border: 1px solid #ddd;
  padding: 5px;
}
<div id="textEditorTab">
  <span data-cmd="bold"><b>B</b></span>
  <span data-cmd="italic"><i>I</i></span>

  <select id="fonts">
    <option value="Arial">Arial</option>
    <option value="Comic Sans MS">Comic Sans MS</option>
    <option value="Courier New">Courier New</option>
    <option value="Monotype Corsiva">Monotype</option>
    <option value="Tahoma">Tahoma</option>
    <option value="Times">Times</option>
  </select>
</div>

<div id="textEditor" contenteditable>Lorem ipsum dolor sit amet</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

现在,我发现您希望在单击按钮时使其状态为“ACTIVE”, 但如果你三思而后行,你会得到的结果却是一团糟,原因如下:

用户输入文本 -> 选择一部分并单击粗体,现在它会随着光标跳到没有粗体文​​本的行首...但是等等,您的按钮仍然处于事件状态状态...

为了防止此类用户体验,您需要跟踪用户选择的子元素,并相应地打开选项选项卡中与所选 tag 匹配的所有按钮。标准。

为了不让您失望 - 这是一个示例:

$(function() {

  var $editor = $('#textEditor').prop('contenteditable', true);
  var $btn = $('span[data-cmd]');
  var tag2cmd = {
    "B": 'bold',
    "I": 'italic'
  };

  // HIGHLIGHT BUTTONS on content selection
  function findParentNode(el) {

    $btn.removeClass('selected');

    var tagsArr = [];
    var testObj = el.parentNode || '';
    if (!testObj) {
      return;
    }

    var c = 1;
    tagsArr.push(el.nodeName);
    if (el.tagName != 'DIV') {
      while (testObj.tagName != 'DIV') {
        c++;
        tagsArr.push(testObj.nodeName);
        testObj = testObj.parentNode;
      }
      for (i = 0; i < c; i++) {
        $('[data-cmd="' + tag2cmd[tagsArr[i]] + '"]').addClass('selected');
      }
      console.log(tagsArr);
    }

  }
  // EXECUTE COMMAND
  function execCmd(cmd, arg) {
    document.execCommand(cmd, false, arg);
  }

  $btn.mousedown(function(e) {
    e.preventDefault();
    $(this).toggleClass("selected");
    execCmd(this.dataset.cmd);
  });

  $("#fonts").change(function() {
    execCmd("FontName", this.value);
  });


  // Having a button click toggleClass is not enough cause you'd also want 
  // to change button state when the user tlicks on different
  // elements tag inside the editor.

  var $lastSelected;
  $editor.on('mouseup', function(e) {
    e.stopPropagation();
    $lastSelected = e.target;
    findParentNode($lastSelected); // auto highlight select buttons
  });

});
* {margin: 0; padding: 0;}

#textEditorTab span {
  cursor: pointer;
  display: inline-block;
  padding: 0px 10px 0px 10px;
}

#textEditorTab span:hover {
  background: #eee;
}

#textEditorTab span.selected {
  background-color: orange;
}

#textEditor {
  width: 300px;
  height: 120px;
  border: 1px solid #ddd;
  padding: 5px;
}
<div id="textEditorTab">
  <span data-cmd="bold"><b>B</b></span>
  <span data-cmd="italic"><i>I</i></span>

  <select id="fonts">
    <option value="Arial">Arial</option>
    <option value="Comic Sans MS">Comic Sans MS</option>
    <option value="Courier New">Courier New</option>
    <option value="Monotype Corsiva">Monotype</option>
    <option value="Tahoma">Tahoma</option>
    <option value="Times">Times</option>
  </select>
</div>

<div id="textEditor">Lorem ipsum dolor sit amet</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

所以你看,只有一个“想法”,代码就会立即变得庞大,所以如果你真的想保持简单,请避免这样的东西并享受乐趣!

关于javascript - 从 contenteditable 填充并保存文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23120809/

相关文章:

javascript - 使用 JavaScript 和 HTML 将多个文件下载为文件夹?

Javascript 对象构造函数未注册参数

javascript - Vue js 在 Action 中调用 Action

javascript - 更改选择列表的选定值

javascript - 将鼠标悬停在 li 上时更改 div 的颜色

wordpress - 您可以使iFrame响应式吗?

facebook - 如何使用 Google Analytics 跟踪我网站上的 Facebook iframe 视频?

javascript - 检测变量是否为全局变量

javascript - 打印时扩展div的高度

javascript - 将 URL 信息从父 iframe 转发到子 iframe