WEB 编程:使用富文本编辑器 Quill 配合 WebBroker 后端

使用 Delphi 的 WebBroker 框架写 Web Server,需要一个前端的富文本编辑器。

评估了好几个,最后选择 Quill 这个开源的。

官方地址:Quill - Your powerful rich text editor

把前端代码,存储为一个单独的文本文件,方便随便哪个页面需要的时候可以使用。相当于封装为一个独立的对象,方便代码重用。

Quill 编辑器的代码如下:


<!-- quill 编辑器的封装 -->
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.js"></script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.snow.css" rel="stylesheet">

  <style>
    .edit_container {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
    }
    .ql-editor{
         height:400px;
     }
  </style>
  <form id="myForm" action="ContentUpdate" method="post">
        <div id="editor"></div>
        <input type="hidden" name="delta" id="deltaInput">
        <input type="hidden" name="html" id="htmlInput">
        <input type="submit" value="Submit">
  </form>

  <script>
        const quill = new Quill('#editor', {
            modules: {
            toolbar: [
              [{ header: [1, 2, false] }],
              ['bold', 'italic', 'underline'],
              ['image', 'code-block'],
            ],
            },
            theme: 'snow'
        });

        document.getElementById('myForm').addEventListener('submit', function() {
            // 获取 Quill 编辑器的内容
            const delta = JSON.stringify(quill.getContents());
            const html = quill.root.innerHTML;

            // 将内容放入隐藏输入框中
            document.getElementById('deltaInput').value = delta;
            document.getElementById('htmlInput').value = html;
        });
  </script>

把上述代码,保存为文本文件:QuillEditor.txt

然后,我们来做一个测试用的 html 文件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Quill Form Submission</title>
</head>
<body>
  <#Editor>
</body>
</html>

这个文件,保存为 index.html;

这个文件里面的 <#Editor> 是给 WebBroker 的 PageProducer 自动替换的标记。Delphi 的后台程序会将这个标记替换为前面的 QuillEditor.txt 的内容。

Delphi 的代码

首先是如何输出页面

在 Delphi 里面创建一个 WebBroker 工程,

选择 StandAlone 模式,这样方便调试。

在这个工程里面,Delphi 自动帮我们创建了一个 Web 服务器端的核心框架:TWebModule1;

拖一个 PageProducer1 到 TWebModule1 上面。设置它的属性:HTMLFile 为 index.html;

这里的 index.html 就是前面的那个简单的页面框架。这个文件只要放在程序的相同目录下,运行时 PageProducer1 就会自动加载它。当然,也可以指定绝对路径比如:D:\MyHTML\index.html;

然后,选中 PageProducer1 然后把属性面板的页标签切换到 Events,可以看到 PageProducer1 只有一个事件:OnHTMLTag,双击这个事件,Delphi IDE 自动帮我们创建事件的代码框架。在这里我们写代码如下:

procedure TWebModule1.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
  const TagString: string; TagParams: TStrings; var ReplaceText: string);
var
  SL: TStringList;
begin
  SL := TStringList.Create;
  try
    SL.LoadFromFile('QuillEditor.txt');
    if TagString = 'Editor' then
      ReplaceText := SL.Text;
  finally
    SL.Free;
  end;
end;

上述代码的解释:

PageProducer1 在加载 index.html 的时候,会触发上述事件。我们在上述事件里面写代码,首先判断标记:Editor,这个标记就是前面我们写在 index.html 里面的那个 <#Editor>

ReplaceText 则是替换那个标记的内容。这里,我们用前面保存的 Quill Editor 的那个文件的内容来替换掉 Editor 这个标记。这里会将包括尖括号在内的整个 <#Editor> 都替换掉。最终输出的页面内容就是包含 QuillEditor.txt 的内容的一个完整 HTML 页面。

再然后,双击 TWebModule1 这个界面窗口,弹出 Editing WebModule1.Actions 对话框,里面已经有一个默认的 Action,选中它,然后在属性面板里面,把它的 Producer 属性下拉选择为 PageProducer1;这样操作的目的是浏览器访问服务器时,触发这个 Action,这个 Action 最终会把它绑定的 PageProducer1 的内容输出给浏览器。

到此,输出一个包含 Quill Editor 的页面制作完毕。

服务器端接收浏览器提交的内容

在前面提到的 Editing WebModule1.Actions 对话框里面,鼠标右键,下拉菜单:Add,添加一个 Action。

选择这个 Action,设置它的属性 Path 为:ContentUpdate

切换属性面板到事件,它只有一个 OnAction 事件,双击,Delphi IDE 自动产生事件代码框架,在里面写代码如下:

procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  S: string;
  RequestBody: string;
  Delta, Html: string;
  JSONValue: TJSONObject;
  SL: TStringList;
begin
  S := Request.ContentFields.Values['html'];
  SL := TStringList.Create;
  try
    SL.Text := S;
    SL.SaveToFile('abcd.txt');
  finally
    SL.Free;
  end;

  Response.SendRedirect('Show');
  Handled := True;
end;

上述代码解释:

这个 Action 的 Path 之所以设置为 ContentUpdate,是因为页面上的 Quill Editor 里面的代码:

<form id="myForm" action="ContentUpdate" method="post">

页面代码指明了提交给服务器的路径是 ContentUpdate,因此 Delphi WebBroker 服务器里面的这个 Action 的 Path 为 ContentUpdate 的 Action 事件就会被触发。

上述代码中:

S := Request.ContentFields.Values['html'];

这里的 'html' 是对应的 Quill Editor 的 HTML 代码里面的 name 部分的名称:

<input type="hidden" name="html" id="htmlInput">

假设把上述页面代码的 name="html" 改为 "html2",那么,对应的服务器端 Delphi 的代码就应该改为:

S := Request.ContentFields.Values['html2'];

最终,Delphi 把来自浏览器提交的编辑器的内容,保存为一个文本文件 abcd.txt

保存完编辑器提交的内容后,让浏览器跳转到 show 这个路径去:

Response.SendRedirect('Show');

假设浏览器访问的是 http://127.0.0.1:8080/ 就会跳转到 http://127.0.0.1:8080/show

为服务器端增加 Show 这个路径的处理方法

在前面提到的 Editing WebModule1.Actions 对话框里面,鼠标右键,下拉菜单:Add,添加一个 Action。

选择这个 Action,设置它的属性 Path 为:Show

选中这个 Action,切换属性面板到 Events,双击它的 OnAction 事件,IDE 创建事件代码框架,写代码如下:

procedure TWebModule1.WebModule1WebActionItem2Action(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  var SL := TStringList.Create;
  try
    SL.LoadFromFile('abcd.txt');
    Response.Content := SL.Text;
  finally
    SL.Free;
  end;
end;

上述代码解释:

这里我们加载前面保存的浏览器提交过来的 Quill Editor 的内容,也就是保存的 abcd.txt,然后把这个内容作为 Response 返回给浏览器。

如果在浏览器的地址栏里面输入:http://127.0.0.1:8080/show 就会直接触发服务器端的这个事件方法,浏览器页面上就能看到之前我们在 Quill Editor 里面输入的内容。

比较有意思的是:图片

在浏览器端的富文本编辑器里面插入图片,通常是要上传图片,然后把 URL 插入到编辑器里面。但是这样又会增加不少代码工作。比如服务器端需要有个专门的 Action 来接收上传的图片文件,把图片文件保存到 Web 服务器的某个目录里面,再返回 URL;在前端需要写不少 JavaScript 代码,用来上传图片,获得 URL,然后把 URL 插入到编辑器的对应位置。等等,很麻烦。

对于  Quill Editor 来说,前面我给出的代码,用户点击它的工具栏的图片按钮,选择本地硬盘的图片文件,然后,它会自动把图片贴进编辑框的正确位置,完成图文混排。点击提交按钮后,整个文本编辑框的内容包括图片数据,一起提交给服务器。这里的图片数据是编码为 Base64 的,并且格式复合 HTML 的标准的页面嵌入BASE64图片的格式,不完整但能体现这一点的代码片段数据如下:

src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBQYF

因此,服务器端获得的完整的字符串,就是编辑器的完整内容,包含图片。把这个字符串保存后,作为文本输出给浏览器,图片也能完整地显示出来。

这样一来,图片和文字的混合编辑最终输出的就是一段字符串。在前端不需要写额外的 JavaScript 代码,后端也不需要额外的代码来处理图片文件的保存。

在实际的项目里面,后端可以把前端提交的字符串(包含图片和格式化的文字),直接原本保存到数据库的字段里面。需要显示时,直接从数据库的字段里面读取内容,输出给页面。

One more thing

前面提到的服务器端加载 Quill Editor 的代码,使用了 TStringList,重复一下代码片段:

procedure TWebModule1.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
  const TagString: string; TagParams: TStrings; var ReplaceText: string);
var
  SL: TStringList;
