TinyMCE和 ASP.NET MVC高级功能

分享于 

26分钟阅读

Web开发

  繁體

介绍

ibm TinyMCE 是强大的JavaScript富文本编辑器,相对于你的应用程序,它相对容易集成,并且被许可用户 框架,这篇文章将演示 TinyMCE,它是一个完整的基于web的MVC框架,因此它对其他的web开发框架很有帮助,因此它对其他的web开发框架很简单。

然而,本文并不关注 TinyMCE插件的基础,因为它很容易在文档中找到。 这里将展示如何使用不太明确的高级功能,给读者使用这个大组件的有用帮助。 以下是本文的重点:

背景

由于以下因素,TinyMCE 实际上应该被认为是富文本编辑器的选项:

  • 它可以免费使用。
  • 它具有丰富的文本编辑器所需的大多数功能,例如: 字体更改。链接管理。文本操作。视频使用等等。
  • 用起来很简单。
  • 它有很好的文档。
  • 它有很多论坛和讨论,无疑会帮助开发者。
  • 因为它是纯JavaScript工具,所以它可以在任何一个web框架中使用。

使用代码

应用程序概述

这里将描述应用程序如何工作,以便能够更好地理解代码,并充分了解实现的功能。

首先,当应用程序启动时,显示一个显示为 below的屏幕。

你可以看到,在同一屏幕上有两个富文本区域。 要使用它们,只需使用一个希望使用的文本填充它们。 还要注意,当一个在富文本区域填充时,计数器标识使用的HTML字符数量。 屏幕 below 显示了一个示例:

然后,按"创建"按钮提交表单。 下一个显示的是与 rich escaped HTML HTML格式相同的文本,以及每个富文本区域中以前存在的数据,每个富文本区域的提交数据都是纯转义的文本,如下面的代码所示:

注意屏幕顶部显示的值。 它们包含文本以及转义的 HTML格式的字符,这些字符在到达文本区域中设置文本的格式。 这个数据是软件必须存储的,因为它是由富文本区域包含格式化文本的那个。

观察富文本区域中的文本。 如前所述,那里已经重新载入。 这是在 TinyMCE插件组件的加载事件中完成的。

最后,显示用于验证错误的消息,( 它是使用 jQuery插件实现的。):

第1 个富文本区域中验证失败,因为文本是强制性的,在第二个文本中,验证不成功,因为插入了超过2 个。

了解代码

现在是理解代码本身的时候了。 在提取项目文件的zip内容后,应该使用 Microsoft Visual Studio 2010 ( 或者上级) 或者微软 Visual Web Developer 2010 ( 或者上级) 打开项目。 我们将注意到这是一个标准的ASP.NET 3项目。 以下是有关这里项目的主要注意事项:

  • 在文件夹脚本中,有一个称为 tiny_mce。 这保存从主页下载的JavaScript代码。
  • 同样,在文件夹脚本中,有文件 JHomeINdex.js。 这个文件使用 TinyMCE命令操作 UI。
  • 在控制器文件夹中有唯一的控件- HomeControl.cs 用于这个应用程序。
  • 在模型中,只有一个模型- SampleModel用于这个小型软件。
  • 如果你的个人文件夹是这个应用程序的唯一视图,那么你将看到这个小应用程序的"母版页"( 网页)。

从模型- SampleModel开始,看看它下面的代码:

using System;using System.ComponentModel.DataAnnotations;using System.Web.Mvc;
 namespace MvcAppTnyMCE.Models
{
 publicclass SampleModel
 {
 [AllowHtml]
 [Display(Name = "Ritch Text 1")]
 publicString RichText1 {get; set;}
 [AllowHtml]
 publicString RichText1FullHtml { get; set; }
 [AllowHtml]
 [Display(Name = "Ritch Text 2")]
 publicString RichText2 {get; set;}
 [AllowHtml]
 publicString RichText2FullHtml { get; set; }
 }
} 

注意显示的四个字段与执行程序时屏幕中显示的文本区域相关。 字段 RitchText1RichText2 直接绑定到 TinyMCE 组件使用的 textarea。RichText1FullHtmlRichText2FullHtml 用于显示由按钮"创建"按钮提交的文本区域所提交的数据。 如果一个人回顾这篇文章并检查软件做了什么,那么模型中使用的元素就足够了。 此外,注意在参数中使用 AllowHtml 标记以避免设置和获取HTML内容的安全问题。 finally,请注意,HTML中每个字段的显示名称已经定义。

