javascript 实现富文本框选中对齐
需求:
一个可编辑(contenteditable=true)的div,对齐选中内容,左、中,右 ,其实质是:对选中的末梢节点,找到块属性的父元素,设置text-algin:center:
MDN:
text-alignCSS属性定义行内内容(例如文字)如何相对它的块父元素对齐。text-align并不控制块元素自己的对齐,只控制它的行内内容的对齐。
分析需求:
我们来分解一下这个需求的三个关键问题: ”选中部分“,”块元素“,"末梢元素"
1如何获取选中的部分 *
这里涉及到的Web API Document.getSelection().getRangeAt(0) 这里只处理一个选取的情况
注意:光标所在位置,光标所在节点 视为选中区域
2什么是块元素
MDN:
display:block这个值会生成一个块级元素盒子,同时在该元素之前和之后打断(换行)。简单来说就是,这个值会将该元素变成块级元素。
除非特殊指定,诸如标题(
<h1>等)和段落(<p>)默认情况下都是块级的盒子。
用做链接的
<a>元素、<span>、<em>以及<strong>都是默认处于inline状态的。
3末梢元素(没有子节点的元素)
我们操作对齐,实质是操作盒模型中的内容的对齐方式,也就是对:图片,文字 等设置对齐样式,在这里我称其为末梢节点
实现思路:
1、获取选区内的所有末梢元素(递归)
2、找到这些末梢元素的父块元素,设置其text-align:'left|center|right'
代码实现:
前端页面:一个div contenteditable="true";三个按钮:触发对齐(左,中,右)


document.querySelector("#btn_alignl").addEventListener("click", () => { Align.call(this, 'left') })
document.querySelector("#btn_alignc").addEventListener("click", () => { Align.call(this, 'center') })
document.querySelector("#btn_alignr").addEventListener("click", () => { Align('right') })
js 代码:
1、一个公共的Align方法,参数为:left|center|right
/**
* 1 通过getEndNodes(PNode,startNode,endNode, ResultNodes)获取PNode中在startNode和ResultNodes之间的所有末梢元素
* 2 遍历EndNodes,通过getBlockParent获取每一个endNode的父级block元素
* 3 设置endnode 的 blockparent.style.textAlign=left|center|right
* @param alignStr left|center|right
**/
function Align(alignStr) {
const rng = document.getSelection().getRangeAt(0)
const commonAncestor = rng.commonAncestorContainer
isStarted = false, isEnded = false
const startEndNode=getEndNodes(rng.startContainer,rng.startContainer,rng.startContainer,[])[0]
isStarted = false, isEnded = false
const endEndNode=getEndNodes(rng.endContainer,rng.endContainer,rng.endContainer,[])[0]
isStarted = false, isEnded = false
const EndNodes = getEndNodes(commonAncestor,startEndNode,endEndNode,[])
EndNodes.forEach(node => {
const blockparent = getBlockParent(node)
if (!!blockparent && blockparent.style.textAlign != alignStr) {
blockparent.style.textAlign = alignStr
}
})
}
获取选中元素的末梢节点的方法
let isStarted = false, isEnded = false
function getEndNodes(PNode,startNode,endNode, ResultNodes) {
if (PNode == startNode) { isStarted = true }
if (PNode == endNode) {
isEnded = true
ResultNodes.push(PNode)
console.log(PNode)
}
if (isStarted == true && isEnded == false && PNode.hasChildNodes()==false) { ResultNodes.push(PNode) ;console.log(PNode)}
if (PNode.hasChildNodes() && isEnded==false) {
PNode.childNodes.forEach(node => {
getEndNodes(node, startNode,endNode, ResultNodes)
});
}
// debugger
return ResultNodes
}
getBlockParent的实现--获取选中末梢节点的块父节点的实现
let blockTags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'ul', 'ol', 'li', 'div', 'body', 'td', 'th']
// let inlineTags = ['img', 'font', 'b', 'strong', 'span', 'a']
let blockTagSet = new Map()
blockTags.forEach((v) => { blockTagSet.set(v, true) });
const source = document.querySelector('div.source');
function getBlockParent(ele) {
let result = undefined
if (ele === source) {
console.log('已找到editor的根,并没有找父级block元素');
result = undefined
} else {
switch (ele.nodeType) {
//element: 判断ele是否是块级元素,判断依据1 display:block 2 默认的块级元素
case 1: {
const disPro = ele.style.display;
if (disPro && disPro.toLowerCase().indexOf('block') > -1) {
result = ele;
} else if (blockTagSet.get(ele.tagName.toLowerCase())) { result = ele }
else { result = getBlockParent(ele.parentElement) }
break;
}
case 3: {//textNode
if (!!ele.nodeValue.trim())
result = getBlockParent(ele.parentElement)
else result = undefined
break;
}
default: {
break;
}
} //end switch
}//end if
return result
}
javascript 实现富文本框选中对齐的更多相关文章
- django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用
一.modelForm操作及验证 1.获取数据库数据,界面展示数据并且获取前端提交的数据,并动态显示select框中的数据 views.py from django.shortcuts import ...
- 常用的富文本框插件FreeTextBox、CuteEditor、CKEditor、FCKEditor、TinyMCE、KindEditor ;和CKEditor实例
http://www.cnblogs.com/cxd4321/archive/2013/01/30/2883078.html 目前市面上用的比较多的富文本编辑器有: FreeTextBox 一个有很多 ...
- Android 富文本框实现 RichEditText
Android系统自带控件没有富文本框控件,如果想写一封带格式的邮件基本上不可能,EdtiText只有默认一种格式,显示不能滿足要求,!!正好项目需要研究了一下,开发了此控件,现将一些源代码开放一下, ...
- python webdriver api-操作富文本框
操作富文本框-就是邮件正文部分,可以选字体啥的 第一种方式: 一般都是在iframe里,要切进去,一般是”html/body”,编辑之后,再切出来,然后再send_keys就完事儿 #encoding ...
- webdriver高级应用- 操作富文本框
富文本框的技术实现和普通的文本框的定位存在较大的区别,富文本框的常见技术用到了Frame标签,并且在Frame里面实现了一个完整的HTML网页结构,所以使用普通的定位模式将无法直接定位到富文本框对象. ...
- 基于bootstrap的富文本框——wangEditor【欢迎增加开发】
先来一张效果图: 01. 引言 老早就開始研究富文本框的东西,在写完<深入理解javascript原型与闭包>之后,就想着要去做一个富文本框的插件的样例. 如今网络上开源的富文本框插件许多 ...
- web轻量级富文本框编辑
前言 主要介绍squire,wangeditor富文本编辑 以及用原生js 如何实现多个关键字标识 需求 如何标记多个关键字,取消关键字 第一种方法 原生 textarea 标记 准备资料参考:张鑫旭 ...
- kindeditor富文本框,上传文件后,显示文件名称
kindeditor作为一个应用广泛富文本框,我们经常会利用到它,然而在使用的过程中,发现有的地方使用起来很不方便,例如本文要说的,用户上传文件之后,默认只有文件URL,没有文件说明,如图: 点击确定 ...
- selenium 富文本框处理
selenium 富文本框处理, 网上有用API的解决方法1:参见:http://blog.csdn.net/xc5683/article/details/8963621 群里1位群友的解决方法2:参 ...
随机推荐
- Java静态变量、静态块、构造块、构造函数、main函数、普通代码块的执行顺序
测试代码 public class SingleTest { public static String v = "StaticValue"; static { System.out ...
- Solution -「JOISC 2021」「LOJ #3489」饮食区
\(\mathcal{Description}\) Link. 呐--不想概括题意,自己去读叭~ \(\mathcal{Solution}\) 如果仅有 1. 3. 操作,能不能做? ...
- Solution -「NOI 模拟赛」出题人
\(\mathcal{Description}\) 给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\ ...
- head 插件 Content-Type header [application/x-www-form-urlencoded] is not supported
{ "error": "Content-Type header [application/x-www-form-urlencoded] is not supported& ...
- .NET Core Dto映射(AutoMapper)
.Net Core Dto映射(AutoMapper) 我们假设一个场景, 采用EF Core+Web Api, 这时候可能会出现EF Core中的Entity Model和在项目中使用的Model之 ...
- Android 连接蓝牙扫码器 无输入框
Android 的APP 需要集成一个蓝牙扫码器, 特别的是,需要扫码的地方是没有输入框的(EditText),不能通过直觉上理解的通过对EditText输入事件进行监听处理,取得扫码结果.并且设备也 ...
- Docker从入门到精通
1 容器简介1.1 什么是 Linux 容器1.2 容器不就是虚拟化吗1.3 容器发展简史2 什么是 Docker?2.1 Docker 如何工作?2.2 Docker 技术是否与传统的 Linux ...
- MySQL创建表、更改表和删除表
1.创建表 mysql> create table t_address( -> id int primary key auto_increment, // 设置id为主键,自动增值 -&g ...
- 带你掌握Redis数据类型:string和Hash
摘要:Redis中有五大数据类型,分别是String.List.Set.Hash和Zset. 本文分享自华为云社区<Redis的string类型常用命令解析>,作者:灰小猿 . 先问大家一 ...
- Specified cast is not valid(C#) 引发的思考(装箱,拆箱本质)
没有很华丽的语言,直接拿代码说事情把. 这段代码,会报错吗? 结论:当然不会 这段代码会报错了.原因是为啥? 这里面的水比较深.也要提醒各位写代码的适合要引起注意.异常:System.Invalid ...