【问题标题】:Populate and save text from contenteditable从 contenteditable 填充和保存文本
【发布时间】:2014-05-31 23:55:34
【问题描述】:

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

我目前正在使用 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>

谢谢。

【问题讨论】:

  • 出于好奇...你为什么要使用 iframe ??
  • 我在寻找如何制作富文本编辑器时遇到了这个问题。是否可以在普通文本区域使用 execCommand 等?
  • 文本区域?你可以在 DIV 上做到这一点!
  • 我明白了!我要有戏。谢谢!
  • 我已经添加了一个演示,其中包含您所需要的只是......更简单。我仍然不明白的是在哪里以及为什么要保存编辑器数据。

标签: javascript jquery iframe designmode


【解决方案1】:

要创建您的右文本编辑器,您可以在 &lt;div&gt; 元素上使用 contenteditable 属性或通过 JS designMode。你不需要&lt;iframe&gt;

注意:虽然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, 但如果你三思而后行,你会得到一团糟,原因有一个:

用户输入文本 -> 选择一个部分并点击 BOLD,现在它会随着光标跳转到没有 BOLD 文本的行首...但是等等,您的按钮仍然处于活动状态状态...

为防止此类用户体验,您需要跟踪用户选择的子元素,并相应地打开选项选项卡中与所选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>

所以你看,只有一个“想法”,代码会立即变得庞大,所以如果你真的想保持简单,请避免这些东西并玩得开心!

【讨论】:

  • 惊人的答案!谢谢!我正在制作一个基本的博客系统,因此使用具有基本功能的 tex 编辑器来编辑帖子。可以用ckEditor之类的,但我什么都学不到!
  • @user2921557 但实际上,尽量保持简单。在 (3) 最流行的文本编辑器上工作的人实际上是在社区中,因为由于浏览器之间的所有差异以及他们对可编辑元素的理解,在正确的方式中涉及太多的技巧来使 contenteditable 工作跨浏览器,所以他们不断尝试跟上所有这些混乱。所以如果你不想打开那个盒子(不要)真的坚持颜色,粗体,斜体,字体大小,就是这样。例如,为了以正确的方式处理table,您只需要额外的 1000 行 :)
  • @user2921557 对于我的一个项目,我正在构建自己的项目,在采取一些小步骤之前,我已经两次到达 regret 点。我只是决定保持简单,这是最好的主意。
猜你喜欢
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2012-11-01
  • 2016-06-10
相关资源
最近更新 更多