接下来,控制器- HomeController.cs 显示 below: 将被分析

using System.Web.Mvc;using MvcAppTnyMCE.Models;
 namespace MvcAppTnyMCE.Controllers
{
 publicclass HomeController : Controller
 {
 public ActionResult Index()
 {
 return View();
 }
 [HttpPost]
 public ActionResult Index(SampleModel model)
 {
 model.RichText1FullHtml = model.RichText1;
 model.RichText2FullHtml = model.RichText2;
 model.RichText1 = null;
 model.RichText2 = null;
 return View(model);
 }
 }
}

这个控制器很简单。 第一种方法,只是显示视图- Index.cshtml。 其次,从模型获取数据- 获取用户在富文本区域中输入的值,并将它们设置为字段以显示为HTML元素。 最后,RitchText1RichText2的值是 nulled,因此可以确保它们在 TinyMCE组件的加载事件中设置。

接下来,值得讨论的下一个代码是视图元素- Index.cshtml。 下面是它的代码:

@model MvcAppTnyMCE.Models.SampleModel
@using MvcAppTnyMCE.Models;
@{
 ViewBag.Title ="TinyMCE Sample";
}
 <h2>TinyMCE Sample</h2> 
@section JavaScriptSection {
 <scriptsrc="@Url.Content("~/Scripts/jquery.validate.min.js")"type="text/javascript"></script> 
 <scriptsrc="@Url.Content("~/Scripts/tiny_mce/tiny_mce.js")"type="text/javascript"></script> 
 <scriptsrc="@Url.Content("~/Scripts/JHomeIndex.js")"type="text/javascript"></script>}
@using (Html.BeginForm("Index","Home", FormMethod.Post, new { id ="formText" })) {
 <fieldset><legend>TinyMCE Sample</legend> 
 @{
 if (Model!= null && Model.RichText1FullHtml!= null && Model.RichText1FullHtml.Length> 0)
 {
 <p> The submitted text from"Ritch Text 1" is: 
 </p><div> @Model.RichText1FullHtml;
 </div><inputid="RichText1Value"name="RichText1Value"type="hidden"value="@Server.HtmlDecode(Model.RichText1FullHtml)"/> }
 if (Model!= null && Model.RichText2FullHtml!= null && Model.RichText2FullHtml.Length> 0)
 {
 <p> The submitted text from"Ritch Text 2" is: 
 </p><div> @Model.RichText2FullHtml;
 </div><inputid="RichText2Value"name="RichText2Value"type="hidden"value="@Server.HtmlDecode(Model.RichText2FullHtml)"/> }
 }
 <p> @Html.LabelFor(m => m.RichText1)
 <inputid="RichText1Copy"name="RichText1Copy"type="hidden"/> @Html.TextAreaFor(m => m.RichText1, new { @class ="mceEditor" })
 </p><p> @Html.LabelFor(m => m.RichText2)
 <inputid="RichText2Copy"name="RichText2Copy"type="hidden"/> @Html.TextAreaFor(m => m.RichText2, new { @class ="mceEditor" })
 </p><p><inputid="saveButton"type="submit"value="Create"/></p></fieldset>}

在这里,有一些事情做:

  • 导入必要的JavaScript脚本。 基本 脚本已经在 _Layout.cshtml 视图中导入了。
  • 表单被定义为
  • 显示由富文本区域提交的HTML的页面顶部,处于处理状态。 注意,只有在实际存在数据的情况下才显示某些内容。 同时注意这个数据保存在隐藏字段( RichText1ValueRichText2Value ) 中,因为它们稍后会被用来在 TinyMCE组件的加载事件中重新填充富文本区域。
  • 这里还有两个需要提及的东西:
  • 模型中的绑定值,用于 TinyMCE。 它们是:RitchText1RichText2.
  • 还要注意,( RichText1CopyRichText2Copy ) 创建两个隐藏字段变量。 稍后你将看到,这些变量用于使用进行验证。 这是通过实现成功验证的必要方法。

现在是代码的核心,使用JavaScript操作 UI,的JHomeIndex.js 脚本。 请查看下面的内容:

