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. php方法-------将汉字转为拼音或者提取汉字首字母

    将汉字转为全拼,提取汉字首字母 <?php /** * 基于PHP语言的汉语转拼音的类 * 兼容 UTF8.GBK.GB2312 编码,无须特殊处理 * 对中文默认返回拼音首字母缩写,其它字符不 ...

  2. ZBrush破解版真的好用么?

    安装ZBrush®的时候是不是经常出现各种奇葩问题,使用ZBrush时候是不是经常出现停止工作状况,究其原因,原来都是破解搞的鬼.ZBrush破解版你还敢用么? 随着国人对版权的重视,越来越多的制作商 ...

  3. Pyhton学习——Day54

    #Django内容回顾# -请求响应HTTP协议(有.无状态)默认传递的是字符串# 传递字符串分为两个部分:1.http1.1 GET /url /index + 请求头# Provisional h ...

  4. linux 源码包安装拾遗

    源码包安装和apt-get/yum的区别 安装前的区别:概念上的区别 rpm和dpkg包是经过编译过的包,并且其安装位置由厂商说了算,厂商觉得安装在哪里合适,就会装在哪里,而源码包则是没有经过编译的文 ...

  5. [HDU1052]Tian Ji -- The Horse Racing(田忌赛马)

    题目大意:田忌赛马问题,给出田忌和齐威王的马的数量$n$和每匹马的速度$v$,求田忌最多赢齐威王多少钱(赢一局得200,输一局扣200,平局不得不扣). 思路:贪心. 1.若田忌最慢的马可以战胜齐王最 ...

  6. 转载:CentOS查看本机公网IP命令

    icanhazip.com 使你在任何地方知道你的公网IP地址 icanhazip.com是一个网址,你在浏览器中输入这个网址,你就能得到你的公网IP地址了. 我在Linux下一般使用curl ica ...

  7. vuex中mutations与actions的区别

    要执行vuex中的函数,有两种方法: 1.commit,例如this.$store.commit("GETMODULESELECTLIST"); //mutations中的方法 2 ...

  8. jvm 虚拟机参数_堆内存分配

    1.参数 -XX:+PrintGC 只要遇到 GC 就会打印日志 -XX:+UseSerialGC 配置串行回收器 -XX:+PrintGCDetails 查看详细信息,包括各个区的情况 -XX:+P ...

  9. ubuntu系统AndroidStudio改动内存大小

    位于android-studio/bin文件夹下的studio64.vmoptions和studio.vmoptions文件. 把Xms,Xmx,-XX:MaxPermSize.-XX:Reserve ...

  10. Transformation in kentico

    https://docs.kentico.com/k10/developing-websites/loading-and-displaying-data-on-websites/writing-tra ...