官方文档:制作一个插件 | TinyMCE中文文档中文手册
首先在TinyMCE/plugins文件夹中创建一个与插件同名的文件夹。该文件夹内的插件js文件命名方式有两种。一种为plugin.js,当开发人员使用未压缩的tinymce.js时,会使用该文件。同样,在使用tinymce.min.js时,会加载加载plugin.min.js。所以如果你不确定会使用tinymce.js还是tinymce.min.js,干脆两个都留着,一个叫plugin.js,一个叫plugin.min.js。
需求是:给两张图片的标题文字之间插入通过计算的空格数量,让后端生成的word文档每个标题文字能够在图片下方正中间。
下面这个的功能是获取两张图片的总宽度以及两张图中间的空格数量,然后用公式:图片总宽度/20+图片之间空格数量,得到需要在光标当前位子插入公式得到的空格数量。
注意:通过获取到的手动插入的空格,可以发现富文本存在多个空格在一起时,值是一个空字符和一个 的形式。所以插入空格时要插入这样的字符串,并且在数据保存到数据库之后,再从数据库查询到的这个数据,多个空格不再是一个空字符和一个 的形式,而是全都是一个一个的空字符,所以获取两张图片之间的空格数量,要取(空字符数量+ 数量)和两个图片之间字符串长度中的更大的值。
目前这个计算插入空格数量的公式是有问题的,文字长度、文字字符类型等因素都会影响其每个字符像素值,所以还需完善。
// index.js
(function () {
'use strict';
var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
var insertSpace = function (editor) {
let spaceNum = getSpaceNum(editor)
let insertContent = ''
for(let i = 0; i]*>/g); // 匹配所有的图片标签
if (imageTags && imageTags.length > 1) {
const firstImageIndex = content.indexOf(imageTags[0]);
const secondImageIndex = content.indexOf(imageTags[1]);
const spaceText = content.substring(firstImageIndex + imageTags[0].length, secondImageIndex);
console.log(imageTags[0], 'imageTags[0]')
console.log(spaceText, 'spaceText')
console.log(spaceText.length, 'spaceText.length')
const spaceTextWithoutImages = spaceText.replace(/]*>/g, '');
console.log(spaceTextWithoutImages, 'spaceTextWithoutImages')
const spaceCount = (spaceTextWithoutImages.match(/ /g) || []).length; // 统计空格数量
const emptyCount = (spaceTextWithoutImages.match(/ /g) || []).length; // 统计空字符数量
console.log(spaceCount, emptyCount , 'spaceCount emptyCount')
return spaceTextWithoutImages.length>1&&spaceCount===0?spaceTextWithoutImages.length:(spaceCount+emptyCount)
}
return 0; // 默认情况下返回 0
}
// 计算需要插入空格数量
var getSpaceNum = function (editor) {
// console.log(editor, 'editor')
var imageElement = editor.dom.select('img'); // 获取所有图片元素
// console.log(imageElement, 'imageElement')
/*if (imageElement.length > 0) {
var firstImage = imageElement[0];
var width = firstImage.width;
var height = firstImage.height;
console.log('Image size:', width, 'x', height);
}*/
let totalWidth = 0
let imgNum = imageElement.length
for(let i = 0; i < imgNum; i++){
totalWidth += imageElement[i].width
}
console.log(totalWidth, 'totalWidth')
// console.log(getCurrentLine(editor), 'getCurrentLine')
console.log(getCurrentLineLength(editor), 'getCurrentLineLength')
let textLen = getCurrentLineLength(editor)
let spaceBetweenImg = getSpaceCountBetweenImages(editor)
console.log(spaceBetweenImg, 'spaceBetweenImg')
return totalWidth/20 + spaceBetweenImg
// return (totalWidth/25 + textLen/2)
}
// 获取当前光标所在行
function getCurrentLine(editor) {
const selection = editor.selection;
if (selection) {
const range = selection.getRng();
const startContainer = range.startContainer;
const startOffset = range.startOffset;
const textBeforeCursor = startContainer.textContent.slice(0, startOffset);
const lastLinebreakIndex = textBeforeCursor.lastIndexOf('\n');
const currentLineStartIndex = lastLinebreakIndex < 0 ? 0 : lastLinebreakIndex + 1;
const currentLineEndIndex = startOffset;
const currentLine = startContainer.textContent.slice(currentLineStartIndex, currentLineEndIndex);
return currentLine;
}
return null;
}
// 获取当前行的所有字符长度
function getCurrentLineLength(editor) {
const selection = editor.selection;
if (selection) {
const range = selection.getRng();
console.log(range, 'range')
const currentNode = range.startContainer;
const currentLine = getCurrentLineText(currentNode);
console.log(currentLine, 'currentLine')
return currentLine.length;
}
return 0;
}
// 获取当前行的文本内容
function getCurrentLineText(node) {
const textNodes = getTextNodes(node);
let currentLineText = '';
console.log(textNodes, 'textNodes')
for (let i = 0; i < textNodes.length; i++) {
const textNode = textNodes[i];
currentLineText += textNode.textContent;
/*if (isCurrentLineTextNode(textNode)) {
currentLineText += textNode.textContent;
}*/
// console.log(isCurrentLineTextNode(textNode), 'isCurrentLineTextNode')
}
console.log(currentLineText, 'currentLineText')
return currentLineText;
}
// 判断文本节点是否在当前行
function isCurrentLineTextNode(textNode) {
const selection = document.getSelection();
console.log(selection, 'selection')
if (selection) {
const range = selection.getRangeAt(0);
console.log(range, 'range2')
const startContainer = range.startContainer;
console.log(startContainer, 'startContainer2')
if (startContainer === textNode || textNode.contains(startContainer)) {
return true;
}
}
return false;
}
// 获取当前节点及其子节点中的文本节点
function getTextNodes(node) {
const textNodes = [];
function traverse(node) {
// console.log(Node, 'Node')
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push(node);
} else {
const children = node.childNodes;
if (children) {
for (let i = 0; i < children.length; i++) {
traverse(children[i]);
}
}
}
}
traverse(node);
return textNodes;
}
var register = function (editor) {
editor.addCommand('mceInsertSpace', function () {
insertSpace(editor);
});
};
var register$1 = function (editor) {
editor.ui.registry.addButton('insertspace', {
tooltip: '插入空格',
text: '插入空格',
onAction: function (_api) {
return editor.execCommand('mceInsertSpace');
},
});
};
function Plugin () {
global.add('insertspace', function (editor) {
register(editor);
register$1(editor);
});
}
Plugin();
}());