• tinymce原装插件源码分析(二)-link


    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'按钮会有加灰底提示。
  • 相关阅读:
    static&初始化顺序
    java基础语法
    MySQL调优
    Nnginx调优
    cisco 一些基本命令
    路由器密码忘记
    利用GetPrivateProfileString读取配置文件(.ini)
    MFC中OnActivate函数解析
    在MFC应用程序中传输的消息类型
    MFC中UpdateData函数解析
  • 原文地址:https://www.cnblogs.com/xunhanliu/p/10693509.html
Copyright © 2020-2023  润新知