link

功能描述如下:

  • 单纯放置光标:

1、如果光标放到了<a>上,读取a标签的内容,并弹框显示,确定的时候,更新当前a标签。

  2、否则,就创建弹框,确定的时候,按照参数添加a标签。

  • seletion:

1、部分或全部选择<a>的时候,与上面的1一样,更新。

2、选择非文字的<span>、<p>等,会读取选择的文字,并弹框,把显示文字字段填成选择的文字,根据修改,把选择的文字修改成<a>。

当然实际上link的功能不止这些。还有锚点等功能。这需要看源码的条件判断,才能解锁新的功能。

这里涉及到弹框及选择部分文字的读取。

plugin.js

     editor.addButton('link', {
icon: 'link',
tooltip: 'Insert/edit link',
shortcut: 'Meta+K', //快捷键 ctl+K
onclick: createLinkList(showDialog),
stateSelector: 'a[href]'
});

在hr中,按钮的动作是使用cmd参数指定指令名来触发指令。这里直接绑定了click函数。注:stateSelector在代码中未进行处理,见 L31976- L31991。

click函数:createLinkList依赖于link_list配置(默认未配置),所以实际上,只调用了showDialog函数(核心)。

     function showDialog(linkList) {
selectedElm = selection.getNode();
anchorElm = dom.getParent(selectedElm, 'a[href]'); //如果当前是a,就返回当前,否则一直找,直到找到父亲。找不到就返回null
onlyText = isOnlyTextSelected(); //跨元素的时候会返回false,否则返回true
。。。。此处省略n行。 这里面有一堆条件,都是新的功能触发。都是与setting设置有关。 win = editor.windowManager.open({
title: 'Insert link',
data: data,
body: [
{ //地址
name: 'href',
type: 'filepicker',
filetype: 'file',
size: 40,
autofocus: true,
label: 'Url',
onchange: urlChange,
onkeyup: updateText
},
textListCtrl, //显示文字
linkTitleCtrl, //标题
buildAnchorListControl(data.href),
linkListCtrl,
relListCtrl,
targetListCtrl,
classListCtrl
],
onSubmit: function(e) {
/*eslint dot-notation: 0*/ //点击确定后,会触发此函数
var href; data = tinymce.extend(data, e.data);
href = data.href; // Delay confirm since onSubmit will move focus
function delayedConfirm(message, callback) {
var rng = editor.selection.getRng(); window.setTimeout(function() {
editor.windowManager.confirm(message, function(state) {
editor.selection.setRng(rng);
callback(state);
});
}, 0);
}
function insertLink() {
//最终的插入a的操作
}
if (!href) { //如果连接为空的时候,不进行link添加操作,并返回
editor.execCommand('unlink');
return;
}
// 此处省略email链接的处理,与下面的一个条件类似。
// Is not protocol prefixed
if ((editor.settings.link_assume_external_targets && !/^\w+:/i.test(href)) ||
(!editor.settings.link_assume_external_targets && /^\s*www[\.|\d\.]/i.test(href))) {
delayedConfirm(
'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
function(state) {
if (state) {
href = 'http://' + href;
} insertLink();
}
); return;
} insertLink();
}
});
}

核心 1: editor.windowManager.open

打开一个model对话框,这里需要注意参数body的写法,内部是一个列表,每写一个元素,会生成一行form表单。

上面三个红框内部的数据描述分别是:

        

注意下type和name。这里显示成中文,请参见langs文件夹下的zh_CN,js 。它是一个字典,来替换显示的关键字的。

当url数据有‘问题’的时候,巧妙的使用了:

     window.setTimeout(function() {
editor.windowManager.confirm(message, function(state) {
editor.selection.setRng(rng);
callback(state);
});
}, 0);

来重新修改url。


解锁新技能- 添加anchor

观察plugin.js L73下面的函数:

         function buildAnchorListControl(url) {
var anchorList = []; tinymce.each(editor.dom.select('a:not([href])'), function(anchor) { //找其他没有href但有id属性的<a>,然后把他们的id列在上图的锚点处。
var id = anchor.name || anchor.id; if (id) {
anchorList.push({
text: id,
value: '#' + id,
selected: url.indexOf('#' + id) != -1
});
}
}); if (anchorList.length) {
anchorList.unshift({text: 'None', value: ''}); return {
name: 'anchor',
type: 'listbox',
label: 'Anchors',
values: anchorList,
onselect: linkListChangeHandler
};
}
}

核心二-insertLink:

                 function insertLink() {
var linkAttrs = {
href: href,
target: data.target ? data.target : null,
rel: data.rel ? data.rel : null,
"class": data["class"] ? data["class"] : null,
title: data.title ? data.title : null
}; if (anchorElm) { //把光标放到了a标签处或选择a
editor.focus(); if (onlyText && data.text != initialText) {
if ("innerText" in anchorElm) {
anchorElm.innerText = data.text;
} else {
anchorElm.textContent = data.text;
}
} dom.setAttribs(anchorElm, linkAttrs); selection.select(anchorElm);
editor.undoManager.add();//操作可被undo
} else { //未选择a
if (onlyText) { //未跨元素
editor.insertContent(dom.createHTML('a', linkAttrs, dom.encode(data.text))); //直接插入新元素即可。
} else { //跨元素了
editor.execCommand('mceInsertLink', false, linkAttrs);
}
}
}