// max number of chars allwed in a tinyMice componentvar tinyMiceMaxCharLength = 5000;
 function loadTinyMiceRichTextFeature(controlName, inputCopyIdentifier) {
 var configArray = {
 // General options mode: "textareas",
 theme: "advanced",
 encoding: "xml",
 mode : "specific_textareas",
 editor_selector : "mceEditor",
 mode: "none",
 plugins: "autolink,lists,pagebreak,style,table,advhr,advlink,emotions,
 iespell,inlinepopups,insertdatetime,preview,searchreplace,print,paste,
 directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,
 template,wordcount,advlist,autosave,visualblocks",
 // Theme options theme_advanced_buttons1: "save,newdocument,|,bold,italic,underline,
 strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect",
 theme_advanced_buttons2: "fontselect,fontsizeselect,!,cut,copy,paste,
 pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent",
 theme_advanced_buttons3: "blockquote,|,undo,redo,|,link,unlink,anchor,|,
 insertdate,inserttime,preview,!,hr,removeformat,visualaid,|,
 sub,sup,|,charmap,emotions,iespell,media,advhr,|,print",
 theme_advanced_buttons4: "tablecontrols",
 theme_advanced_buttons5: "moveforward,movebackward,absolute,|,cite,abbr,
 acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak,
 restoredraft,visualblocks,|,forecolor,backcolor,fullscreen,|,ltr,rtl,|",
 theme_advanced_toolbar_location: "top",
 theme_advanced_toolbar_align: "left",
 theme_advanced_statusbar_location: "bottom",
 theme_advanced_resizing: true,
 theme_advanced_path: false,
 // Example content CSS (should be your site CSS) content_css: "../../Content/Site.css",
 // Drop lists for link/image/media/template bloglists template_external_list_url: "lists/template_list.js",
 external_link_list_url: "lists/link_list.js",
 external_image_list_url: "lists/image_list.js",
 media_external_list_url: "lists/media_list.js",
 // Style formats style_formats: [
 { title: 'Bold Text', inline: 'b' },
 { title: 'Red Text', inline: 'span', styles: { color: '#ff0000'} },
 { title: 'Red Title', block: 'h1', styles: { color: '#ff0000'} }
 ],
 charLimit: tinyMiceMaxCharLength, // this is a default value which can get modified later//set up a new editor function  setup: function (ed) {
 //peform this action every time a key is pressed ed.onKeyUp.add(function (ed, e) {
 updateTinyMiceHtmlCounter(ed, e, inputCopyIdentifier);
 });
 // event called when the content is to be loaded in the rich text editor ed.onLoadContent.add(function (ed, o) {
 if (tinyMCE.editors!= null && tinyMCE.editors.length> 0) {
 var trueValue = "#formText" + " #" + controlName + "Value";
 if ($(trueValue)!= null && $(trueValue).val()!= null) {
 // update content tinyMCE.activeEditor.setContent($(trueValue).val());
 // trigger click so validation will be performed even// if no data is modified in the editor updateTinyMiceHtmlCounter(ed, o, inputCopyIdentifier);
 }
 }
 });
 }
 };
 tinyMCE.settings = configArray;
 tinyMCE.execCommand('mceAddControl', true, controlName);
}
 // update tiny mice html counterfunction updateTinyMiceHtmlCounter(ed, e, inputCopyIdentifier) {
 //define local variablesvar tinymax, tinylen, htmlcount;
 //manually setting our max character limit tinymax = ed.settings.charLimit;
 //grabbing the length of the curent editors content tinylen = ed.getContent().length;
 //setting up the text string that will display in the path area htmlcount = "# of HTML characters:" + tinylen + "/" + tinymax;
 //if the user has exceeded the max turn the path bar red.if (tinylen> tinymax) {
 htmlcount = "<span style='font-weight:bold; color: #f00;'>" + 
 htmlcount + "</span>";
 }
 // copy content to follow up text area so it can be validated $(inputCopyIdentifier).val(ed.getContent());
 //this line writes the html count into the path row of the active editor tinymce.DOM.setHTML(tinymce.DOM.get(tinyMCE.activeEditor.id + '_path_row'), htmlcount);
}
 var inputCopyId1 = "#formText #RichText1Copy";
 var inputCopyId2 = "#formText #RichText2Copy";
