چندی قبل، معرفی ادیتور سبک وزن و مناسبی را تحت عنوان
RedActor، در این سایت ملاحظه کردید. زمانیکه اینکار انجام شد، این ادیتور هم رایگان بود و هم سورس آخرین نگارش آن به سادگی در دسترس. بعد از مدتی، هر دو ویژگی یاد شدهی RedActor حذف شدند. پس از آن ادیتور مدرن و بسیار مناسب دیگری به نام
Froala منتشر شد که هرچند نگارشهای تجاری هم دارد، اما سورس آخرین نگارش آن برای عموم قابل دریافت است. در ادامه مروری خواهیم داشت بر نحوهی یکپارچه سازی آن با ASP.NET MVC و همچنین ASP.NET Web forms.
دریافت آخرین نگارش Froala WYSIWYG Editor
برای دریافت فایلهای آخرین نگارش این ادیتور وب میتوانید به سایت آن، قسمت دریافت فایلها مراجعه نمائید.
http://editor.froala.com/download
و یا به این آدرس مراجعه کنید:
https://github.com/froala/wysiwyg-editor/releases
ساختار پروژه و نحوهی کپی فایلهای آن
در هر دو مثالی که فایلهای آنرا از انتهای بحث میتوانید دریافت کنید، این ساختار رعایت شده است:
فایلهای CSS و فونتهای آن، در پوشهی Content قرار گرفتهاند.
فایلهای اسکریپت و زبان آن (که دارای زبان فارسی هم هست) در پوشهی Scripts کپی شدهاند.
یک نکته
فایل font-awesome.css را نیاز است کمی اصلاح کنید. مسیر پوشهی فونتهای آن اکنون با fonts شروع میشود.
تنظیمات اولیه
تفاوتی نمیکند که از وب فرمها استفاده میکنید یا MVC، نحوهی تعریف و افزودن پیش نیازهای این ادیتور به نحو ذیل است:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="Content/font-awesome.css" rel="stylesheet" />
<link href="Content/froala_editor.css" rel="stylesheet" />
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script src="Scripts/froala_editor.min.js"></script>
<script src="Scripts/langs/fa.js"></script>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
دو فایل CSS دارد (آیکنهای آن و همچنین شیوه نامهی اصلی ادیتور) به همراه سه فایل JS (جیکوئری، ادیتور و فایل زبان فارسی آن) که باید در فایل master یا layout سایت اضافه شوند.
استفاده از Froala WYSIWYG Editor در ASP.NET MVC
در ادامه نحوهی فعال سازی ادیتور وب Froala را در یک View برنامههای ASP.NET MVC ملاحظه میکنید:
@{
ViewBag.Title = "Index";
}
<style type="text/css">
/*تنظیم فونت پیش فرض ادیتور*/
.froala-element {
}
</style>
@using (Html.BeginForm(actionName: "Index", controllerName: "Home"))
{
@Html.TextArea(name: "Editor1")
<input type="submit" value="ارسال" />
}
@section Scripts
{
<script type="text/javascript">
$(function () {
$('#Editor1').editable({
buttons: ["bold", "italic", "underline", "strikeThrough", "fontFamily",
"fontSize", "color", "formatBlock", "align", "insertOrderedList",
"insertUnorderedList", "outdent", "indent", "selectAll", "createLink",
"insertImage", "insertVideo", "undo", "redo", "html", "save", "inserthorizontalrule"],
inlineMode: false,
inverseSkin: true,
preloaderSrc: '@Url.Content("~/Content/img/preloader.gif")',
allowedImageTypes: ["jpeg", "jpg", "png"],
height: 300,
language: "fa",
direction: "rtl",
fontList: ["Tahoma, Geneva", "Arial, Helvetica", "Impact, Charcoal"],
autosave: true,
autosaveInterval: 2500,
saveURL: '@Url.Action("FroalaAutoSave", "Home")',
saveParams: { postId: "123" },
spellcheck: true,
plainPaste: true,
imageButtons: ["removeImage", "replaceImage", "linkImage"],
borderColor: '#00008b',
imageUploadURL: '@Url.Action("FroalaUploadImage", "Home")',
imageParams: { postId: "123" },
enableScript: false
});
});
</script>
}
اگر میخواهید فونت پیش فرض آن را تنظیم کنید، باید مطابق کدهای ابتدای فایل، ویژگیهای froala-element را تغییر دهید.
سپس این ادیتور را بر روی المان TextArea قرار گرفته در صفحه، فعال میکنیم.
در قسمت مقادیر buttons، تمام حالات ممکن پیش بینی شدهاند. هر کدام را که نیاز ندارید، حذف کنید.
نحوهی تعریف زبان و راست به چپ بودن این ادیتور را با مقدار دهی پارامترهای language و direction ملاحظه میکنید.
پارامترهای autosave، saveURL و saveParams کار تنظیم ارسال خودکار محتوای ادیتور را جهت ذخیرهی آن در سرور به عهده دارند. بر اساس مقدار autosaveInterval میتوان مشخص کرد که هر چند میلی ثانیه یکبار اینکار باید انجام شود.
/// <summary>
/// ذخیره سازی خودکار
/// </summary>
[HttpPost]
[ValidateInput(false)]
public ActionResult FroalaAutoSave(string body, int? postId) // نام پارامتر بادی را تغییر ندهید
{
//todo: save body ...
return new EmptyResult();
}
در قسمت سمت سرور هم میتوان این مقادیر ارسالی را در اکشن متدی که ملاحظه میکنید، دریافت کرد.
چون قرار است تگهای HTML به سرور ارسال شوند، ویژگی ValidateInput به false تنظیم شدهاست.
saveParams آن، برای مقدار دهی پارامترهای اضافی است که نیاز میباشند تا به سرور ارسال شوند. مثلا شماره مطلب جاری نیز به سرور ارسال گردد.
در اینجا نام پارامتری که ارسال میگردد، دقیقا مساوی body است. بنابراین آنرا تغییر ندهید.
پارامترهای imageUploadURL و imageParams برای فعال سازی ذخیره تصاویر آن در سرور کاربرد دارند.
اکشن متد مدیریت کنندهی آن به نحو ذیل میتواند تعریف شود:
// todo: مسایل امنیتی آپلود را فراموش نکنید
/// <summary>
/// ذخیره سازی تصاویر ارسالی
/// </summary>
[HttpPost]
public ActionResult FroalaUploadImage(HttpPostedFileBase file, int? postId) // نام پارامتر فایل را تغییر ندهید
{
var fileName = Path.GetFileName(file.FileName);
var rootPath = Server.MapPath("~/images/");
file.SaveAs(Path.Combine(rootPath, fileName));
return Json(new { link = "images/" + fileName }, JsonRequestBehavior.AllowGet);
}
در اینجا نام پارامتری که به سرور ارسال میگردد، دقیقا معادل file است. بنابراین آنرا تغییر ندهید.
خروجی آن برای مشخص سازی محل ذخیره سازی تصویر در سرور باید یک خروجی JSON دارای خاصیت و پارامتر link به نحو فوق باشد (این مسیر، یک مسیر نسبی است؛ نسبت به ریشه سایت).
imageParams آن برای مقدار دهی پارامترهای اضافی است که نیاز میباشند تا به سرور ارسال شوند. مثلا شماره مطلب جاری نیز به سرور ارسال گردد.
استفاده از Froala WYSIWYG Editor در ASP.NET Web forms
تمام نکاتی که در قسمت تنظیمات ASP.NET MVC در مورد ویژگیهای سمت کلاینت این ادیتور ذکر شد، در مورد وب فرمها نیز صادق است. فقط قسمت مدیریت سمت سرور آن اندکی تفاوت دارد.
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master"
ValidateRequest="false"
EnableEventValidation="false"
AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FroalaWebFormsTest.Default" %>
<%--اعتبارسنجی ورودی غیرفعال شده چون باید تگ ارسال شود--%>
<%--همچنین در وب کانفیگ هم تنظیم دیگری نیاز دارد--%>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<%--حالت کلاینت آی دی بهتر است تنظیم شود در اینجا--%>
<asp:TextBox ID="txtEditor" ClientIDMode="Static"
runat="server" Height="199px" TextMode="MultiLine" Width="447px"></asp:TextBox>
<br />
<asp:Button ID="btnSave" runat="server" OnClick="btnSave_Click" Text="ارسال" />
<style type="text/css">
/*تنظیم فونت پیش فرض ادیتور*/
.froala-element {
}
</style>
<script type="text/javascript">
$(function () {
$('#txtEditor').editable({
buttons: ["bold", "italic", "underline", "strikeThrough", "fontFamily",
"fontSize", "color", "formatBlock", "align", "insertOrderedList",
"insertUnorderedList", "outdent", "indent", "selectAll", "createLink",
"insertImage", "insertVideo", "undo", "redo", "html", "save", "inserthorizontalrule"],
inlineMode: false,
inverseSkin: true,
preloaderSrc: 'Content/img/preloader.gif',
allowedImageTypes: ["jpeg", "jpg", "png"],
height: 300,
language: "fa",
direction: "rtl",
fontList: ["Tahoma, Geneva", "Arial, Helvetica", "Impact, Charcoal"],
autosave: true,
autosaveInterval: 2500,
saveURL: 'FroalaHandler.ashx',
saveParams: { postId: "123" },
spellcheck: true,
plainPaste: true,
imageButtons: ["removeImage", "replaceImage", "linkImage"],
borderColor: '#00008b',
imageUploadURL: 'FroalaHandler.ashx',
imageParams: { postId: "123" },
enableScript: false
});
});
</script>
</asp:Content>
همانطور که ملاحظه میکنید، ValidateRequest صفحه به false تنظیم شده و همچنین در وب کانفیگ httpRuntime requestValidationMode به نگارش 2 تنظیم گردیدهاست تا بتوان توسط این ادیتور تگهای ارسالی را به سرور ارسال کرد.
به علاوه ClientIDMode=Static نیز تنظیم شدهاست، تا بتوان از ID تکست باکس قرار گرفته در صفحه، به سادگی در کدهای سمت کاربر جیکوئری استفاده کرد.
اگر دقت کرده باشید، save urlها اینبار به فایل FroalaHandler.ashx اشاره میکنند. محتوای این Genric handler را ذیل مشاهده میکنید:
using System.IO;
using System.Web;
using System.Web.Script.Serialization;
namespace FroalaWebFormsTest
{
public class FroalaHandler : IHttpHandler
{
//todo: برای اینکارها بهتر است از وب ای پی آی استفاده شود
//todo: یا دو هندلر مجزا یکی برای تصاویر و دیگری برای ذخیره سازی متن
public void ProcessRequest(HttpContext context)
{
var body = context.Request.Form["body"];
var postId = context.Request.Form["postId"];
if (!string.IsNullOrWhiteSpace(body) && !string.IsNullOrWhiteSpace(postId))
{
//todo: save changes
context.Response.ContentType = "text/plain";
context.Response.Write("");
context.Response.End();
}
var files = context.Request.Files;
if (files.Keys.Count > 0)
{
foreach (string fileKey in files)
{
var file = context.Request.Files[fileKey];
if (file == null || file.ContentLength == 0)
continue;
//todo: در اینجا مسایل امنیتی آپلود فراموش نشود
var fileName = Path.GetFileName(file.FileName);
var rootPath = context.Server.MapPath("~/images/");
file.SaveAs(Path.Combine(rootPath, fileName));
var json = new JavaScriptSerializer().Serialize(new { link = "images/" + fileName });
// البته اینجا یک فایل بیشتر ارسال نمیشود
context.Response.ContentType = "text/plain";
context.Response.Write(json);
context.Response.End();
}
}
context.Response.ContentType = "text/plain";
context.Response.Write("");
context.Response.End();
}
public bool IsReusable
{
get { return false; }
}
}
}
در اینجا نحوهی مدیریت سمت سرور auto save و همچنین ارسال تصاویر ادیتور Froala ، ذکر شدهاند. با استفاده از context.Request.Form میتوان به عناصر ارسالی به سرور دسترسی پیدا کرد. همچنین توسط context.Request.Files، اگر فایلی ارسال شده بود، ذخیره شده و نهایتا خروجی JSON مدنظر بازگشت داده میشود.
یک نکتهی امنیتی مهم <location path="upload">
<system.webServer>
<handlers accessPolicy="Read" />
</system.webServer>
</location>
تنظیم فوق را در web.config سایت، جهت Read only کردن پوشهی ارسال تصاویر، حتما مدنظر داشته باشید. در اینجا فرض شدهاست که پوشهی uploads قرار است قابلیت اجرای فایلهای پویا را نداشته باشد.
کدهای کامل این مطلب را در ادامه میتوانید دریافت کنید Froala-Sample