HTMLエディタ上のボタンでビジュアルエディタ用のコマンド処理をする方法
まずはタイトルの日本語表現が下手くそで申し訳ないと書いておきます。
プラグイン「WP Theme ShapeShifter Extensions」の更新で追加された機能なんですが、今のところビジュアルエディタ用に追加している「SS」ボタンをHTML上で機能する方法を探しており、最近色々試していました。
まぁ本当はビジュアルエディタ用にボタン追加したコードを真似てHTMLエディタ用のコードを書いた方が良い気がしたんですが、流石にちょっと面倒だなと思って何かいい方法は無いかと探していたんですよ。
探り探りでやってみた方法ですが、役に立てば使ってみてほしいですし、他にHTML用に同じようなコードを書かなくていい方法があれば教えてほしいです。
概要と問題点など
まず始める前に整理です。
紹介するのはビジュアルエディタ用に書いたコードをHTMLエディタで使うということですが、もうちょっと厳密に書くと、ビジュアルエディタに書いたコードは、TinyMCEのプラグインという形で登録されます。
ただ、其の中でボタンを追加して、コマンド処理を色々登録していくんですが、これらはビジュアルエディタを開いた時に初期化されますので、普段からHTMLエディタを使用している場合、一度ビジュアルエディタをタブ切り替えで開かないと、ビジュアルエディタ用のコードが読まれないんですよ。
まずはビジュアルエディタ用のプラグインコードを読ませることからです。
手順としては、
- プラグイン用コードを編集
- プラグインコードを読ませる。
- クイックタグでプラグインコードのコマンド処理を実行
となります。
オプションとして、ポップアップ上で別IDでTinyMCEエディタを初期化した際の処理方法なども紹介していきます。
基本的なクイックタグ設定方法
まずは基本的なクイックタグの設定方法も紹介しておきます。
QTags.addButton( id, display, arg1, arg2, access_key, title, priority, instance );
- id ( string ) ( 必須 ) ボタンID
- display ( string ) ( 必須 ) 表示されるテキスト
- arg1 ( string ) ( 必須) オープンタグ
- arg2 ( string ) ( オプション ) クローズタグ
- access_key ( string ) ( オプション ) ショートカットキー
- title ( string ) ( オプション ) タイトル
- priority ( int ) ( オプション ) ボタンの位置
- instance ( string ) ( オプション ) クイックタグの特定のインスタンスにあるボタンを制限し、 存在しない場合はすべてのインスタンスに追加します。
まぁこちらはクイックタグAPIの参照ページに載っていますので各自ご参照ください。
「QTags」はグローバルなオブジェクトですので、JavaScriptで管理ページのフッターにでも出力されるコードに書いておけば読まれるようになります。
値を返すことで、それぞれ「オープンタグ」と「クローズタグ」をそれぞれ挿入することが出来ますが、クイックタグの「オープンタグ」で、
QTags.insertContent( insertedContent );
といった感じで、値を返さず、上記のような処理を行うと任意の値を挿入することが出来ます。
ビジュアルエディタ用のプラグインコードの編集
通常のビジュアルエディタ用のプラグインコードでは、MCEボタンの処理に、
editor.insertContent( insertedContent );
というようなコードが書かれます。これはクイックタグ同様のテキスト挿入コードです。
ただ、今回はクイックタグからビジュアルエディタ用のプラグインコードをコールして、コードを挿入するなどの処理を行いますので、この処理を行う場合は条件を設ける必要が出てきます。
まず、クイックタグからコールする場合に、引数のオブジェクトにHTMLエディタからコールされていると示すための値を与えます。
editor.execCommand( 'command_id', false, { editorMode: 'html' } );
といった感じです。あとは、ビジュアルエディタ側で処理するコードでは受け取る値を元に条件を設け、
if( params.editorMode == "html" ) { QTags.insertContent( text ) } else if( params.editorMode ) { editor.insertContent( text ) }
こうしておくことでHTMLエディタからコールした場合でも、ちゃんとHTMLエディタ側にテキストなどが挿入されるようになります。
あとは、エディターをグローバル化しておき、クイックタグからエディタオブジェクトを使えるようにしておきます。他に方法があるかもしれませんので、知っている方がいらっしゃればご教授願います。
// Define Editor as Global in order to use by Quicktags window.yourEditor = editor;
プラグインコードを読ませる。
では、次のステップです。ビジュアルエディタ用のプラグインコードを読ませる方法です。
通常、編集ページを開くと前に使用していたエディタモードがロードされますので、前の編集ページでビジュアルエディタを使用していた場合は、そのままプラグインコードが読まれて初期化されますが、HTMLエディタを使用していた場合、プラグインコードが読まれませんので、HTMLエディタを普段から使用していると、ビジュアルエディタに一度切り替えないとコードが読まれないんですよ。
それを解決する方法です。
まずは、クイックタグ用のJavaScriptファイルを用意して、アクションフック「admin_enqueue_scripts」でエンキューしておきましょう。
ビジュアルエディタを初期化設定
まずは、グローバル変数「tinymce」が定義されていることをチェックして、ビジュアルエディタを初期化する前に、初期化された時にトリガーされるコードを書いておきます。
// Check if global tinymce is defined if( typeof window.tinymce == "undefined" ) return; // Init Data window.tinyMCEPreInit.mceInit['content'].init_instance_callback = function( editor ) { if( editor.id === "content" ) { // Get Editor shapeshifterButtonMethods.shapeshifterEditor = window.shapeshifterEditor; if( shapeshifterButtonMethods.isHTMLActive() ) { window.switchEditors.go( 'content', 'html' ); } } };
次の初期化のコードですが、window.tinyMCEPreInit.mceInit['content']
はテキストエリアのIDが「content」TinyMCE用の設定データオブジェクトで、そのinit_instance_callback
に関数を定義しておきます。これは初期化された時にトリガーされる関数ですので、ここにHTMLエディターに切り替えるコードを書いておくんです。というのは、ビジュアルエディタを初期化すると、HTMLエディタからビジュアルエディタに自動的に切り替わってしまいますので、強制的にHTMLエディタに戻してやるんです。
当然、ビジュアルエディタを使用する方にとっては迷惑なコードですので、エディタの種類を判別する条件を設ける必要があり、上のコードでは「shapeshifterButtonMethods.isHTMLActive()
」でHTMLエディタが起動している場合を判別しています。
具体的なコードはおまかせしますが、これはjQueryで簡単に判別できます。エディタのラッパーを見て、そのクラスに「tmce-active」か「html-active」のどちらかが属性値に含まれていますので、「hasClass」で真偽値を取ればいいだけです。
また、「shapeshifterButtonMethods.shapeshifterEditor = window.shapeshifterEditor;
」という風にエディタを取得していますが、別にグローバルなオブジェクトをそのまま使っても良いんじゃないでしょうか。ただ、初期化されているかどうかを判別するために取得しているという一面もありますので、「エディタは別に取得しなくてグローバルなまま使うからいいよ」って方は、初期化のコードが読まれたかどうかの真偽値だけでも定義できるようにしておくといいと思います。ただ、以降のコード例にはこの変数を使っていきます。
最後に「window.switchEditors.go( 'content', 'html' );
」によって、テキストエリアのIDが「content」のTinyMCEをHTMLエディタに切り替える処理を行っています。
ビジュアルエディタを初期化
一応まだ初期化されていないことを条件にしていますが、こんな感じで書いています。
// Visual Editor Activate if( typeof shapeshifterButtonMethods.shapeshifterEditor == 'undefined' ) { // Init Visual Editor window.tinymce.init( window.tinyMCEPreInit.mceInit['content'] ); }
初期化はこれだけです。
あとは前の項目で書いたコードが読まれますので、前の編集でHTMLエディタを使用していた場合は、ビジュアルエディタが起動した後で、HTMLエディタに切り替わるようになります。
クイックタグでプラグインコードのコマンド処理を実行
ここまでスムーズに進んでいる方は恐らく大丈夫だと思いますが最後の処理です。
最初の方に紹介したクイックタグを追加するコードを書いていくのですが、まず関数を定義します。というのは、3つ目の引数「オープンタグ」の設定値にコールバックを設定し、ボタンをクリックした際にコマンド処理コードをコールするためです。
// コールバック用の関数を定義 function execYourCommand() { shapeshifterButtonMethods.shapeshifterEditor.execCommand( 'shapeshifter_items_popup', false, { // Params editorMode: 'html', itemName : 'none', isColEditorOn: false } ); } // ボタンを追加 QTags.addButton( 'shapeshifter-ss-button', 'SS', execYourCommand );
といった感じです。
まぁ試してみてください。
複数のエディタを使用する場合
延長線上の話になりますが、TinyMCEを複数使用する場合の問題です。
HTMLエディタにコンテンツ挿入するには、既に紹介したように「QTags.insertContent( text );」をコールします。
プラグイン「WP Theme ShapeShifter Extensions」のエディタに追加したボタン「SS」には「吹き出し」を挿入するものが存在しますが、これをクイックタグからポップアップさせて設定した値を挿入しようとするのですが、これがなかなか上手く行かなかったんですね。おまけにエラーも発生しないので原因がよく分からなかったので、結構時間を食わされました。
では、何故問題が起こったのかです。
ポップアップでも何でも良いんですが、TinyMCEで編集する場合、焦点が当てられているエディタはグローバル変数で管理されていて、フォーカスされたエディタのIDがセットされるようになっているんですよ。
吹き出し挿入までの処理は、
- 設定ウィンドウをポップアップ
- 画像とテキストを設定
- 挿入ボタンをクリック -> HTMLを挿入
- ウィンドウを閉じる(ポップアップHTMLを削除)
となっていますが、2のテキストにビジュアルエディタを使用していますので、ここでIDが「content」のコンテンツ編集用のエディタではなく、ポップアップした一時的なビジュアルエディタに焦点が当てられ、3の処理が4で削除されるエディタに挿入されていたんですよ。
ですので、HTMLを挿入する前に、エディタのIDを「content」に切り替える処理が必要になるんです。
// 焦点の当たっているエディタの切り替え window.wpActiveEditor = editor.prevEditorId; // HTMLエディタに切り替え window.switchEditors.go( editor.prevEditorId, "html" );
ただ、コピペはしないでください。
「editor.prevEditorId」という変数は、ビジュアルエディタ用のプラグインコードで「addCommand」内で「editor.id」を取得させています。そうしておくことで、別のエディタが起動してそれに焦点が当てられても、「editor.prevEditorId」が再定義されなければ1つ前のエディタIDを使うことが出来ます。
最後に余談
ぶっちゃけ最後のやつが一番大変でした。修正方法というよりは原因が分からなかったことです。
エラーが出ないもんですから、久々にワードプレス内の「quicktags.js」や「editor.js」を見て探しました。
僕自身TinyMCEも使いこなせていない部分も多くありますので、改善点や問題点など有りましたらご教授いただけると有り難いです。