plugin.js
119 lines
| 1 | (function () { |
| 2 | var anchor = (function () { |
| 3 | 'use strict'; |
| 4 | |
| 5 | var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); |
| 6 | |
| 7 | var isValidId = function (id) { |
| 8 | return /^[A-Za-z][A-Za-z0-9\-:._]*$/.test(id); |
| 9 | }; |
| 10 | var getId = function (editor) { |
| 11 | var selectedNode = editor.selection.getNode(); |
| 12 | var isAnchor = selectedNode.tagName === 'A' && editor.dom.getAttrib(selectedNode, 'href') === ''; |
| 13 | return isAnchor ? selectedNode.id || selectedNode.name : ''; |
| 14 | }; |
| 15 | var insert = function (editor, id) { |
| 16 | var selectedNode = editor.selection.getNode(); |
| 17 | var isAnchor = selectedNode.tagName === 'A' && editor.dom.getAttrib(selectedNode, 'href') === ''; |
| 18 | if (isAnchor) { |
| 19 | selectedNode.removeAttribute('name'); |
| 20 | selectedNode.id = id; |
| 21 | editor.undoManager.add(); |
| 22 | } else { |
| 23 | editor.focus(); |
| 24 | editor.selection.collapse(true); |
| 25 | editor.execCommand('mceInsertContent', false, editor.dom.createHTML('a', { id: id })); |
| 26 | } |
| 27 | }; |
| 28 | var Anchor = { |
| 29 | isValidId: isValidId, |
| 30 | getId: getId, |
| 31 | insert: insert |
| 32 | }; |
| 33 | |
| 34 | var insertAnchor = function (editor, newId) { |
| 35 | if (!Anchor.isValidId(newId)) { |
| 36 | editor.windowManager.alert('Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.'); |
| 37 | return true; |
| 38 | } else { |
| 39 | Anchor.insert(editor, newId); |
| 40 | return false; |
| 41 | } |
| 42 | }; |
| 43 | var open = function (editor) { |
| 44 | var currentId = Anchor.getId(editor); |
| 45 | editor.windowManager.open({ |
| 46 | title: 'Anchor', |
| 47 | body: { |
| 48 | type: 'textbox', |
| 49 | name: 'id', |
| 50 | size: 40, |
| 51 | label: 'Id', |
| 52 | value: currentId |
| 53 | }, |
| 54 | onsubmit: function (e) { |
| 55 | var newId = e.data.id; |
| 56 | if (insertAnchor(editor, newId)) { |
| 57 | e.preventDefault(); |
| 58 | } |
| 59 | } |
| 60 | }); |
| 61 | }; |
| 62 | var Dialog = { open: open }; |
| 63 | |
| 64 | var register = function (editor) { |
| 65 | editor.addCommand('mceAnchor', function () { |
| 66 | Dialog.open(editor); |
| 67 | }); |
| 68 | }; |
| 69 | var Commands = { register: register }; |
| 70 | |
| 71 | var isAnchorNode = function (node) { |
| 72 | return !node.attr('href') && (node.attr('id') || node.attr('name')) && !node.firstChild; |
| 73 | }; |
| 74 | var setContentEditable = function (state) { |
| 75 | return function (nodes) { |
| 76 | for (var i = 0; i < nodes.length; i++) { |
| 77 | if (isAnchorNode(nodes[i])) { |
| 78 | nodes[i].attr('contenteditable', state); |
| 79 | } |
| 80 | } |
| 81 | }; |
| 82 | }; |
| 83 | var setup = function (editor) { |
| 84 | editor.on('PreInit', function () { |
| 85 | editor.parser.addNodeFilter('a', setContentEditable('false')); |
| 86 | editor.serializer.addNodeFilter('a', setContentEditable(null)); |
| 87 | }); |
| 88 | }; |
| 89 | var FilterContent = { setup: setup }; |
| 90 | |
| 91 | var register$1 = function (editor) { |
| 92 | editor.addButton('anchor', { |
| 93 | icon: 'anchor', |
| 94 | tooltip: 'Anchor', |
| 95 | cmd: 'mceAnchor', |
| 96 | stateSelector: 'a:not([href])' |
| 97 | }); |
| 98 | editor.addMenuItem('anchor', { |
| 99 | icon: 'anchor', |
| 100 | text: 'Anchor', |
| 101 | context: 'insert', |
| 102 | cmd: 'mceAnchor' |
| 103 | }); |
| 104 | }; |
| 105 | var Buttons = { register: register$1 }; |
| 106 | |
| 107 | global.add('anchor', function (editor) { |
| 108 | FilterContent.setup(editor); |
| 109 | Commands.register(editor); |
| 110 | Buttons.register(editor); |
| 111 | }); |
| 112 | function Plugin () { |
| 113 | } |
| 114 | |
| 115 | return Plugin; |
| 116 | |
| 117 | }()); |
| 118 | })(); |
| 119 |