涉及到的命令:

mceInsertLink (在选择位置处,可能跨元素,插入a)、unlink、

有用的函数:

editor.windowManager.open(打开一个包含指定form表单的model窗口)、editor.windowManager.confirm(内部封装了MessageBox.msgBox)、editor.insertContent(内部调用了mceInsertContent命令)、及此plugin的buildListItems(构建editor.windowManager.open中body中某个元素的value参数的)。

补:

stateSelector: 'a[href]': 功能是: 鼠标放在了这个元素上,'link'按钮会有加灰底提示。

tinymce原装插件源码分析(二)-link的更多相关文章

  1. tinymce原装插件源码分析(一)-hr

    tinymce简介 tinymce是一款能方便无限扩展的网页富文本编辑器. tinymce原装插件已经十分丰富,对于文本编辑(blog等文章)是绰绰有余,但是应对一些复杂的应用,比如在上面开发html ...

  2. tinymce原装插件源码分析(五)-searchreplace

    searchreplace 功能:查找和替换 代码注释见: https://www.xunhanliu.top/static/js/tinymce/plugins/searchreplace/plug ...

  3. tinymce原装插件源码分析(四)-fullscreen

    fullscreen 作为一款文本编辑器,全屏功能是非常有必要的.在插件中主要是修改一些css style和触发resize事件. style问题(反例): 见github源码:https://git ...

  4. tinymce原装插件源码分析(三)-code

    code: 用于显示源码.主要包含一个弹框.设置显示内容以及内容的更新. function showDialog() { var win = editor.windowManager.open({ t ...

  5. tinymce原装插件源码分析(七)-使能css、script

    在tinymce中使用css个script tinymce的编辑器中css和script默认是不起作用的.(编辑器主要面向写文章使用,考虑到xss攻击,默认是不启用的) 需要修改tinymce.js中 ...

  6. tinymce原装插件源码分析(六)-preview

    priview 此插件文件结构比较简单,按钮注册.editor.windowManager.open.窗口出现之前的渲染数据的准备.页面代码的准备. 注意: 1.preview的默认宽高设置: 2.c ...

  7. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  8. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  9. 十、Spring之BeanFactory源码分析(二)

    Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...

随机推荐

  1. nsrunloop与模式

    scrollview的模式切换:退出原来的模式使用新模式. 2018-04-18 18:16:41.208113+0800 CEMonitor[5014:410604] kCFRunLoopDefau ...

  2. EL表达式的作用与限制条件

    限制条件 只能访问域对象的数据 用法 访问基本数据类型 首先把数据保存在域对象中 pagecontext.setAttribute("name","eric") ...

  3. servletconfig和servletcontext学习

    servletconfig java.lang.String getInitParameter(java.lang.String name)  //根据参数名获取参数值 java.util.Enume ...

  4. Node Sass does not yet support your current environment: Windows 64-bit然如何解决,cnpm此问题解决方法

    这里直接说了node sass不支持当前环境,所以可以直接删掉原来不支持本机的node sass,再重新安装就行了 删除: npm uninstall --save node-sass 安装: npm ...

  5. vue安装以及配置

    今天又重新做了一遍vue的安装步骤: 1.条件,vue需要安装在node环境里面,确保安装了node. 2.安装脚手架. 找一个文件夹,放你的项目.待会儿安装的时候,项目会在你找的这个文件下新增一个你 ...

  6. Lua 中的 RSA 加解密实现

    记得之前,部门某款游戏陆陆续续收到一些玩家反馈,抱怨在登录游戏时会等待很久.初步排查后基本断定可能是此游戏的登录服务器程序某块代码有问题,于是即安排了服务器同事作排查分析但一直无果. 之后我时间有了空 ...

  7. [CodeForces] 543B Destroying Roads

    脑洞+暴力. 因为边权是1,所以bfs一下,O(n^2)求任意两点间最短路,再枚举. ans最大是\(dis_{s1,t1}+dis_{s2,t2}\) 再考虑有公共边的情况,一定存在两个点 u, v ...

  8. myEclies项目导入Eclipse中常见问题

    需要配置Tomcat 左上方菜单 windosw > Prefrences TomCat JS文件报错 打开项目位置 找到 这个文件打开 删除这一段ok

  9. jQuery 事件流的概念

    jQuery  事件流的概念 什么是事件流 DOM事件流 1. 事件捕获阶段; 2.处于目标阶段; 3.事件冒泡阶段; <!DOCTYPE html> <html lang=&quo ...

  10. WinServer-win7通过powershell操作AD-从接触到放弃

    额....我想在win7上练习AD的powershell命令 看了这篇帖子,他们说在WIN7上没法导入powershell的模块,只能在SERVER 上弄 https://social.technet ...