ウィジェット配置時にウィジェットのIDナンバーをJavaScriptで使用する方法
ウィジェットをウィジェットエリアにドラッグなどして追加した時、ウィジェットのメソッド「form」で出力される部分のIDってどうなっているか知っていますか? 僕も最近まで「$this->id」で取得できるものだと思い込んでいたんですが、実際は少し異なるものでびっくりしたんです。
そもそも何故こんなことをしているのかですが、フォーム内でJavaScriptの変数名にIDナンバーを使用し、その変数にJSON型にしたウィジェットアイテムの設定値を保存し、ボタンで呼び出すメソッドの引数などである程度自由に使えるようにしたかったからです。ええ、テーマ「ShapeShifter」用に新しくスライダー機能のウィジェットを作成しています。
今回は「ウィジェットを新しく配置してから最初に保存するまで」の間で、この内の「form」が出力する箇所のウィジェットのIDナンバーについて紹介します。
先に書いておきますが、本当に細かい話ですので、まだウィジェットを作成したことがない人は、ウィジェットアイテムの基本的な作成方法については、「」で作り方を紹介していますので、そちらをご参照ください。
また、もっと良い方法があるようでしたらご提案いただけると有難いです。
追加時のIDナンバーの仕組み
ウィジェットの元になる親クラス「WP_Widget」により、各ウィジェットには自動で生成されるIDが備わっています。ええ、「$this->id」です。
じゃこの「$this->id」はどのように生成されているかというと、
$this->id = $this->id_base . '-' . $number;
となっており、この時に使用されている変数「$number」は、同じ関数内で「$this->number」と同じ値に設定されます。また、「$this->id_base」は、
$this->id_base = empty($id_base) ? preg_replace( '/(wp_)?widget_/', '', strtolower(get_class($this)) ) : strtolower($id_base);
といった形で、クラス名を小文字化したものが使用されています。
これらは本来自動で生成されるものですし、通常は「$this->get_field_id( ‘field_name’ )」といった形で(このメソッドも「$this->number」の値が含まれています。)、フォームのinputタグなどの属性値に使用されますから、通常IDのみで使用することは殆ど無いと思いますが、実際に「$this->number」を「echo」してみると、ウィジェットを新しく配置した時だけ数値以外のものが返ってくるんです。
ちゃんとソースを読んでいないのでどこまで正確なのか分かりませんので、詳しい方がいると助かります。フォーラムにでも書いてみようかな。
代替値「__i__」
実際にブラウザのツールで検証してみると、「$this->get_field_id( ‘field_name’ )」といった形で使用されているinputタグの属性値にはちゃんとIDナンバーが数値として入っているのに、何も無いところで「echo」した「$this->number」は「__i__」と定義されているんです。
ただし、これはあくまで新しくウィジェットを配置した時のみで、通常既に配置されているウィジェットなど、一度保存をしてしまった後は、何の問題もなくIDナンバーとして使用できます。
「__i__」が変換される条件(推測)
色んな箇所で試してみましたが、1つだけは条件が分かりました。それが「HTML要素の属性値に使用されている場合」です。
例えば、input要素のvalue値やidの一部に使用するなどの場合は、「__i__」はIDナンバーに変換されるようになっており、それ以外の場所では変換されず「__i__」のままですので、テキストとして出力してもIDナンバーは出てきませんので気を付けましょう。
「__i__」は出力後に変換されるが…
おそらくJavaScriptで変換されていると思うんですが、一度出力した後で値がIDナンバーに変更されていることが分かります。
例えば、変換されるであろうと予想して、inputなどのvalue属性値などに入れておき、jQueryでそれを取得してみても「__i__」のままだったんですよ。
これが僕がJavaScriptをあまり理解しないまま使っているせいなのかなと思う部分なんですが、「$( document ).ready( function() {} )」だったり、「setTimeout」で時間差で読ませたりしてみたんですが、「__i__」しか取得できなかったので、jQueryで取得することは諦めました。
どうすればIDナンバーを取得できるのか
生成されるIDナンバー「$this->number」の値を取得するには、「$this->get_settings()」というメソッドを使用します。
これは同じウィジェットアイテムの設定をまとめて取得するメソッドで、複数配置されている場合は、そのウィジェットの数分の配列で取得できるようになっています。
そして、これで取得した配列のインデックス値の最大値がウィジェットアイテムのIDナンバーになっています。
form( $instance ) { foreach( $this->get_settings() as $index => $settings ) { $widget_number = $index; } }
こうしておくと、ページロードした時のウィジェットナンバーの最大値を取得できますので、新しく配置したウィジェットアイテムのIDは、これに「プラス1」すればOKになるんですよ。
ただし、この「$this->get_settings()」は、ウィジェット配置時には現在の設定ではなく、どうやらページをロードした時点での設定が取得されるようですので、複数を新規配置することを想定すると、加算値にもプラス1しておく必要があることを忘れないようにしましょう。ページをロードしない状態であれば、ウィジェットの削除によって生成されるウィジェットのIDナンバーの数値が減ることもありません。
JavaScriptの変数名に使用してみる
上記のIDナンバーの特徴を元にして、JavaScriptでIDナンバーを使用してみます。
といった感じで、JavaScriptのグローバル変数にウィジェットのIDナンバーを取得できます。上の例では「window[ ‘widgetNumber’ ]」がIDナンバーになります。
最初はウィジェット配置した時の処理から分からなかったもんですから、結構苦労してしまいました。
という話でした。
もっと楽な取得方法があるなら、教えて欲しいです。