Skip to content

Instantly share code, notes, and snippets.

@cheeaun
Created October 7, 2010 02:44
Show Gist options
  • Select an option

  • Save cheeaun/614464 to your computer and use it in GitHub Desktop.

Select an option

Save cheeaun/614464 to your computer and use it in GitHub Desktop.

Revisions

  1. cheeaun created this gist Oct 7, 2010.
    239 changes: 239 additions & 0 deletions facebook-tinymce.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,239 @@
    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, '&nbsp;');
    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>&nbsp;</p>'],
    [/<\/p[^>]*>(\r|\n|\s)*<br[^>]*>/gi, '</p><p>&nbsp;</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;
    }
    }
    };