-
-
Save danott/1996383 to your computer and use it in GitHub Desktop.
Facebook's TinyMCE code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function MceEditor() {} | |
MceEditor.prototype = { | |
init: function (b, c) { | |
this.canvasId = b.id; | |
this.settings = c; | |
var a = c.plugins; | |
if (a && a.search('AtD') !== -1) this.settings.atd_rpc_id = $('post_form_id').value; | |
if (this.is_visible || !this.settings.delay_initialization) this.startEditor(); | |
}, | |
startEditor: function () { | |
if (!this.settings) { | |
this.is_visible = true; | |
return; | |
} | |
if (!this.getEditor() && !this.loadingEditor) this.loadingEditor = new AsyncRequest().setURI('/ajax/load_tiny_mce.php').setData({ | |
plugins: this.settings.plugins | |
}).setHandler(this._loadedTinyMCE.bind(this)).setOption('suppressErrorAlerts', true).send(); | |
}, | |
_loadedTinyMCE: function (c) { | |
this.settings = copy_properties(c.getPayload(), this.settings); | |
var b = this.settings.enabled_features || {}, | |
a = b.Blockquote; | |
copy_properties(this.settings, { | |
mode: 'exact', | |
theme: 'facebook', | |
doctype: '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', | |
valid_elements: 'strong/b,em/i,ol,ul,li,p' + (b.Blockquote ? ',blockquote' : '') + (b.Underline ? ',span[class]' : ''), | |
elements: this.canvasId, | |
paste_block_drop: true, | |
paste_text_sticky: true, | |
plugins: (this.settings.plugins + ',paste' || 'paste'), | |
setup: function (f) { | |
this.mceEditor = f; | |
var e = this.settings.plugins; | |
if (e && e.search('AtD') !== -1) Bootloader.loadComponents('text-editor-writing-tips', function () { | |
this.atd = new TextEditorWritingTips(this, this.settings.atd_typing_pause, this.settings.atd_max_pause); | |
}.bind(this)); | |
if (this.pendingOnInit) { | |
for (var d = 0; d < this.pendingOnInit.length; ++d) this.pendingOnInit[d](f); | |
delete this.pendingOnInit; | |
} | |
f.onInit.add(function () { | |
if (this.pendingOnMceInit) { | |
var h = this.pendingOnMceInit.length, | |
g = 0; | |
for (; g < h; ++g) this.pendingOnMceInit[g](); | |
this.pendingOnMceInit = null; | |
} | |
}.bind(this)); | |
}.bind(this) | |
}); | |
if (!this.settings.pasteAsPlainText) this.settings.paste_preprocess = function (f, e) { | |
var d = e.content; | |
function g(h) { | |
h.forEach(function (i) { | |
d = d.replace(i[0], i[1]); | |
}); | |
} | |
d = d.replace(/(<pre[^>]*>.*?<\/pre[^>]*>)/gi, function (h) { | |
h = h.replace(/(<[A-Za-z0-9]*[^>]*>)(.*?<br[^>]*>)/gi, function (i, j, k) { | |
return j + '<p>' + k + '</p>'; | |
}); | |
h = h.replace(/\s/gi, ' '); | |
return h; | |
}); | |
g([ | |
[/<(div|dl|dt|tr)[^>]*>/gi, '<p>'], | |
[/<\/(div|dl|dt|tr)[^>]*>/gi, '</p>'], | |
[/<\/t(d|able)[^>]*>/gi, '\t'], | |
[/<t(d|able)[^>]*>/gi, ''], | |
[/<br[^>]*>(\r|\n|\s)*<br[^>]*>/gi, '<p> </p>'], | |
[/<\/p[^>]*>(\r|\n|\s)*<br[^>]*>/gi, '</p><p> </p>'] | |
]); | |
e.content = d; | |
}; | |
if (this.settings.onleavemessage) onbeforeunloadRegister(function () { | |
var d = this.getEditor(); | |
if (d && d.isDirty()) return this.settings.onleavemessage; | |
}.bind(this)); | |
Bootloader.loadComponents('tinyMCE', function () { | |
tinyMCE.init(this.settings); | |
}.bind(this)); | |
}, | |
addListener: function (event, b) { | |
var c = event === 'onBlur'; | |
var a = c ? | |
function () { | |
tinymce.dom.Event.add(this.mceEditor.getWin(), 'blur', b); | |
} : function () { | |
this.mceEditor[event].add(b); | |
}; | |
this.runOnceAfterInit(a.bind(this), c); | |
}, | |
runOnceAfterInit: function (b, a) { | |
if (this.mceEditor) { | |
b(this.mceEditor); | |
} else if (a) { | |
this.pendingOnMceInit = this.pendingOnMceInit || []; | |
this.pendingOnMceInit.push(b); | |
} else { | |
this.pendingOnInit = this.pendingOnInit || []; | |
this.pendingOnInit.push(b); | |
} | |
}, | |
focus: function () { | |
if (this.mceEditor) tinyMCE.execCommand('mceFocus', false, this.canvasId); | |
return this; | |
}, | |
getPlainText: function () { | |
if (this.mceEditor) return DOM.getText(this.mceEditor.contentDocument.body); | |
return ''; | |
}, | |
getEditor: function () { | |
return this.mceEditor; | |
}, | |
setDirty: function (a) { | |
this.mceEditor && (this.mceEditor.isNotDirty = !a); | |
}, | |
getContent: function (a) { | |
this.setDirty(false); | |
return this.mceEditor ? this.mceEditor.getContent() : ''; | |
}, | |
setContent: function (a) { | |
this.runOnceAfterInit(function () { | |
this.mceEditor.setContent(a); | |
}.bind(this), true); | |
}, | |
save: function (a) { | |
this.runOnceAfterInit(function () { | |
this.mceEditor.save(); | |
this.setDirty(false); | |
}.bind(this), true); | |
}, | |
attachDialogButton: function (a) { | |
var a = a || Dialog.OK.name; | |
var b = Dialog.getCurrent(); | |
if (b) a = b.getButtonElement(a); | |
this.attachButton(a); | |
}, | |
attachButton: function (a) { | |
if (a) Event.listen(a, 'mousedown', this.save.bind(this)); | |
} | |
}; | |
function TextEditor() { | |
this.parent.construct(this); | |
} | |
TextEditor.extend('MceEditor'); | |
TextEditor.prototype = { | |
init: function (c, a, d) { | |
this.parent.init(a, d); | |
this.root = c; | |
this.buttons = {}; | |
var b = this.settings.enabled_features || {}; | |
if (b.Bold) this.addButton('fbTextEditorBold', 'Bold'); | |
if (b.Italic) this.addButton('fbTextEditorItalic', 'Italic'); | |
if (b.UnorderedList) this.addButton('fbTextEditorUnorderedList', 'InsertUnorderedList'); | |
if (b.OrderedList) this.addButton('fbTextEditorOrderedList', 'InsertOrderedList'); | |
if (b.Underline) { | |
this.addButton('fbTextEditorUnderline', 'Underline'); | |
this.addListener('onBeforeGetContent', this.setUnderlineClasses.bind(this)); | |
this.addListener('onGetContent', this.unsetUnderlineClasses.bind(this)); | |
} | |
if (b.Blockquote) this.addButton('fbTextEditorBlockquote', 'mceBlockquote'); | |
Event.listen(DOM.find(this.root, 'div.fbTextEditorToolbar'), 'click', this.onMouseClickToolbar.bind(this)); | |
this.addListener('onEvent', this.updateButtonStates.bind(this)); | |
this.addListener('onChange', this.enableAllButtons.bind(this)); | |
this.runOnceAfterInit(function () { | |
for (var e in this.buttons) Button.setEnabled(this.buttons[e].domElement, true); | |
}.bind(this)); | |
this.destroyToken = Arbiter.subscribe('page_transition', this.destroy.bind(this), Arbiter.SUBSCRIBE_NEW); | |
}, | |
destroy: function (a, b) { | |
if (a === "page_transition") { | |
var d = b.uri, | |
c = d.getQueryData(); | |
if (c && c.keep_objects) return; | |
} | |
if (this.mceEditor) this.runOnceAfterInit(function (e) { | |
tinyMCE.execCommand('mceRemoveControl', false, this.mceEditor.id); | |
this.mceEditor = null; | |
}.bind(this)); | |
Arbiter.unsubscribe(this.destroyToken); | |
}, | |
onMouseClickToolbar: function (b) { | |
var c = Parent.byClass(b.getTarget(), 'fbEditorButton'); | |
if (c) for (var a in this.buttons) if (CSS.hasClass(c, a)) { | |
this.onButtonClick(this.buttons[a].tinyMceCommand); | |
b.kill(); | |
} | |
}, | |
getRootNode: function () { | |
return this.root; | |
}, | |
addButton: function (b, c) { | |
var a = DOM.scry(this.root, 'label.' + b)[0]; | |
if (!a) return; | |
this.buttons[b] = { | |
domElement: a, | |
tinyMceCommand: c | |
}; | |
}, | |
updateButtonStates: function () { | |
for (var a in this.buttons) { | |
var b = this.buttons[a]; | |
CSS.conditionClass(b.domElement, 'uiButtonDepressed', this.getEditor().queryCommandState(b.tinyMceCommand)); | |
} | |
}, | |
enableAllButtons: function () { | |
var b = DOM.scry(this.root, 'label.uiButtonDisabled'); | |
for (var a = 0; a < b.length; a++) Button.setEnabled(b[a], true); | |
}, | |
onButtonClick: function (a) { | |
this.getEditor().execCommand(a); | |
this.updateButtonStates(); | |
}, | |
setUnderlineClasses: function (c, d) { | |
if (d && d.save) { | |
var b = $A(c.getBody().getElementsByTagName('span')), | |
a = []; | |
b.forEach(function (e) { | |
if (e.style.textDecoration === "underline") { | |
CSS.addClass(e, 'fbUnderline'); | |
a.push[e]; | |
} | |
}); | |
this.array_modified_spans = a; | |
} | |
}, | |
unsetUnderlineClasses: function () { | |
if (this.array_modified_spans) { | |
this.array_modified_spans.forEach(function (a) { | |
CSS.removeClass(a, 'fbUnderline'); | |
}); | |
this.array_modified_spans = null; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment