(function(){ tinymce.create('tinymce.plugins.annoFormats', { init : function(ed, url){ var t = this; t.editor = ed; ed.addCommand('Anno_Monospace', function() { tinymce.activeEditor.formatter.toggle('monospace'); }); ed.addCommand('Anno_Preformat', function() { tinymce.activeEditor.formatter.toggle('preformat'); }); ed.addButton('annopreformat', { title : 'Preformat', //ed.getLang('advanced.references_desc'), cmd : 'Anno_Preformat', }); ed.addButton('annomonospace', { title : 'Monospace', //ed.getLang('advanced.references_desc'), cmd : 'Anno_Monospace', }); // Add node change function which updates format dropdown ed.onInit.add(function() { ed.onNodeChange.add(t._nodeChanged, t); }) }, // Update format dropdown on change _nodeChanged : function (ed, cm) { if (c = cm.get('annoformatselect')) { var parent = ed.dom.getParent(ed.selection.getNode(), 'HEADING, PARA, SEC'), selVal; if (parent) { selVal = parent.nodeName.toLowerCase(); } else { selVal = 'format'; } c.select(selVal); } }, // @TODO Translation for formats createControl : function(n, cm) { var t = this, c, ed = t.editor; if (n == 'annoformatselect') { function applyAnnoFormat(format) { var sel = ed.selection, dom = ed.dom, range = sel.getRng(), remove = false; // We don't care about the selection, just collapse sel.collapse(0); // Returns a new node that removes all the unsupported tags of the new format function getNewNode(originalNode, newNodeName) { var newNode = ed.dom.create(newNodeName, null, '
'+originalNode.innerHTML+'
'); // We want to remove the div, which is required above dom.remove(newNode.childNodes[0], true); for (var i=0; i < newNode.childNodes.length; i++) { childNode = newNode.childNodes[i]; if (childNode.nodeName == 'DIV') { dom.remove(childNode, true); } if (childNode.nodeType != 3 && !ed.schema.isValidChild(newNode.nodeName.toLowerCase(), childNode.nodeName.toLowerCase())) { //@TODO maybe keep formats, just strip them dom.remove(childNode); } } return newNode; }; // Determines whether or not the immediate parent supports the new format type function canApplyFormat(node, newFormat) { return !!ed.schema.isValidChild(node.parentNode.nodeName.toLowerCase(), newFormat.toLowerCase()); } // Find first parent var wrapper = ed.dom.getParent(sel.getNode(), 'HEADING, PARA, SEC'); // Only continue if we can insert the new format into the parent node. if (!canApplyFormat(wrapper, format) && wrapper !== null) { return false; } if (wrapper !== null) { // Remove2 if (format.toLowerCase() === wrapper.nodeName.toLowerCase()) { // Move to the end of the current wrapper, and get the bookmark // This prevents us from having a bookmark in the middle of an element that may be removed sel.select(wrapper); sel.collapse(0); var bookmark = sel.getBookmark(); newNode = getNewNode(wrapper, wrapper.parentNode.nodeName); wrapper.parentNode.replaceChild(newNode, wrapper); dom.remove(newNode, true); sel.moveToBookmark(bookmark); remove = true; } else { // convert newNode = getNewNode(wrapper, format); wrapper.parentNode.replaceChild(newNode, wrapper); } } else { // Insert a new node if we don't have a valid wrapper var newNode = ed.dom.create(format); range.insertNode(newNode); } if (newNode && !remove) { range.selectNodeContents(newNode); range.collapse(0); sel.setRng(range); } }; // Create the list box var listbox = cm.createListBox('annoformatselect', { title : 'Format', onselect : function(v) { ed.undoManager.beforeChange(); applyAnnoFormat(v); ed.undoManager.add(); ed.focus(); } }); // Add some values to the list box listbox.add('Heading', 'heading'); listbox.add('Paragraph', 'para'); listbox.add('Section', 'sec'); // Return the new listbox instance return listbox; } }, getInfo : function() { return { longname: 'Annotum Formats', author: 'Crowd Favorite', authorurl: 'http://crowdfavorite.com/', infourl: 'http://annotum.wordpress.com/', version: "0.1" }; } }); tinymce.PluginManager.add('annoFormats', tinymce.plugins.annoFormats); })();