begin
  SL := TStringList.Create;
  try
    SL.LoadFromFile('QuillEditor.txt');
    if TagString = 'Editor' then
      ReplaceText := SL.Text;
  finally
    SL.Free;
  end;
end;

应该把上述代码,封装为一个对象,需要的地方,直接调用对象就好了。避免每个不同的 WEB 项目里面都要重复写上述代码。封装为对象,就可以实现代码重复使用。

代码如下:

unit UQuillEditor;

interface

uses
  System.SysUtils, System.Classes, System.IOUtils;

type
  TQuillEditor = class
  private

  public
    class function GetHtml(const QuillEditorFileName: string): string;
  end;

implementation

{ TQuillEditor }

class function TQuillEditor.GetHtml(const QuillEditorFileName: string): string;
var
  SL: TStringList;
begin
  if (not FileExists(QuillEditorFileName)) then raise Exception.Create('文件不存在!' + QuillEditorFileName);

  SL := TStringList.Create;
  try
    SL.LoadFromFile(QuillEditorFileName);
    Result := SL.Text;
  finally
    SL.Free;
  end;
end;

end.

结论

Quill Editor 作为一个前端的开源的富文本编辑器,用起来还是很方便的。后端使用 Delphi WebBroker 框架来开发,可以简单地封装为一个文本文件和一个简单的 Delphi 对象,在需要的地方就可以直接使用了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/879547.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

硬件工程师笔试面试——变压器

目录 9、变压器 9.1 基础 变压器原理图 变压器实物图 9.1.1 概念 9.1.2 变压器组成结构 9.1.3 变压器原理 9.1.4 变压器的类型 9.1.5 应用领域 9.2 相关问题 9.2.1 变压器的工作原理是什么? 9.2.2 如何选择合适的变压器类型? 9.2.3 变压器在实际应用中,如何进行…

安卓BLE蓝牙通讯

蓝牙测试demo 简介   Android手机间通过蓝牙方式进行通信&#xff0c;有两种常见的方式&#xff0c;一种是socket方式&#xff08;传统蓝牙&#xff09;&#xff0c;另一种是通过GATT&#xff08;BLE蓝牙&#xff09;。与传统蓝牙相比&#xff0c;BLE 旨在大幅降低功耗。这样…

iKuai使用及设置流程

iKuai使用及设置流程 iKuai安装步骤 一、配置主机 1.电脑连接ETH0网口 2.ETH1网口连接猫上面的千兆口 3.手动配置pc的IP地址和192.168.1.1./24在同一网段 3.浏览器输入192.168.1.1 admin admin 二、外网设置 1.直接联通电信网络设置 2.点击 网络设置-内外网设置-点击接…

Python “字符串操作” ——Python面试100道实战题目练习,巩固知识、检查技术、成功就业

本文主要是作为Python中列表的一些题目&#xff0c;方便学习完Python的元组之后进行一些知识检验&#xff0c;感兴趣的小伙伴可以试一试&#xff0c;含选择题、判断题、实战题、填空题&#xff0c;答案在第五章。 在做题之前可以先学习或者温习一下Python的列表&#xff0c;推荐…

食品检测与分类系统源码分享

食品检测与分类检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

推荐10款最佳的电脑监控软件,知名电脑监控软件推荐

随着互联网和科技的飞速发展&#xff0c;电脑监控软件成为企业和个人用户管理和保护信息安全的必备工具。这些软件可以帮助你实时了解电脑的使用情况、保护隐私、优化工作效率&#xff0c;甚至防止潜在的安全威胁。在这篇文章中&#xff0c;我们将为你推荐10款最佳的电脑监控软…

iPhone 16系列:摄影艺术的全新演绎,探索影像新境界

在科技的浪潮中&#xff0c;智能手机摄影功能的进化从未停歇。 苹果公司即将推出的iPhone 16系列&#xff0c;以其卓越的相机升级和创新特性&#xff0c;再次站在了手机摄影的前沿。 从硬件到软件&#xff0c;从拍照体验到图像处理&#xff0c;iPhone 16系列都展现了其在移动…

1×4矩阵键盘详解(STM32)

目录 一、介绍 二、传感器原理 工作原理介绍 三、程序设计 main.c文件 1x4key.h文件 1x4key.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 矩阵键盘是单片机外部设备中所使用排布类似于矩阵键盘组&#xff0c;矩阵式结构的键盘会比独立键盘复杂一点&#xff…

国内外ChatGPT网站集合,无限制使用【2024-09最新】~

