yma16-logo

前言

大家好,我是yma16,本文分享关于前端文本编辑器原理——从javascripthtmlcss开始。
文本编辑器
文本编辑器是指具有格式化文本和图像编辑功能的文本编辑器

参考文档https://w3c.github.io/selection-api/#abstract

htmlcontenteditable属性

全局属性 contenteditable一个枚举属性,表示元素是否可被用户编辑。如果可以浏览器修改元素组件以允许编辑

<!DOCTYPE html&gt;
<html&gt;
	<head&gt;
		<meta charset="utf-8"&gt;
		<title&gt;富文本编辑器</title&gt;
	</head&gt;
	<style&gt;
		blockquote {
		  background: #eee;
		  border-radius: 5px;
		  margin: 16px 0;
		}
		
		blockquote p {
		  padding: 15px;
		}
		
		cite {
		  margin: 16px 32px;
		  font-weight: bold;
		}
		
		blockquote p::before {
		  content: '201C';
		}
		
		blockquote p::after {
		  content: '201D';
		}
		
		[contenteditable='true'] {
		  caret-color: red;
		}

	</style>
	<body>
		<blockquote contenteditable="true">
		  <p>Edit this content to add your own quote</p>
		</blockquote>
		
		<cite contenteditable="true">-- Write your own name here</cite>

	</body>
</html>

效果如下可以输入编辑html元素
rich-text

💖 输入光标位置浏览器获取selection

getSelection() method
GetSelection ()方法返回一个 Selection 对象,该对象表示用户选择的文本范围插入符号当前位置

使用Selection.toString () 返回指定的文本

例:

<body>
	<blockquote contenteditable="true">
	  <p>Edit this content to add your own quote</p>
	</blockquote>
	
	<cite contenteditable="true">-- Write your own name here</cite>
	<button onclick="printSelection()">console.log(getSelection)</button>

</body>
<script type="text/javascript">
	const printSelection=()=>{
		const selection=window.getSelection()
		console.log('selection',selection)
		console.log('selection.toString()',selection.toString())
	}
</script>

效果如下:
selection.toString

getRangeAt 获取指定索引范围

函数接受一个索引
返回,其中
结束的索引值,endOffset
开始的索引值,startOffset
效果下图
getRangeAt

💖 修改光标位置

调用 setStart() 和 setEnd() 方法,来修改一个光标位置或拖蓝范围
Range.setStart()
Range.setStart() 方法用于设置 Range的开始位置

如果起始节点类型是 Text、Comment 或 CDATASection之一,那么 startOffset 指的是从起始节点算起字符偏移量。对于其他 Node 类型节点startOffset 是指从起始结点开始算起子节点偏移量

如果设置的起始位点在结束点之下(在文档中的位置),将会导致选区折叠起始点和结束点都会被设置为指定起始位置
startNode
startNode 用于设定 Range的起始位置

startOffset
必须为不小于 0 的整数表示startNode的开始位置算起的偏移量
Range.setEnd()
Range.setEnd()
方法用于设置 Range的结束位置

如果结束节点类型是 Text、Comment 或 CDATASection之一,那么 endOffset 指的是从结束节点算起字符偏移量。对于其他 Node 类型节点endOffset 是指从结束结点开始算起子节点偏移量

如果设置的结束点在起始点之上(在文档中的位置),将会导致选区折叠起始点和结束点都会被设置为指定的结束位置。
endNode
endNode用于设定 Range的结束位置。

endOffset
必须为不小于 0 的整数。表示从endNode的结束位置算起的偏移量
语法

range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);

例:
点击不失去焦点跳转开始和结束,避免失去焦点使用preventDefault

<body>
	<blockquote contenteditable="true">
		<p>Edit this content to add your own quote</p>
	</blockquote>

	<cite contenteditable="true">-- Write your own name here</cite>
	<button onclick="printSelection()">console.log(getSelection)</button>
	<button id='start-id'>jumpt start</button>
	<button id='end-id'>jumpt end</button>


</body>
<script type="text/javascript">
	function printSelection() {
		const selection = window.getSelection()
		console.log('selection', selection)
		console.log('selection.toString()', selection.toString())
		console.log('selection.getRangeAt(0)', selection.getRangeAt(0))
	}

	function jumpStart() {
		let range = window.getSelection().getRangeAt(0);
		let textEle = range.commonAncestorContainer;
		range.setStart(range.startContainer, 0);
		range.setEnd(range.startContainer, 0);
	}

	function jumpEnd() {
		let range = window.getSelection().getRangeAt(0);
		let textEle = range.commonAncestorContainer;
		range.setStart(range.startContainer, textEle.length);
		range.setEnd(range.endContainer, textEle.length);
	}
	window.onload = function() {
		document.getElementById('start-id').addEventListener('click', function(e) {
			jumpStart()
		})
		document.getElementById('start-id').addEventListener('mousedown', function(e) {
			e.preventDefault()
		})
		
		document.getElementById('end-id').addEventListener('click', function(e) {
			jumpEnd()
		})
		document.getElementById('end-id').addEventListener('mousedown', function(e) {
			e.preventDefault()
		})
	}
