TinyMCEをとことんまでカスタマイズしたい方向け
前のページでTinyMCEの基本的なカスタマイズ方法について解説しました。
このページではもう一歩踏み込んで、出力されるデータの形式を変更したり、自作のボタンを追加する方法やイベントに反応して新しいウィンドウを開くといったカスタマイズ方法を解説します。
element_format
高度なカスタマイズを行うには「エディタから出力されるコンテンツを把握し必要な形に変換する」といった作業が必要になります。
そこで公式のContent Filteringページから特に重要と思われる項目を解説していきます。
このオプションでHTMLモードまたはXHTMLモードを指定することができます。
ざっくり言えば、改行の扱いが<br>か<br />かの違いです。
この章では出力結果を変換するため、出力の結果も見られるようにします。
具体的には以下のようにして検証を行います。
<?php function h($s) { echo htmlspecialchars($s, ENT_QUOTES, "UTF-8"); } $data = @$_POST["foo"]; ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="js/tinymce/tinymce.min.js"></script> <script> tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 element_format : 'html' }); </script> </head> <body> <form method="post"> <!-- 送信されたデータを表示 --> <textarea if="foo" name="foo"><?php h($data); ?></textarea> <input type="submit" value="送信"> </form> <h2>送信データ</h2> <?php if ($data) { ?> <pre><?php h($data); ?></pre> <?php } ?> </body> </html>
ちなみにTinyMCEでは改行を行うと自動で段落が作られます。そのため段落内で改行を行うには「Shift + Enter」と入力してください。
通常の出力ではxml形式なので<br />となっている。
htmlと指定すると以下のように<br>となる。
encoding
山括弧(<>)やアンド(&)がEntity処理されて渡されます。
デフォルトでは無効になっています。
tinymce.init({ selector: 'textarea', // change this value according to your HTML encoding: 'xml' });
通常「test」と入力した場合、以下のようになります。
<p>test</p>
xmlとすると以下のようにEntity処理されます。
<p>test</p>
entities
Entity処理を行う文字とコードの一覧です。
奇数項目が「数値文字参照の数字部分」、偶数項目が対応する「文字実体参照の名前部分」となります。例えばノーブレークスペースの場合は「 」と「 」なので「160,nbsp」となります。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 entities : '160,,162,euro' });
通常数値文字の¢は¢です。つまり#¢です。
このデモでは「162,euro」としているので、¢を入力すると出力は€となり、以下のようになります。
<p>€</p>
蛇足ですが対応する文字コードを入力しないと「&;」とだけ出力されます。(上のデモで言うノーブレークスペース。つまり特定の文字を削除するといった用途には使えない)
Entity文字の一覧は「TinyMCE – entities」というページにあります。
tinyMCE.init({ ... entities : '160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,' + '171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,' + '183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,' + '194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,' + '205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,' + '216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,' + '227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,' + '238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,' + '249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,' + '917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,' + '931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,' + '950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,' + '963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,' + '8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,' + '8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,' + '8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,' + '8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,' + '8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,' + '8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,' + '376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,' + '8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro' });
entity_encoding
Entity処理の形式を指定します。
ちなみにTinyMCEがbase entitiesとする「< > & ‘ “」はこの設定のいかんにかかわらず強制的にEntity処理されます。ただし「‘ “」で囲まれた要素に限り「< >」がそのまま出力されます。
おそらく脆弱性対策なのだと思いますが、個人的にはありがた迷惑な実装だと思います。多重エスケープの原因にもなるため、入力時にはそのままで、出力時にエスケープ処理することが基本だと思います。
namedとすると文字実体参照。¢であれば¢となる。
numericとすると数値実体参照。¢であれば¢となる。
rawとすると生データ。¢であれば¢となる。ただし「< > & ‘ “」は別。
tinymce.init({ selector: 'textarea', // change this value according to your HTML entity_encoding : "raw" });
entity_encoding:namedのテスト デモ31ページ
entity_encoding:numericのテスト デモ32ページ
entity_encoding:rawのテスト デモ33ページ
それぞれ¢を入力して試してみてください。
force_p_newlines(旧式)
このオプションは削除予定ですが重要な項目のため、他の解説から拝借している場合は、以下のforced_root_blockに置き換えてください。
forced_root_block
TinyMCEでは要素を追加すると自動で新たな段落(P要素)が作成されます。
英語圏では問題ないのかもしれませんが、日本語では同じ段落で改行するというほうが多いのではないでしょうか。実は段落内での改行はShift + Enterで可能なのですが、ほとんどの利用者は知らないと思います。
そこで必要になるのがこのオプションです。
このオプションをfalseにすることで、Enterで改行になります。また、Shift + Enterで段落が作られるようになります。要は改行と段落の扱いが逆になるということです。
tinymce.init({ selector: 'textarea', // change this value according to your HTML forced_root_block : false });
forced_root_block_attrs
上のforced_root_blockで追加される要素の属性を決められます。段落に独自のクラスやタグを追加したいといった用途に使えます。
tinymce.init({ selector: 'textarea', // change this value according to your HTML forced_root_block_attrs: { 'class': 'myclass', 'data-something': 'my data' } });
forced_root_block_attrsのテスト デモ35ページ
valid_elements
装飾された要素を渡す際に有効にする属性を指定します。
つまり、このオプションで有効でない要素は削除されます。
書式が特殊なので、Control characters:をご覧ください。
tinyMCE.init({ selector: 'textarea', // change this value according to your HTML valid_elements : 'a[href|target=_blank],strong/b,div[align],br' });
このデモではa属性やstrongなどしか有効でないので、送信ボタンを押すと、斜体や右寄せといった要素は削除されるのを確認してください。
block_formats
formatselectでプルダウンした際に表示されるメニュー。
デフォルトは以下の通り。
Default Value: 'Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre'
今回は「見出し」という表記に変更します。
tinymce.init({ selector: 'textarea', // change this value according to your html toolbar: 'formatselect', block_formats: "Paragraph=p;見出し1=h2;見出し2=h3;見出し3=h4" });
このデモでは「見出し1」を選択すると「h2」で囲まれます。
ちなみにtoolでformatselectを指定しないと動作しない。(formatsの項目とは異なる)
fontsize_formats
フォントサイズのプルダウンメニューを変更する。
スペース区切りでpt、pxもしくは%を指定する。
tinymce.init({ selector: 'textarea', // change this value according to your HTML toolbar: 'fontsizeselect', fontsize_formats: '8pt 36pt' });
formats
エディタに予め用意された書式や各種ボタンの動作を変更します。
柔軟なカスタマイズが可能な反面、要素を追加したり削除したりとなるとフォーマットの理解がかかせません。
フォーマット一覧(Built in formats)
この項目はTinyMCEで既に定義されたフォーマットの一覧。上書きすることで変更が可能となる。
alignleft aligncenter alignright alignjustify bold italic underline strikethrough forecolor hilitecolor fontname fontsize blockquote removeformat p h1, h2, h3, h4, h5, h6 div address pre div code dt, dd samp
フォーマットパラメータ(Format parameters)
それぞれのフォーマットへ変更を加える際の仕様。
各要素の特徴を理解することが重要となる。
inline 実行した際に使われるラッパーを指定する。spanなど。インライン要素の場合。 block 実行した際に使われるラッパーを指定する。h1など。ブロック要素の場合。 selector 実行した際に影響を与える要素を指定する。p,h1,h2,h3ul,ol,liなど classes 要素に追加されるCSSを指定する。text-align:right;など attributes 要素に追加される属性を指定する。独自のname属性など exact 特定のラッパーで囲まれている場合は除外するといった場合に利用する。 wrapper 特定の要素のラッパーであることを指定する。
なかなか複雑な仕組みであることを理解していただけたと思います。
そしてTinyMCEのドキュメントは往々にしてそうですが、公式のサンプルはそのままではまともに動作しません。
まずは上書きして動作を変更するデモをご覧ください。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 formats: { alignleft: {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', styles: {'text-align': 'right'}} } });
これは公式で用意されている左寄せを上書きして右寄せに変更したものです。
各フォーマットは「タイトル:{設定}」といった構成になっています。selectorで適応する要素を指定、stylesで追加するCSSを指定しています。
公式のサンプルでは「classes : ‘left’」となっていますが、これでは「class=”left”」という追記を行うだけです。(独自のCSSを読み込まない限り動作しません)
続いて新しいフォーマットを追加して利用する方法を紹介します。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="js/tinymce/tinymce.min.js"></script> <script> tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 formats: { custom_format: {block : 'h1', attributes : {title : 'Header'}, styles : {color : 'red'}} } }); </script> </head> <body> <textarea></textarea> <a href="#" onclick="tinymce.activeEditor.formatter.apply('custom_format');return false;">[Apply custom format]</a> <a href="#" onclick="tinymce.activeEditor.formatter.remove('custom_format');return false;">[Remove custom format]</a> </body> </html>
文字を入力して選択した状態で[Apply custom format]をクリックすると自作したフォーマットが適用されます。[Remove custom format]で無効になります。
クリックをフラグに作成したフォーマットをオンオフしています。このデモではテキストリンクでしたが、自作のボタンやリストを追加してコールバック関数で指定すればオリジナルのボタンやリストを簡単に実装できます。
style_formats
書式のプルダウンメニューを変更することができます。
決まった書式しか使わないような場合には便利です。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 style_formats: [ {title: 'Bold text', inline: 'b'}, {title: 'Red text', inline: 'span', styles: {color: '#ff0000'}}, {title: 'Red header', block: 'h1', styles: {color: '#ff0000'}}, {title: 'Example 1', inline: 'span', classes: 'example1'}, {title: 'Example 2', inline: 'span', classes: 'example2'}, {title: 'Table styles'}, {title: 'Table row 1', selector: 'tr', classes: 'tablerow1'} ] });
デフォルトの値は以下の通り
What is default style_formats?
style_formats_autohide
特定のスタイルに一致する場合のみプルダウンメニューに表示される。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 plugins:"table", style_formats: [ {title: 'Red cell', selector: 'td', styles: {'background-color': '#ff0000'}}, {title: 'White text', inline: 'span', styles: {'color': '#000000'}} ], style_formats_autohide: true });
selectorでtdとなっているので、テーブルのTable Data要素内でのみ書式に「Red cell」が表示される。
style_formats_autohideのテスト デモ42ページ
style_formats_merge
既存のメニューを活かして追加するタイプ。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 plugins:"table", style_formats: [ {title: 'Red cell', selector: 'td', styles: {'background-color': '#ff0000'}}, {title: 'White text', inline: 'span', styles: {'color': '#000000'}} ], style_formats_merge: true });
style_formats_mergeのテスト デモ43ページ
TinyMCEのツールバーに自作のボタンを追加する方法
ボタンを追加するにはaddButton()という関数を利用します。
ちなみに公式の解説は以下のとおりです。
「Create a Custom Toolbar Button」
ボタンを追加する最も簡単な例
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 toolbar: ["mybutton"], // 言語 = 日本語 setup: function(editor) { // オリジナルのプラグインボタンの追加 editor.addButton('mybutton', { text: "My Button", onclick: function () { alert("My Button clicked!"); } }); } // setup: function(editor) });
まず、setupオプションを追加します。これはエディタが読み込まれるより前に実行されるコールバック関数です。
その中でeditor.addButton()を実行しています。
第一引数のmybuttonはボタンの名前です。続いて表示のためのtext、クリックした際の動作を指定するonclickと指定します。imageでボタンアイコンのパスを指定すれば独自のアイコンも利用できます。
editor.addButtonのオプションは以下の通り
text - ボタンに表示されるテキスト icon - アイコンのスタイルシート image - アイコンのイメージ(16×16px、icon等ある場合はこの要素で上書き) tooltip - ポップアップ時に表示される onclick - ボタンをクリックした際のコールバック関数 onpostrender - ボタンがレンダリングされた際のコールバック関数 cmd - クリックした際に実行されるコマンド。(事前にコマンドを登録しておく必要あり)
注意点として、作成したボタンはtoolbarの項目で指定する必要があります。
以下のデモで、My ButtonというボタンをクリックするとMy Button clicked!というアラートが表示されます。
エディタに何かの要素を追加するにはeditor.insertContent()を利用します。簡単なものならonclickの関数内でそのまま記述する方法もあります。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 toolbar: ["mybutton"], // 言語 = 日本語 setup: function(editor) { // オリジナルのプラグインボタンの追加 editor.addButton('mybutton', { text: "My Button", onclick: function () { editor.insertContent("hoge"); } }); } // setup: function(editor) });
editor.insertContent()のテスト デモ45ページ
ボタンをクリックすると「hoge」と入力されます。
トグルボタン
トグルボタンとはクリックするごとにオンオフされるボタンです。例えばボールドやイタリックといった機能です。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 toolbar: ["strikethrough"], // 言語 = 日本語 setup: function(editor) { // オリジナルのプラグインボタンの追加 editor.addButton('strikethrough', { onclick: function () { editor.execCommand('mceToggleFormat', false, 'strikethrough'); } }); } });
onclickのコールバックでexecCommand()を実行します。第一引数にmceToggleFormatを指定するとトグルボタンになります。
strikethroughは公式でサポートされてる打ち消し線のformatsです。ボタンの定義がされているためtext等の設定は必要ありません。
もちろんオリジナルのformatsも利用できます。
ボタンのオンオフを視覚的に実現するには以下のようにします。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 toolbar: ["strikethrough"], // 言語 = 日本語 setup: function(editor) { // オリジナルのプラグインボタンの追加 editor.addButton('strikethrough', { onclick: function () { editor.execCommand('mceToggleFormat', false, 'strikethrough'); } }); }, // setup: function(editor) onpostrender: function() { var btn = this; editor.on('init', function() { editor.formatter.formatChanged('strikethrough', function(state) { btn.active(state); }); }); } // onpostrender: function() });
onpostrenderでボタンのレンダリング前にボタンの定義を変更します。
editor.on(‘init’, function(){~});の部分はエディタの初期設定へのフックです。
editor.formatter.formatChanged(‘strikethrough’, function(){~});の部分はformatterというAPIで、トグルボタン専用の定義です。formatChangedの第一引数に一致するフォーマットに状態を示すstateを渡します。
formatterに関する公式の解説
APIが出てきたので難しく感じるかもしれませんが、このへんは覚えるしかないテンプレです。必要な時にサンプルから拝借しましょう。
追加したボタンをクリックすると入力ウィンドウを開く
ここからは私がPukiWikiにTinyMCEを導入するにあたり使用したサンプルです。
実際にはどうやって利用するかの参考になれば幸いです。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="js/tinymce/tinymce.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script> tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 toolbar: ["plugin"], // 言語 = 日本語 setup: function(editor) { // オリジナルのプラグインボタンの追加 editor.addButton("plugin", { // プラグインボタンの追加 icon: "plugin", image: "./plugin.png", tooltip: "プラグイン", onclick: pluginWin, // コールバック関数 onPostRender: function() { // プラグイン要素選択時プラグインボタンアクティブ var _this = this; editor.on("NodeChange", function(e) { var is_active = jQuery( editor.selection.getNode() ).hasClass("ref"); var is_active = jQuery( editor.selection.getNode() ).hasClass("plugin"); _this.active( is_active ); }) editor.on("DblClick", function(e) { if ( e.target.className == "plugin" || e.target.className=="ref" ) { pluginWin(e.toElement.innerText); } }) }, }); function pluginWin(e) { // プラグインウィンドウを開く関数 if (String(e).match(/^(&|#)/)) { // eはボタンをクリックした場合オブジェクト、プラグインのコンテンツをダブルクリックした際は文字列が入るので判定のため文字列に一旦変換する var m = e.match(/^(&|#)(\w+)\((.*)\)([\s\S]*)?/); // プラグインの形式に対応する正規表現(暫定)。ややこしいことにインラインテキストのある無しや{}を二重にしたり、改行の有無最後のセミコロンなしでも動くプラグインがあるなど対応が複雑 if(typeof(m[4]) !== "undefined"){ if (m[4].match(/;$/)) { m[4] = m[4].replace(/;$/g, "") }; // インライン要素のあるなしにかかわらず行末の;は削除 } var inline_block_value = (m[1] === "&") ? "inline" : "block"; } else { var m = new Array("", "", "", "", ""); // ボタンをクリックした際は空のデフォルト値を指定 } tinymce.activeEditor.windowManager.open({ title: "プラグイン", width: 600, height: 300, body: [{ type: "listbox", name: "inline_block", label: "タイプ", values : [ { text: "インライン型", value: "inline" }, { text: "ブロック型", value: "block" } ], value: inline_block_value // valueの指定でデフォルト値を指定する },{ type: "textbox", name: "plugin_name", label: "プラグイン名", value: m[2] },{ type: "textbox", // 引数の数はプラグインの種類によって異なるためまとめて一つにする name: "plugin_option", label: "オプション", value: m[3] },{ type: "textbox", name: "inline_text", multiline: true, minHeight: 150, label: "インライン要素({}必須)", value: m[4] }], onsubmit: function(e) { // OKボタンをクリックした際の挙動 if (e.data.plugin_name === "") { // 入力値のバリデーション(簡易版) tinyMCE.activeEditor.windowManager.alert("プラグイン名が入力されていません。"); return; } if (e.data.inline_block === "inline") { var inline_block = ["&", ";"] } else { var inline_block = ["#", ""] } if (e.data.inline_text) { var inline_text = e.data.inline_text; inline_text = inline_text.replace(/\r?\n/g, "<br>"); } else { var inline_text = ""} editor.insertContent( '<span class="plugin" contenteditable="false" style="cursor: default;" data-mce-style="cursor: default;">' + inline_block[0] + e.data.plugin_name + '(' + e.data.plugin_option + ')' + inline_text + inline_block[1] + '</span>'); } }); } // function pluginWin() } // setup: function(editor) }); </script> </head> <body> <textarea></textarea> </body> </html>
基本的には今までの解説を組み合わせたものです。
プラグインというオリジナルのボタンを追加しました。ボタンをクリックすると独自のウィンドウが開きます。
新しいのは、windowManagerというAPIを用いて入力ウィンドウを表示する点です。他にも、jQueryを利用したり、コールバック関数に独自の関数を利用しています。
追加される要素はpluginというclassを持ち、contenteditable属性がfalseのため編集不可となっています。
代わりに追加された要素をダブルクリックするとプラグインボタンをクリックしたときと同じようにウィンドウが開き、入力した値がウィンドウに反映されます。
プラグイン要素を選択中は、トグルボタンのようにプラグインボタンが押された状態になります。ここではeditor.onで「NodeChange」というオプションを利用しています。これはエディター内で選択する範囲が変更された際に実行されます。これをフラグにpluginというクラスを選択した際にボタン要素をactiveに変更しています。
イベントについては詳しく触れていませんが、Editor Eventsには様々なフラグが用意されています。ほとんどの場合はこのAPIを利用すれば目的の実装が可能だと思います。
さらに詳しくAPIについて学びたいという方は公式のAPIページをご覧ください。
自作のプラグインを作る方法
上の例を見てもらえば分かる通り、要素が複雑になるとコードも長くなります。そんな時に有効なのが自作プラグインです。
自作プラグインの作成方法は「Create a Plugin for TinyMCE」で解説されています。
このページでは「hoge」というプラグインを作成してみます。
仕組みは簡単で「js/tinymce/plugins」というフォルダにプラグイン名のフォルダを追加すると、それがそのままプラグイン名になります。つまり「hoge」というプラグインを作りたい場合は「js/tinymce/plugins/hoge」というフォルダを作ります。
そのなかに「plugin.min.js」というファイルを作ります。(公式の解説ではplugin.jsという名前でも動作すると解説されていますが、動作しません)
中身はtinymce.PluginManager.add()という関数を作り、プラグイン名の「hoge」を第一引数に指定すれば、tinymce.init()のsetupオプションで設定したコールバック関数と同じように使用できます。
今回は上のプラグインというオリジナルボタンを追加したコードをプラグイン化してみます。
tinymce.PluginManager.add('hoge', function(editor, url) { editor.addButton("plugin", { // プラグインボタンの追加 icon: "plugin", image: "./plugin.png", tooltip: "プラグイン", onclick: pluginWin, // コールバック関数 onPostRender: function() { // プラグイン要素選択時プラグインボタンアクティブ var _this = this; editor.on("NodeChange", function(e) { var is_active = jQuery( editor.selection.getNode() ).hasClass("ref"); var is_active = jQuery( editor.selection.getNode() ).hasClass("plugin"); _this.active( is_active ); }) editor.on("DblClick", function(e) { if ( e.target.className == "plugin" || e.target.className=="ref" ) { pluginWin(e.toElement.innerText); } }) }, }); function pluginWin(e) { // プラグインウィンドウを開く関数 if (String(e).match(/^(&|#)/)) { // eはボタンをクリックした場合オブジェクト、プラグインのコンテンツをダブルクリックした際は文字列が入るので判定のため文字列に一旦変換する var m = e.match(/^(&|#)(\w+)\((.*)\)([\s\S]*)?/); // プラグインの形式に対応する正規表現(暫定)。ややこしいことにインラインテキストのある無しや{}を二重にしたり、改行の有無最後のセミコロンなしでも動くプラグインがあるなど対応が複雑 if(typeof(m[4]) !== "undefined"){ if (m[4].match(/;$/)) { m[4] = m[4].replace(/;$/g, "") }; // インライン要素のあるなしにかかわらず行末の;は削除 } var inline_block_value = (m[1] === "&") ? "inline" : "block"; } else { var m = new Array("", "", "", "", ""); // ボタンをクリックした際は空のデフォルト値を指定 } tinymce.activeEditor.windowManager.open({ title: "プラグイン", width: 600, height: 300, body: [{ type: "listbox", name: "inline_block", label: "タイプ", values : [ { text: "インライン型", value: "inline" }, { text: "ブロック型", value: "block" } ], value: inline_block_value // valueの指定でデフォルト値を指定する },{ type: "textbox", name: "plugin_name", label: "プラグイン名", value: m[2] },{ type: "textbox", // 引数の数はプラグインの種類によって異なるためまとめて一つにする name: "plugin_option", label: "オプション", value: m[3] },{ type: "textbox", name: "inline_text", multiline: true, minHeight: 150, label: "インライン要素({}必須)", value: m[4] }], onsubmit: function(e) { // OKボタンをクリックした際の挙動 if (e.data.plugin_name === "") { // 入力値のバリデーション(簡易版) tinyMCE.activeEditor.windowManager.alert("プラグイン名が入力されていません。"); return; } if (e.data.inline_block === "inline") { var inline_block = ["&", ";"] } else { var inline_block = ["#", ""] } if (e.data.inline_text) { var inline_text = e.data.inline_text; inline_text = inline_text.replace(/\r?\n/g, "<br>"); } else { var inline_text = ""} editor.insertContent( '<span class="plugin" contenteditable="false" style="cursor: default;" data-mce-style="cursor: default;">' + inline_block[0] + e.data.plugin_name + '(' + e.data.plugin_option + ')' + inline_text + inline_block[1] + '</span>'); } }); } // function pluginWin() });
これで「hogeプラグイン」が完成しました。
あとは他のプラグインと同じようにpluginsに「hoge」を追加して、ツールバーへの追加のために「plugin」と記述するだけです。
tinymce.init({ selector: 'textarea', language: "ja", // 言語 = 日本語 plugins: 'hoge', toolbar: 'plugin' });
これでツールバーにオリジナルボタンを追加しつつ、コード自体は短くすることができます。
javaScriptを圧縮したり、配布可能な形式にしたりするTinyMCE plugin Yeoman generatorという専用のツールも存在するようです。配布予定の方は利用してください。
こちらの記事のおかげで、2日間困っていたことが解決しました。
たすかりました。ありがとうございました。
コメントありがとうございます。
お役に立てたようで何よりです。