经过我一年多以来&#xff0c;使用各种AI工具的体验&#xff0c;我收集了一批AI工具和站点 这些工具都是使用的最强最主流的模型&#xff0c;也都在各个领域里都独领风骚的产品。 而且&#xff0c;这些工具你都可以无限制地使用。 无论你是打工人、科研工作者、学生、文案写…

Python 数学建模——傅里叶变换时间序列分析

文章目录 前言原理Python 库函数实现单周期函数多周期函数真实数据挑战 前言 在数学建模过程中&#xff0c;得到一个序列 x 1 , ⋯ , x n x_1,\cdots,x_n x1​,⋯,xn​&#xff0c;我们首先要进行数据分析&#xff0c;其中就包括分析数据的周期性。这里的周期性不是数学上严格…

逆向学习系列(三)adb的使用

由于是记录学习&#xff0c;我就用结合自己的理解&#xff0c;用最通俗的语言进行讲解。 adb是android debug bridge的简写&#xff0c;其作用就是将电脑和手机相连接&#xff0c;用电脑控制手机。 一、adb哪里来 我使用的adb一般都是安装模拟器的时候&#xff0c;模拟器自带…

深入探索Android开发之Java核心技术学习大全

Android作为全球最流行的移动操作系统之一&#xff0c;其开发技能的需求日益增长。本文将为您介绍一套专为Android开发者设计的Java核心技术学习资料&#xff0c;包括详细的学习大纲、PDF文档、源代码以及配套视频教程&#xff0c;帮助您从Java基础到高级特性&#xff0c;再到A…

Basler 相机与LabVIEW进行集成

Basler 提供的相机驱动和 SDK (Software Development Kit) 允许用户通过 LabVIEW 对相机进行控制和图像采集。以下是 Basler 相机与 LabVIEW 集成的几种方式&#xff1a; 1. Baslers Pylon SDK Basler 提供的 Pylon SDK 是一套用于控制 Basler 相机的开发工具包&#xff0c;支…

13 Midjourney从零到商用·实战篇:漫画设计一条龙

大家好&#xff0c;经过前面十三篇文章,相信大家已经对Midjourney的使用非常熟悉了&#xff0c;那么现在我们开始进行实际的项目操作啦&#xff0c;想想是不是有点小激动呀&#xff0c;本篇文章为大家带来Midjourney在漫画制作领域的使用流程&#xff0c;同样也适用于现在短视频…

2024.9.12(k8s环境搭建2)

一、接9.11 19、部署calico的pod 4. 查看容器和节点状态 异常处理&#xff1a; 出现Init:0/3&#xff0c;查看node节点 /var/log/messages是否有除网络异常之外的报错信息 三台机器执行&#xff1a;&#xff08;更新版本&#xff09; yum list kernel yum update kernel reb…

基于JavaWeb开发的java+Springboot操作系统教学交流平台详细设计实现

基于JavaWeb开发的javaSpringboot操作系统教学交流平台详细设计实现 &#x1f345; 作者主页 网顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接…

云计算实训50——Kubernetes基础命令、常用指令

一、Kubernetes 自动补齐 # 安装自动补齐软件 [rootmaster ~]# yum -y install bash-completion # 临时开启自动补齐功能 [rootmaster ~]# source # 永 久开启自动补齐功能 [rootmaster ~]# echo "source > ~/.bashrc 二、Kubernetes 基础命令 kubectl [command] …

国产化中间件正在侵蚀开源中间件

开源中间件的发展趋势表明&#xff0c;它们将继续在技术创新和生态建设中发挥重要作用&#xff0c;尤其是在云计算、大数据等新兴技术领域。开源中间件如Apache Kafka、RabbitMQ、ActiveMQ和RocketMQ等在市场上有着广泛的应用。它们在技术社区中得到了良好的支持&#xff0c;并…

计算机网络30——Linux-gdb调试命令makefile

1、开始调试 编译时带-g为调试&#xff0c;带调试信息编译后的可执行文件更大 2、进入调试 使用gdb 可执行文件名——进入调试 失败版&#xff1a; 成功版&#xff1a; 3、l命令 l什么都不加——列出10行代码 l 行号——行号的行在中间&#xff0c;向上向下展示10行 4、st…

【经典文献】双边曲面去噪

文章目录 2003 TOG基本思想效果 2003 TOG 2003年&#xff0c;Fleishman等人在TOG上&#xff0c;基于图像双边滤波的思想&#xff0c;将其改造成了可以用在曲面上的双边滤波算法。 Fleishman S, Drori I, Cohen-Or D. Bilateral mesh denoising[M]//ACM SIGGRAPH 2003 Papers.…