Tag Archives: tinymce

TinyMCE Plugin: columns

tinymce.PluginManager.add("columns", function (editor) {
    function insert(count) {
        editor.undoManager.transact(function () {
            var row = editor.dom.create("div", { "class": "row" });
            var width = Math.ceil(12 / count);
            for (var index = 0; index < count; index++) {
                var column = editor.dom.add(row, "div", { "class": "col-sm-" + width });
                editor.dom.add(column, "p", {}, "Column " + (index + 1));
            }
            var node = editor.selection.getNode();
            if (node === editor.getBody()) {
                node = node.firstChild;
            }
            node.parentNode.insertBefore(row, node);
        });
    }

    function getMenuItem(text, count) {
        return {
            text: text,
            onclick: function () {
                insert(count);
            }
        };
    }

    var menu = [
        getMenuItem("Two", 2),
        getMenuItem("Three", 3),
        getMenuItem("Four", 4)
    ];
    editor.addMenuItem("columns", {
        text: "Insert columns",
        context: "insert",
        menu: menu
    });
});

TinyMCE Plugin: paragraphs

tinymce.PluginManager.add("paragraphs", function (editor) {
    function insert(place) {
        var body = editor.getBody();
        var paragraph = editor.dom.create("p");
        place(paragraph, body);
        editor.selection.setCursorLocation(paragraph);
        editor.nodeChanged();
    }

    editor.addMenuItem("paragraph", {
        text: "Insert paragraph",
        context: "insert",
        menu: [
            {
                text: "At top",
                onclick: function () {
                    insert(function (paragraph, body) {
                        body.insertBefore(paragraph, body.firstChild);
                    });
                }
            },
            {
                text: "At bottom",
                onclick: function () {
                    insert(function (paragraph, body) {
                        body.appendChild(paragraph);
                    });
                }
            }
        ]
    });
});

TinyMCE Plugin: glyphicons