</script>

效果下图
riche-editor-positon

💖 设置选取range

Selection.addRange()
概述
向选区(Selection)中添加一个区域(Range)。

语法

sel.addRange(range)

例子
失去焦点之后恢复选区

<body>
	<blockquote contenteditable="true">
		<p>Edit this content to add your own quote</p>
		<b>yma16</b>
	</blockquote>

	<cite contenteditable="true">-- Write your own name here</cite>
	<br>
	<button id='print-id'>console.log(getSelection)</button>
	<br>
	<br>
	<button id='start-id'>jump start</button>
	<button id='end-id'>jump end</button>
	<button id='focus-id'>focus content</button>


</body>
<script type="text/javascript">
	const config = {
		selection: null
	}

	function printSelection() {
		const selection = window.getSelection()

		range = document.getSelection().getRangeAt(0).cloneRange();
		config.cloneRange = range;
		console.log('selection', selection)
		// console.log('selection.toString()', selection.toString())
		// console.log('selection.getRangeAt(0)', selection.getRangeAt(0))
	}

	function jumpStart() {
		let range = window.getSelection().getRangeAt(0);
		let textEle = range.commonAncestorContainer;
		range.setStart(range.startContainer, 0);
		range.setEnd(range.startContainer, 0);
		range = document.getSelection().getRangeAt(0).cloneRange();
		config.cloneRange = range;
	}

	function jumpEnd() {
		let range = window.getSelection().getRangeAt(0);
		let textEle = range.commonAncestorContainer;
		range.setStart(range.startContainer, textEle.length);
		range.setEnd(range.endContainer, textEle.length);
		range = document.getSelection().getRangeAt(textEle.length).cloneRange();
		config.cloneRange = range;
	}

	function focusContent() {
		document.getSelection().removeAllRanges(); //把没用的Ranges删除
		console.log('config.cloneRange',config.cloneRange)
		document.getSelection().addRange(config.cloneRange); //恢复Range
	}
	window.onload = function() {
		document.getElementById('print-id').addEventListener('click', function(e) {
			printSelection()
		})
		document.getElementById('print-id').addEventListener('mousedown', function(e) {
			e.preventDefault()
		})
		document.getElementById('start-id').addEventListener('click', function(e) {
			jumpStart()
		})
		document.getElementById('start-id').addEventListener('mousedown', function(e) {
			e.preventDefault()
		})

		document.getElementById('end-id').addEventListener('click', function(e) {
			jumpEnd()
		})
		document.getElementById('end-id').addEventListener('mousedown', function(e) {
			e.preventDefault()
		})
		document.getElementById('focus-id').addEventListener('click', function(e) {
			focusContent()
		})
		document.getElementById('focus-id').addEventListener('mousedown', function(e) {
			e.preventDefault()
		})
	}
</script>

效果如下:
focus-content

⭐总结

Contenteditable属性
Contenteditable是一种HTML属性,用于指定页面中的元素是否可以编辑。以下是Contenteditable的总结:

  1. Contenteditable属性可以应用于HTML元素上,如divspan、p、h1等等。

  2. 当Contenteditable属性设置为true时,用户可以编辑元素内的文本、图像内容

  3. Contenteditable属性的取值包括true和false,分别表示可编辑不可编辑。

  4. Contenteditable属性可以通过JavaScript来动态修改

  5. Contenteditable属性的兼容性很好,支持大多数现代浏览器

  6. 虽然Contenteditable属性很方便,但也存在一些潜在安全问题,因此应该谨慎使用

富文本编辑器

富文本编辑器是一种允许用户编辑带有样式格式的文本的编辑器。它与普通文本编辑器的区别在于,它允许用户使用各种字体颜色大小加粗斜体下划线超链接图片等来设计呈现文本内容。其原理主要包括以下几个方面:

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!
scene

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向
✏️ 评论,是我进步的财富
💖 感谢你的阅读

原文地址:https://blog.csdn.net/qq_38870145/article/details/133579239

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_49567.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注