$().ready(function () {
 // load rich text feature loadTinyMiceRichTextFeature("RichText1", inputCopyId1);
 loadTinyMiceRichTextFeature("RichText2", inputCopyId2);
 // allow the validation of hidden fields so the tinymce textarea// can be validated $.validator.setDefaults({ ignore: "" });
 // validate form validateForm();
});
 // validate formfunction validateForm() {
 $().ready(function () {
 $("#formText").validate({
 rules: {
 RichText1Copy: {
 required: true,
 maxlength: tinyMiceMaxCharLength
 },
 RichText2Copy: {
 maxlength: tinyMiceMaxCharLength
 }
 }
 });
 });
} 

虽然这个代码看起来很长,但是要理解它并不难。 部分内容将被详细解释,以便读者能看到它的目的。

请遵守下面的代码:

$().ready(function () {
 // load rich text feature loadTinyMiceRichTextFeature("RichText1", inputCopyId1);
 loadTinyMiceRichTextFeature("RichText2", inputCopyId2);
 // allow the validation of hidden fields so the tinymce textarea// can be validated $.validator.setDefaults({ ignore: "" });
 // validate form validateForm();
}); 

加载 Index.cshtml 时执行这里代码。 看看这里会发生什么:

  • TinyMCE 组件通过方法附加到字段 RichText1RichText2loadTinyMiceRichTextFeature(controlName, inputCopyIdentifier) 注意 RichText1RichText2 是文本标记的id,它将使用 TinyMCE 组件保存富文本区域。 还要注意,方法 loadTinyMiceRichTextFeature(...) 使用第二个参数,它是与每个富文本区域( RichText1ValueRichText2Value ) 关联的隐藏字段的jQuery 标识符。
  • 使用 jQuery插件的验证也是在这里设置的,方法是通过方法。

现在,观察下面显示的方法 loadTinyMiceRichTextFeature(...):

// max number of chars allwed in a tinyMice componentvar tinyMiceMaxCharLength = 5000;
 function loadTinyMiceRichTextFeature(controlName, inputCopyIdentifier) {
 var configArray = {
 // General options mode: "textareas",
 theme: "advanced",
 encoding: "xml",
 mode : "specific_textareas",
 editor_selector : "mceEditor",
 mode: "none",
 plugins: "autolink,lists,pagebreak,style,table,advhr,advlink,emotions,iespell,
 inlinepopups,insertdatetime,preview,searchreplace,print,paste,directionality,
 fullscreen,noneditable,visualchars,nonbreaking,
 xhtmlxtras,template,wordcount,advlist,autosave,visualblocks",
 // Theme options theme_advanced_buttons1: "save,newdocument,|,bold,italic,underline,strikethrough,|,
 justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect",
 theme_advanced_buttons2: "fontselect,fontsizeselect,!,cut,copy,paste,
 pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent",
 theme_advanced_buttons3: "blockquote,|,undo,redo,|,link,unlink,anchor,|,insertdate,
 inserttime,preview,!,hr,removeformat,visualaid,|,sub,sup,|,
 charmap,emotions,iespell,media,advhr,|,print",
 theme_advanced_buttons4: "tablecontrols",
 theme_advanced_buttons5: "moveforward,movebackward,absolute,|,cite,abbr,acronym,del,
 ins,attribs,|,visualchars,nonbreaking,template,pagebreak,restoredraft,
 visualblocks,|,forecolor,backcolor,fullscreen,|,ltr,rtl,|",
 theme_advanced_toolbar_location: "top",
 theme_advanced_toolbar_align: "left",
 theme_advanced_statusbar_location: "bottom",
 theme_advanced_resizing: true,
 theme_advanced_path: false,
 // Example content CSS (should be your site CSS) content_css: "../../Content/Site.css",
 // Drop lists for link/image/media/template bloglists template_external_list_url: "lists/template_list.js",
 external_link_list_url: "lists/link_list.js",
 external_image_list_url: "lists/image_list.js",
 media_external_list_url: "lists/media_list.js",
 // Style formats style_formats: [
 { title: 'Bold Text', inline: 'b' },
 { title: 'Red Text', inline: 'span', styles: { color: '#ff0000'} },
 { title: 'Red Title', block: 'h1', styles: { color: '#ff0000'} }
 ],
 charLimit: tinyMiceMaxCharLength, // this is a default value which can get modified later//set up a new editor function  setup: function (ed) {
 //peform this action every time a key is pressed ed.onKeyUp.add(function (ed, e) {
 updateTinyMiceHtmlCounter(ed, e, inputCopyIdentifier);
 });
 // event called when the content is to be loaded in the rich text editor ed.onLoadContent.add(function (ed, o) {
 if (tinyMCE.editors!= null && tinyMCE.editors.length> 0) {
 var trueValue = "#formText" + " #" + controlName + "Value";
 if ($(trueValue)!= null && $(trueValue).val()!= null) {
 // update content tinyMCE.activeEditor.setContent($(trueValue).val());
 // trigger click so validation will be performed even// if no data is modified in the editor updateTinyMiceHtmlCounter(ed, o, inputCopyIdentifier);
 }
 }
 });
 }
 };
 tinyMCE.settings = configArray;
 tinyMCE.execCommand('mceAddControl', true, controlName);
} 

它做了很多事情,它们是:

  • 设置 TinyMCE 作为第一个方法参数输入的文本区域。 这里参数必须是 textarea ( RichText1RichText2 )的id。 第二个参数用于标识隐藏字段( RichText1ValueRichText2Value ),它将在富文本区域中保存输入文本的副本。 它们用于验证,稍后会解释。
  • 现在有了不同的方面,这些事件。
  • 下面的方法 updateTinyMiceHtmlCounter(...) 中的事件 onkeyUp: 对于每个文本区域中添加或者删除的字符,它计算已经键入的HTML字符数。 而且,每次调用这里事件时,都将整个内容复制到由方法 updateTinyMiceHtmlCounter(...)的参数 inputCopyIdentifier 标识的隐藏字段中。 复制到隐藏字段对于验证目的非常重要。 无法在由 TinyMCE 定义的富文本区域中进行验证,因为它改变了开发人员无法控制的manners。 因此,验证最安全的方法是将它的内容复制到隐藏字段中,使用它进行验证。
  • event onLoadContent(...) 是在将 TinyMCE加载项加载到页面时负责加载数据的。 因这里,每次调用这里事件时,都需要验证是否需要在富文本区域中加载数据。 注意,这里方法从窗体顶部的隐藏字段( RichText1ValueRichText2Value ) 获取值,它的中显示了HTML内容。 如果这些值确实存在,则将它们放入 TinyMCE插件组件中。 人们可能认为,简单的解决方案是通过在 Index.cshtml 中通过绑定直接设置值。 然而,当这样做时,html不会相应地解释 TinyMCE 这个解决方案不合适。

最后要讨论的是验证,它由下面的方法 validateForm() 完成:

// validate formfunction validateForm() {
 $().ready(function () {
 $("#formText").validate({
 rules: {
 RichText1Copy: {
 required: true,
 maxlength: tinyMiceMaxCharLength
 },
 RichText2Copy: {
 maxlength: tinyMiceMaxCharLength
 }
 }
 });
 });
} 

我们可以看到,这是一个简单的 jQuery插件。 但是,在这里,验证字段是接收来自富文本区域的值的隐藏字段,每次更改字符 updateTinyMiceHtmlCounter(...)。 ,,因为 one textareas TinyMCE 验证使用which验证不能工作,因为 TinyMCE无法unpredictably修改这些字段,。 注意这里验证了字段是必需的还是允许的最大HTML字符数。

然而,这个代码看起来很复杂,但是需要一点时间来理解它。

根据HTML字符数而不是键入字符限制

可能出现的一个讨论是限制HTML字符数量的原因,而不是键入字符的数量。 有以下几个原因:

  • 在JavaScript中计算输入字符的数量并不容易,可能会导致性能问题。
  • 字符的真正限制是 HTML,而不是键入的字符。 因这里,由于HTML字符数总是高于类型的数量,因这里可以使用不足的空间来限制。
  • TinyMCE 没有提供任何简单的解决方案,因此一切都必须手工完成。

结语

设置的基础是简单的,它的文档足以做到这一点。 然而,其他更复杂的任务,例如使用多个组件,使用事件验证和加载数据并不那么简单。 然而,各种论坛和调查允许本文的作者解决所有问题,以便参与各种软件需求。 这是 TinyMCE的一个关键力量。 有许多论坛和讨论可以帮助开发人员克服困难。

另一个重要特性是,因为这是纯Javascript组件,它可以与各种web开发技术一起。 这里已经说明了这一点,但是强调这个伟大的方面是很重要的。

TinyMCE 有两种风格: Javascript和 jQuery插件。 奇怪的是,本文是使用JavaScript版本编写的,原因很简单: 它的文档更丰富。

使用这个小的应用程序示例可以能有大部分需要解决的问题,使得这个组件更容易使用。


相关文章