tinymce.PluginManager.add("glyphicons", function (editor) {
    function insert(name) {
        editor.insertContent("<span class='glyphicon glyphicon-" + name + "'></span>");
    }

    function getMenuItem(name) {
        return {
            text: name,
            onclick: function () {
                insert(name);
            }
        };
    }

    editor.addMenuItem("glyphicons", {
        text: "Icon",
        context: "insert",
        menu: [
            getMenuItem("adjust"),
            getMenuItem("alert"),
            getMenuItem("align-center"),
            getMenuItem("align-justify"),
            getMenuItem("align-left"),
            getMenuItem("align-right"),
            getMenuItem("apple"),
            getMenuItem("arrow-down"),
            getMenuItem("arrow-left"),
            getMenuItem("arrow-right"),
            getMenuItem("arrow-up"),
            getMenuItem("asterisk"),
            getMenuItem("baby-formula"),
            getMenuItem("backward"),
            getMenuItem("ban-circle"),
            getMenuItem("barcode"),
            getMenuItem("bed"),
            getMenuItem("bell"),
            getMenuItem("bishop"),
            getMenuItem("bitcoin"),
            getMenuItem("blackboard"),
            getMenuItem("bold"),
            getMenuItem("book"),
            getMenuItem("bookmark"),
            getMenuItem("briefcase"),
            getMenuItem("btc"),
            getMenuItem("bullhorn"),
            getMenuItem("calendar"),
            getMenuItem("camera"),
            getMenuItem("cd"),
            getMenuItem("certificate"),
            getMenuItem("check"),
            getMenuItem("chevron-down"),
            getMenuItem("chevron-left"),
            getMenuItem("chevron-right"),
            getMenuItem("chevron-up"),
            getMenuItem("circle-arrow-down"),
            getMenuItem("circle-arrow-left"),
            getMenuItem("circle-arrow-right"),
            getMenuItem("circle-arrow-up"),
            getMenuItem("cloud"),
            getMenuItem("cloud-download"),
            getMenuItem("cloud-upload"),
            getMenuItem("cog"),
            getMenuItem("collapse-down"),
            getMenuItem("collapse-up"),
            getMenuItem("comment"),
            getMenuItem("compressed"),
            getMenuItem("console"),
            getMenuItem("copy"),
            getMenuItem("copyright-mark"),
            getMenuItem("credit-card"),
            getMenuItem("cutlery"),
            getMenuItem("dashboard"),
            getMenuItem("download"),
            getMenuItem("download-alt"),
            getMenuItem("duplicate"),
            getMenuItem("earphone"),
            getMenuItem("edit"),
            getMenuItem("education"),
            getMenuItem("eject"),
            getMenuItem("envelope"),
            getMenuItem("equalizer"),
            getMenuItem("erase"),
            getMenuItem("euro"),
            getMenuItem("exclamation-sign"),
            getMenuItem("expand"),
            getMenuItem("export"),
            getMenuItem("eye-close"),
            getMenuItem("eye-open"),
            getMenuItem("facetime-video"),
            getMenuItem("fast-backward"),
            getMenuItem("fast-forward"),
            getMenuItem("file"),
            getMenuItem("film"),
            getMenuItem("filter"),
            getMenuItem("fire"),
            getMenuItem("flag"),
            getMenuItem("flash"),
            getMenuItem("floppy-disk"),
            getMenuItem("floppy-open"),
            getMenuItem("floppy-remove"),
            getMenuItem("floppy-save"),
            getMenuItem("floppy-saved"),
            getMenuItem("folder-close"),
            getMenuItem("folder-open"),
            getMenuItem("font"),
            getMenuItem("forward"),
            getMenuItem("fullscreen"),
            getMenuItem("gbp"),
            getMenuItem("gift"),
            getMenuItem("glass"),
            getMenuItem("globe"),
            getMenuItem("grain"),
            getMenuItem("hand-down"),
            getMenuItem("hand-left"),
            getMenuItem("hand-right"),
            getMenuItem("hand-up"),
            getMenuItem("hd-video"),
            getMenuItem("hdd"),
            getMenuItem("header"),
            getMenuItem("headphones"),
            getMenuItem("heart"),
            getMenuItem("heart-empty"),
            getMenuItem("home"),
            getMenuItem("hourglass"),
            getMenuItem("ice-lolly"),
            getMenuItem("ice-lolly-tasted"),
            getMenuItem("import"),
            getMenuItem("inbox"),
            getMenuItem("indent-left"),
            getMenuItem("indent-right"),
            getMenuItem("info-sign"),
            getMenuItem("italic"),
            getMenuItem("jpy"),
            getMenuItem("king"),
            getMenuItem("knight"),
            getMenuItem("lamp"),
            getMenuItem("leaf"),
            getMenuItem("level-up"),
            getMenuItem("link"),
            getMenuItem("list"),
            getMenuItem("list-alt"),
            getMenuItem("lock"),
            getMenuItem("log-in"),
            getMenuItem("log-out"),
            getMenuItem("magnet"),
            getMenuItem("map-marker"),
            getMenuItem("menu-down"),
            getMenuItem("menu-hamburger"),
            getMenuItem("menu-left"),
            getMenuItem("menu-right"),
            getMenuItem("menu-up"),
            getMenuItem("minus"),
            getMenuItem("minus-sign"),
            getMenuItem("modal-window"),
            getMenuItem("move"),
            getMenuItem("music"),
            getMenuItem("new-window"),
            getMenuItem("object-align-bottom"),
            getMenuItem("object-align-horizontal"),
            getMenuItem("object-align-left"),
            getMenuItem("object-align-right"),
            getMenuItem("object-align-top"),
            getMenuItem("object-align-vertical"),
            getMenuItem("off"),
            getMenuItem("oil"),
            getMenuItem("ok"),
            getMenuItem("ok-circle"),
            getMenuItem("ok-sign"),
            getMenuItem("open"),
            getMenuItem("open-file"),
            getMenuItem("option-horizontal"),
            getMenuItem("option-vertical"),
            getMenuItem("paperclip"),
            getMenuItem("paste"),
            getMenuItem("pause"),
            getMenuItem("pawn"),
            getMenuItem("pencil"),
            getMenuItem("phone"),
            getMenuItem("phone-alt"),
            getMenuItem("picture"),
            getMenuItem("piggy-bank"),
            getMenuItem("plane"),
            getMenuItem("play"),
            getMenuItem("play-circle"),
            getMenuItem("plus"),
            getMenuItem("plus-sign"),
            getMenuItem("print"),
            getMenuItem("pushpin"),
            getMenuItem("qrcode"),
            getMenuItem("queen"),
            getMenuItem("question-sign"),
            getMenuItem("random"),
            getMenuItem("record"),
            getMenuItem("refresh"),
            getMenuItem("registration-mark"),
            getMenuItem("remove"),
            getMenuItem("remove-circle"),
            getMenuItem("remove-sign"),
            getMenuItem("repeat"),
            getMenuItem("resize-full"),
            getMenuItem("resize-horizontal"),
            getMenuItem("resize-small"),
            getMenuItem("resize-vertical"),
            getMenuItem("retweet"),
            getMenuItem("road"),
            getMenuItem("rub"),
            getMenuItem("ruble"),
            getMenuItem("save"),
            getMenuItem("save-file"),
            getMenuItem("saved"),
            getMenuItem("scale"),
            getMenuItem("scissors"),
            getMenuItem("screenshot"),
            getMenuItem("sd-video"),
            getMenuItem("search"),
            getMenuItem("send"),
            getMenuItem("share"),
            getMenuItem("share-alt"),
            getMenuItem("shopping-cart"),
            getMenuItem("signal"),
            getMenuItem("sort"),
            getMenuItem("sort-by-alphabet"),
            getMenuItem("sort-by-alphabet-alt"),
            getMenuItem("sort-by-attributes"),
            getMenuItem("sort-by-attributes-alt"),
            getMenuItem("sort-by-order"),
            getMenuItem("sort-by-order-alt"),
            getMenuItem("sound-5-1"),
            getMenuItem("sound-6-1"),
            getMenuItem("sound-7-1"),
            getMenuItem("sound-dolby"),
            getMenuItem("sound-stereo"),
            getMenuItem("star"),
            getMenuItem("star-empty"),
            getMenuItem("stats"),
            getMenuItem("step-backward"),
            getMenuItem("step-forward"),
            getMenuItem("stop"),
            getMenuItem("subscript"),
            getMenuItem("subtitles"),
            getMenuItem("sunglasses"),
            getMenuItem("superscript"),
            getMenuItem("tag"),
            getMenuItem("tags"),
            getMenuItem("tasks"),
            getMenuItem("tent"),
            getMenuItem("text-background"),
            getMenuItem("text-color"),
            getMenuItem("text-height"),
            getMenuItem("text-size"),
            getMenuItem("text-width"),
            getMenuItem("th"),
            getMenuItem("th-large"),
            getMenuItem("th-list"),
            getMenuItem("thumbs-down"),
            getMenuItem("thumbs-up"),
            getMenuItem("time"),
            getMenuItem("tint"),
            getMenuItem("tower"),
            getMenuItem("transfer"),
            getMenuItem("trash"),
            getMenuItem("tree-conifer"),
            getMenuItem("tree-deciduous"),
            getMenuItem("triangle-bottom"),
            getMenuItem("triangle-left"),
            getMenuItem("triangle-right"),
            getMenuItem("triangle-top"),
            getMenuItem("unchecked"),
            getMenuItem("upload"),
            getMenuItem("usd"),
            getMenuItem("user"),
            getMenuItem("volume-down"),
            getMenuItem("volume-off"),
            getMenuItem("volume-up"),
            getMenuItem("warning-sign"),
            getMenuItem("wrench"),
            getMenuItem("xbt"),
            getMenuItem("yen"),
            getMenuItem("zoom-in"),
            getMenuItem("zoom-out")
        ]
    });
});

