link
功能描述如下:
- 单纯放置光标:
1、如果光标放到了<a>上,读取a标签的内容,并弹框显示,确定的时候,更新当前a标签。
2、否则,就创建弹框,确定的时候,按照参数添加a标签。
- seletion:
1、部分或全部选择<a>的时候,与上面的1一样,更新。
2、选择非文字的<span>、<p>等,会读取选择的文字,并弹框,把显示文字字段填成选择的文字,根据修改,把选择的文字修改成<a>。
当然实际上link的功能不止这些。还有锚点等功能。这需要看源码的条件判断,才能解锁新的功能。
这里涉及到弹框及选择部分文字的读取。
plugin.js
1 editor.addButton('link', { 2 icon: 'link', 3 tooltip: 'Insert/edit link', 4 shortcut: 'Meta+K', //快捷键 ctl+K 5 onclick: createLinkList(showDialog), 6 stateSelector: 'a[href]' 7 });
在hr中,按钮的动作是使用cmd参数指定指令名来触发指令。这里直接绑定了click函数。注:stateSelector在代码中未进行处理,见 L31976- L31991。
click函数:createLinkList依赖于link_list配置(默认未配置),所以实际上,只调用了showDialog函数(核心)。
1 function showDialog(linkList) { 2 selectedElm = selection.getNode(); 3 anchorElm = dom.getParent(selectedElm, 'a[href]'); //如果当前是a,就返回当前,否则一直找,直到找到父亲。找不到就返回null 4 onlyText = isOnlyTextSelected(); //跨元素的时候会返回false,否则返回true 5 。。。。此处省略n行。 这里面有一堆条件,都是新的功能触发。都是与setting设置有关。 6 7 win = editor.windowManager.open({ 8 title: 'Insert link', 9 data: data, 10 body: [ 11 { //地址 12 name: 'href', 13 type: 'filepicker', 14 filetype: 'file', 15 size: 40, 16 autofocus: true, 17 label: 'Url', 18 onchange: urlChange, 19 onkeyup: updateText 20 }, 21 textListCtrl, //显示文字 22 linkTitleCtrl, //标题 23 buildAnchorListControl(data.href), 24 linkListCtrl, 25 relListCtrl, 26 targetListCtrl, 27 classListCtrl 28 ], 29 onSubmit: function(e) { 30 /*eslint dot-notation: 0*/ //点击确定后,会触发此函数 31 var href; 32 33 data = tinymce.extend(data, e.data); 34 href = data.href; 35 36 // Delay confirm since onSubmit will move focus 37 function delayedConfirm(message, callback) { 38 var rng = editor.selection.getRng(); 39 40 window.setTimeout(function() { 41 editor.windowManager.confirm(message, function(state) { 42 editor.selection.setRng(rng); 43 callback(state); 44 }); 45 }, 0); 46 } 47 function insertLink() { 48 //最终的插入a的操作 49 } 50 if (!href) { //如果连接为空的时候,不进行link添加操作,并返回 51 editor.execCommand('unlink'); 52 return; 53 } 54 // 此处省略email链接的处理,与下面的一个条件类似。 55 // Is not protocol prefixed 56 if ((editor.settings.link_assume_external_targets && !/^w+:/i.test(href)) || 57 (!editor.settings.link_assume_external_targets && /^s*www[.|d.]/i.test(href))) { 58 delayedConfirm( 59 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?', 60 function(state) { 61 if (state) { 62 href = 'http://' + href; 63 } 64 65 insertLink(); 66 } 67 ); 68 69 return; 70 } 71 72 insertLink(); 73 } 74 }); 75 }
核心 1: editor.windowManager.open
打开一个model对话框,这里需要注意参数body的写法,内部是一个列表,每写一个元素,会生成一行form表单。
上面三个红框内部的数据描述分别是:
注意下type和name。这里显示成中文,请参见langs文件夹下的zh_CN,js 。它是一个字典,来替换显示的关键字的。
当url数据有‘问题’的时候,巧妙的使用了:
1 window.setTimeout(function() { 2 editor.windowManager.confirm(message, function(state) { 3 editor.selection.setRng(rng); 4 callback(state); 5 }); 6 }, 0);
来重新修改url。
解锁新技能- 添加anchor
观察plugin.js L73下面的函数:
1 function buildAnchorListControl(url) { 2 var anchorList = []; 3 4 tinymce.each(editor.dom.select('a:not([href])'), function(anchor) { //找其他没有href但有id属性的<a>,然后把他们的id列在上图的锚点处。 5 var id = anchor.name || anchor.id; 6 7 if (id) { 8 anchorList.push({ 9 text: id, 10 value: '#' + id, 11 selected: url.indexOf('#' + id) != -1 12 }); 13 } 14 }); 15 16 if (anchorList.length) { 17 anchorList.unshift({text: 'None', value: ''}); 18 19 return { 20 name: 'anchor', 21 type: 'listbox', 22 label: 'Anchors', 23 values: anchorList, 24 onselect: linkListChangeHandler 25 }; 26 } 27 }
核心二-insertLink:
1 function insertLink() { 2 var linkAttrs = { 3 href: href, 4 target: data.target ? data.target : null, 5 rel: data.rel ? data.rel : null, 6 "class": data["class"] ? data["class"] : null, 7 title: data.title ? data.title : null 8 }; 9 10 if (anchorElm) { //把光标放到了a标签处或选择a 11 editor.focus(); 12 13 if (onlyText && data.text != initialText) { 14 if ("innerText" in anchorElm) { 15 anchorElm.innerText = data.text; 16 } else { 17 anchorElm.textContent = data.text; 18 } 19 } 20 21 dom.setAttribs(anchorElm, linkAttrs); 22 23 selection.select(anchorElm); 24 editor.undoManager.add();//操作可被undo 25 } else { //未选择a 26 if (onlyText) { //未跨元素 27 editor.insertContent(dom.createHTML('a', linkAttrs, dom.encode(data.text))); //直接插入新元素即可。 28 } else { //跨元素了 29 editor.execCommand('mceInsertLink', false, linkAttrs); 30 } 31 } 32 }
涉及到的命令:
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'按钮会有加灰底提示。