(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.addCommand('Anno_Insert_Section', function() {
t.insertSection();
});
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'
});
ed.addButton('annosection', {
title : 'Insert Section',
//ed.getLang('advanced.references_desc'),
cmd : 'Anno_Insert_Section'
});
// 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;
var bm = this.bookmark;
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) {
if (!node) {
return false;
}
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) {
var resetIsIE = false;
// Trick tinyMCE into thinking we're not in IE, and preform as exptected
// Range Dom errors occur otherwise.
if (tinymce.isIE) {
tinymce.isIE = false;
resetIsIE = true;
}
ed.undoManager.beforeChange();
applyAnnoFormat(v);
ed.undoManager.add();
ed.focus();
if (resetIsIE) {
tinymce.isIE = true;
}
}
});
// 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;
}
},
insertSection : function () {
var ed = this.editor, doc = ed.getDoc(), node = ed.selection.getNode(), dom = ed.dom, parent = ed.dom.getParent(node, 'SEC, BODY'), range, elYPos, vpHeight = dom.getViewPort(ed.getWin()).h;
ed.undoManager.beforeChange();
newElement = newSec();
if (parent.nodeName.toUpperCase() == 'BODY') {
parent.appendChild(newElement);
}
else {
dom.insertAfter(newElement, parent);
}
var eleArray = dom.select(' > heading', newElement);
if (eleArray.length > 0) {
newElement = eleArray[0];
}
if (doc.createRange) { // all browsers, except IE before version 9
range = doc.createRange();
range.selectNodeContents(newElement);
}
else { // IE < 9
range = doc.selection.createRange();
range.moveToElementText(newElement);
}
range.collapse(1);
ed.selection.setRng(range);
elYPos = dom.getPos(newElement).y;
// Scroll to new section
if (elYPos > vpHeight) {
ed.getWin().scrollTo(0, elYPos);
}
ed.undoManager.add();
// Create a new sec element with a title
function newSec() {
var sec = dom.create('sec', null);
dom.add(sec, 'heading', null, ' ');
dom.add(sec, 'para');
return sec;
}
},
getInfo : function() {
return {
longname: 'Annotum Formats',
author: 'Crowd Favorite',
authorurl: 'http://crowdfavorite.com/',
infourl: 'http://annotum.wordpress.com/',
version: "0.2"
};
}
});
tinymce.PluginManager.add('annoFormats', tinymce.plugins.annoFormats);
})();