TinyMCE Plugin: revert

tinymce.PluginManager.add("revert", function (editor) {
    var content;
    editor.on("LoadContent", function () {
        content = editor.getContent();
    });
    editor.addMenuItem("revert", {
        text: "Revert changes",
        context: "file",
        onclick: function () {
            editor.undoManager.transact(function () {
                editor.setContent(content);
            });
        }
    });
});

TinyMCE 3 Plugin: numalign

editor_plugin.js:

/*
 * This plugin allows centered alignment for numeric tabular data.
 * For example:
 *
 * +---------------------+
 * |              1      |
 * +---------------------+
 * |          1,000      |
 * +---------------------+
 * |      1,000,000      |
 * +---------------------+
 *
 * This is achieved by wrapping the data in a right-aligned span, which is itself centered within the cell:
 *
 * <!-- Before -->
 * <td>1,000</td>
 *
 * <!-- After -->
 * <td style="text-align: center;">
 *     <span style="display: inline-block; text-align: right; white-space: nowrap; width: 5em;">1,000</span>
 * </td>
 *
 * All spans in the column must be given an explicit (user-specified) width that can accommodate the widest data point.
 * Some experimentation may be required to determine the appropriate width.
 */

tinymce.create("tinymce.plugins.NumAlignPlugin", {
    init: function (editor, url) {
        editor.addCommand("mceNumAlign", function () {
            editor.windowManager.open({
                file: url + "/dialog.html",
                width: 240,
                height: 80,
                inline: true
            }, {
                plugin_url: url
            });
        });
        editor.addButton("numalign", {
            title: "Align Numbers",
            cmd: "mceNumAlign",
            image: url + "/button.gif"
        });
        editor.onNodeChange.add(function (editor, controlManager, node) {
            var cell = editor.dom.getParent(node, "td, th");
            controlManager.setDisabled("numalign", cell === null);
        });
    }
});
tinymce.PluginManager.add("numalign", tinymce.plugins.NumAlignPlugin);

