[前端] 文本編輯器: TinyMCE

TinyMCE
https://www.tiny.cloud/

TinyMCE 是一款功能齊全、簡單好上手、所見即所得的   JavaScript 的   HTML 編輯器,同時 TinyMCE 這編輯器也用於 WordPress 的後台編修文章功能。需注意   TinyMCE 4.7.x 之後已不再支援 IE10 以下瀏覽器,需   IE11 以上才能運行。

以下為vue版

tinymce-vue
https://github.com/tinymce/tinymce-vue

若 vue 版想要於網頁前端直接引用時,可先用 node.js 使用 NPM 下載官方「tinymce-vue」套件,再至 NPM 資料夾中,找到安裝後的 tinymce-vue 的資料夾,取出「tinymce-vue.min.js」即可直接於網頁前端引入使用。


以下為單html檔測試範例︰
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>TinyMCE Vue Demo</title>

    <!--使用vue-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>

    <!--使用tinymce-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.8.3/tinymce.min.js"></script>
    <script type="text/javascript">
        //此區程式碼為使用 node.js 以 NPM 安裝 tinymce-vue 套件後,取出 tinymce-vue.min.js,當前為1.0.9版(2018/09/16)
        var Editor = function () { "use strict"; var n = Object.assign || function (n) { for (var e, t = 1, o = arguments.length; t < o; t++) { e = arguments[t]; for (var i in e) Object.prototype.hasOwnProperty.call(e, i) && (n[i] = e[i]) } return n }, e = ["onActivate", "onAddUndo", "onBeforeAddUndo", "onBeforeExecCommand", "onBeforeGetContent", "onBeforeRenderUI", "onBeforeSetContent", "onBeforePaste", "onBlur", "onChange", "onClearUndos", "onClick", "onContextMenu", "onCopy", "onCut", "onDblclick", "onDeactivate", "onDirty", "onDrag", "onDragDrop", "onDragEnd", "onDragGesture", "onDragOver", "onDrop", "onExecCommand", "onFocus", "onFocusIn", "onFocusOut", "onGetContent", "onHide", "onInit", "onKeyDown", "onKeyPress", "onKeyUp", "onLoadContent", "onMouseDown", "onMouseEnter", "onMouseLeave", "onMouseMove", "onMouseOut", "onMouseOver", "onMouseUp", "onNodeChange", "onObjectResizeStart", "onObjectResized", "onObjectSelected", "onPaste", "onPostProcess", "onPostRender", "onPreProcess", "onProgressState", "onRedo", "onRemove", "onReset", "onSaveContent", "onSelectionChange", "onSetAttrib", "onSetContent", "onShow", "onSubmit", "onUndo", "onVisualAid"], t = function (n) { return -1 !== e.indexOf(n) }, o = function (n, e, o) { var i, r, s, a, p, l, u, c, d = e.$props.value ? e.$props.value : "", f = e.$props.initialValue ? e.$props.initialValue : ""; o.setContent(d || f), e.$listeners.input && (r = o, a = (i = e).$props.modelEvents ? i.$props.modelEvents : null, p = Array.isArray(a) ? a.join(" ") : a, i.$watch("value", function (n, e) { r && "string" == typeof n && n !== s && n !== e && (r.setContent(n), s = n) }), r.on(p || "change keyup undo redo", function () { s = r.getContent(), i.$emit("input", s) })), l = n, u = e.$listeners, c = o, Object.keys(u).filter(t).forEach(function (n) { var e = u[n]; "function" == typeof e && ("onInit" === n ? e(l, c) : c.on(n.substring(2), function (n) { return e(n, c) })) }) }, i = 0, r = function (n) { var e = (new Date).getTime(); return n + "_" + Math.floor(1e9 * Math.random()) + ++i + String(e) }, s = function (n) { return void 0 === n || "" === n ? [] : Array.isArray(n) ? n : n.split(" ") }, a = function () { var n = "undefined" != typeof window ? window : global; return n && n.tinymce ? n.tinymce : null }, p = { apiKey: String, cloudChannel: String, id: String, init: Object, initialValue: String, inline: Boolean, modelEvents: [String, Array], plugins: [String, Array], tagName: String, toolbar: [String, Array], value: String }, l = { listeners: [], scriptId: r("tiny-script"), scriptLoaded: !1 }, u = function (e) { return function () { var t, i, r, p = n({}, e.$props.init, { selector: "#" + e.elementId, plugins: (t = e.$props.init && e.$props.init.plugins, i = e.$props.plugins, s(t).concat(s(i))), toolbar: e.$props.toolbar || e.$props.init && e.$props.init.toolbar, inline: e.inlineEditor, setup: function (n) { e.editor = n, n.on("init", function (t) { return o(t, e, n) }), e.$props.init && "function" == typeof e.$props.init.setup && e.$props.init.setup(n) } }); null !== (r = e.element) && "textarea" === r.tagName.toLowerCase() && (e.element.style.visibility = ""), a().init(p) } }; return { props: p, created: function () { this.elementId = this.$props.id || r("tiny-vue"), this.inlineEditor = this.$props.init && this.$props.init.inline || this.$props.inline }, mounted: function () { if (this.element = this.$el, null !== a()) u(this)(); else if (this.element) { var n = this.element.ownerDocument, e = this.$props.cloudChannel ? this.$props.cloudChannel : "stable", t = this.$props.apiKey ? this.$props.apiKey : ""; o = l, i = n, r = "https://cloud.tinymce.com/" + e + "/tinymce.min.js?apiKey=" + t, s = u(this), o.scriptLoaded ? s() : (o.listeners.push(s), i.getElementById(o.scriptId) || (p = o.scriptId, d = r, f = function () { o.listeners.forEach(function (n) { return n() }), o.scriptLoaded = !0 }, (h = (c = i).createElement("script")).type = "application/javascript", h.id = p, h.addEventListener("load", f), h.src = d, c.head.appendChild(h))) } var o, i, r, s, p, c, d, f, h }, beforeDestroy: function () { null !== a() && a().remove(this.editor) }, render: function (n) { return this.inlineEditor ? (o = n, i = this.elementId, r = this.$props.tagName, o(r || "div", { attrs: { id: i } })) : (e = n, t = this.elementId, e("textarea", { attrs: { id: t }, style: { visibility: "hidden" } })); var e, t, o, i, r } } }();
    </script>

    <script type="text/javascript">

        let tinymce_settings = {
            menubar: 'edit insert format table',
            plugins: 'paste imagetools textcolor link table lists advlist hr charmap',
            toolbar: 'undo redo | fontsizeselect | forecolor backcolor | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent',
            fontsize_formats: '8pt 10pt 11pt 12pt 14pt 18pt 24pt 36pt',
            paste_data_images: true,
            setup: function (ed) {
                ed.on('init', function (e) {

                    //style
                    let s = ed.getBody().style;
                    s.fontSize = '11pt';
                    s.fontFamily = '微軟正黑體';

                });
            },
            height: 250,
        };

    </script>

</head>
<body>

    <vue-tinymce id="app" v-bind:init="tinymce_settings" v-model="content"></vue-tinymce>

    <script type="text/javascript">

        //使用Vue.component加載Editor
        Vue.component('vue-tinymce', Editor);

        new Vue({
            el: '#app',
            data: {
                content: 'I am Example',
            },
        });

    </script>

</body>
</html>

載入後畫面為︰


#Javascript, frontend, Rich Text Editor, TinyMCE, vue, directly in browser, 富文本, 文本編輯器

留言