dialog.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Align Numbers</title>
        <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
        <script type="text/javascript" src="dialog.js"></script>
    </head>
    <body>
        <form>
            <label>
                Width:
                <input type="text" id="width" name="width" />
            </label>
            <div class="mceActionPanel">
                <input type="submit" id="insert" value="OK" />
                <input type="button" id="cancel" value="Cancel" />
            </div>
        </form>
    </body>
</html>

dialog.js:

var P = tinyMCEPopup;

// Initializes the dialog.
function init() {
    var width = P.dom.get("width");
    width.value = P.getWindowArg("width", "5em");
    width.select();
    P.dom.bind(P.dom.get("insert"), "click", update);
    P.dom.bind(P.dom.get("cancel"), "click", close);
}

// Aligns data in the currently selected column and closes the dialog.
function update() {
    var cell = P.editor.dom.getParent(P.editor.selection.getStart(), "td, th");
    var index = getIndex(cell);
    var table = P.editor.dom.getParent(cell, "table");
    var rows = table.getElementsByTagName("tr");
    for (var i = 0; i < rows.length; i++) {
        var cell = getCell(rows[i], index);
        if (cell.nodeName === "TD") {
            align(cell, P.dom.get("width").value);
        }
    }
    P.editor.execCommand("mceEndUndoLevel");
    close();
}

// Returns the column index of the given cell.
function getIndex(cell) {
    var index = 0;
    var child = P.editor.dom.getParent(cell, "tr").firstElementChild;
    while (child !== null) {
        if (child === cell) {
            return index;
        }
        index += getColSpan(child);
        child = child.nextElementSibling;
    }
    return -1;
}

// Returns the cell at the given column index.
function getCell(row, index) {
    var current = 0;
    var child = row.firstElementChild;
    while (child !== null) {
        var next = current + getColSpan(child);
        if (current <= index && index < next) {
            return child;
        }
        current = next;
        child = child.nextElementSibling;
    }
    return null;
}

// If the given node is a cell, returns the column span.
// Otherwise, returns zero.
function getColSpan(node) {
    if (node.nodeName === "TD" || node.nodeName === "TH") {
        return node.colSpan;
    } else {
        return 0;
    }
}

// Updates the given cell's contents and styles for centered numeric alignment.
function align(cell, width) {
    P.editor.dom.setStyle(cell, "text-align", "center");
    
    // We need the cell's contents to be wrapped in a span
    // If the cell contains only a single span (ignoring leading and trailing whitespace text nodes), then use this span
    // (This allows us to run the plugin repeatedly on the same column)
    // Otherwise, remove the cell's child nodes, add them to a newly created span, and add the span to the cell
    var nodes = trim(cell.childNodes);
    var span;
    if (nodes.length === 1 && nodes[0].nodeName === "SPAN") {
        span = nodes[0];
    } else {
        nodes = P.editor.dom.remove(cell.childNodes);
        span = P.editor.dom.create("span");
        for (var i = 0; i < nodes.length; i++) {
            P.editor.dom.add(span, nodes[i]);
        }
        P.editor.dom.add(cell, span);
    }
    
    P.editor.dom.setStyle(span, "display", "inline-block");
    P.editor.dom.setStyle(span, "text-align", "right");
    P.editor.dom.setStyle(span, "white-space", "nowrap");
    P.editor.dom.setStyle(span, "width", width);
}

// Removes leading and trailing whitespace text nodes.
function trim(nodes) {
    if (nodes.length === 0) {
        return [];
    }
    var start = 0;
    var end = nodes.length;
    while (start < end && isWhitespace(nodes[start])) {
        start++;
    }
    while (end > start && isWhitespace(nodes[end - 1])) {
        end--;
    }
    var result = new Array(end - start);
    for (var i = 0; i < result.length; i++) {
        result[i] = nodes[start + i];
    }
    return result;
}

// Returns whether the given node is a whitespace text node.
function isWhitespace(node) {
    return node.nodeName === "#text" && node.textContent.trim().length === 0;
}

// Closes the dialog.
function close() {
    P.close();
}

P.onInit.add(init);

Download