画像の自動並び替え機能
2021/5/17:追記
元画像のファイル名に ”-” が存在すると php で Notice が出る件を修正しています。
画像データを ajax にて送信する jQuery と、そのデータを受け取ってデータベースを更新する functions.php の部分です。本文中にも注意書きがあります。
ご確認ください。
ひとつの投稿に30ほどの画像をまとめてアップロードしているのですが、もともとファイル名順に並んでいても、メディアパネルに表示されているアップロードされた画像たちは、ある部分のまとまりで逆になっていたりします。結局、全部手動でドラッグして並び替えなくてはならないので、いよいよこれが面倒になってきました。
普通は、えっなんで?と思いますよね。
投稿にアップロードした画像をすべて投稿に貼り付けていれば、サイトを開いたときに表示される順番も当然そのままなので、アップロードしたときのメディアパネルに表示されている順番なんてのはどうでもいいことなんですね。
私的には一応、画像が主なサイトなのでたくさんの画像をアップロードしています。index.php で表示されるトップページには、そのなかの見出しの画像として三枚ほどを表示していて、シングルページにおいてすべての画像を表示するようにしています。その場合に、この並び順というのが重要になってきます。single.php のなかでページが表示されるときに画像を並び替えるという手も簡単にできるのではありますが、それだとページが表示されるときに一つ余分に処理が入ってしまうということになります。できることならページ表示は速いにこしたことはないので、余分なことはやらせたくないのです。
前々からなんとか自動で並び替えさせることができないものかと考えていたのですが、管理画面の動的に加えられるパネルなのでどこへ割り込ませればいいのかさっぱりわからず、その部分を探していくのも面倒なのでほったらかしにしていたのですが・・・。
しかし、ちょっと考えてみると、javascriptファイルさえ読み込ませれば、Ajax を使って以外に簡単にできるのではないかと。
アップロードされた画像は、投稿と同じように wp-posts テーブルにそれに関するデータが蓄えられています。post_type が、投稿であれば”post” や ”page” などで、画像の場合はそれが”attachment” になります。
アップロードされた画像は、その並び順をドラッグして変更することができますが、このときにwp-posts テーブルにあるそれぞれの画像のデータのmenu_order の値が、それぞれの並び順で更新され、このmenu_order の値によって投稿やメディアパネルが表示されたときにおいての並び順となります。
と、いうことは、メディアパネルにおいて動くjavascriptから、Ajax でデータベース上のmenu_order の値を更新してやればよいだけのことですね。
それではということで、メディアパネルにおいていかにしてjavascript を動かすかということになりますが、メディアパネルが動的に生成されるときにフックを使ってボタンとなる要素を追加してやるということが、まず普通に頭に浮かびます。
自分だけで使っている場合は、キーボードのショートカットキー( shift + r とか )で動くようにすればもっと簡単にできます。
フックにおいては探してみたものの使えそうなものがよくわからないというか、ひとつ見つけた使えそうなのは、attachment_fields_to_edit というフィルターフック。
これは画像をクリックして選択したときに右側に表示される、「添付ファイルの詳細」と題して、urlやタイトル、キャプションや代替テキストなどを設定するためのパネルに、新たに設定するためのたとえばカスタムフィールド用のフォーム要素などを追加するためのフックです。
これでもいいとは思うのですが、画像を選択状態にしないと表示されないというのがちょっと気に入らない部分ではあります。理想的には「投稿に挿入」のボタンと同じように表示できればとは、思ったりしますが・・・。
フィルターフックattachment_fields_to_edit に関しての詳細はcodex →プラグイン API/フィルターフック一覧/attachment fields to editをご覧のほど。ただ、それを見てもよくわからないのですが、ネットにもっとわかりやすく解説してくれているところがあると思います。
で、とりあえず私的には以下で動きました。もちろんfunctions.phpです。
追加する要素のタグは <a> でも <p> でも何でもいいと思います。
これにより、「メディアを追加」ボタンでメディアパネルを開き、画像を選択したときに表示される右側のパネルの「添付ファイルの表示設定」の上あたりに「sort images」のボタンが表示されることになります。ちなみにフィルターフックにおいて、引数を二つ以上受け取る場合は、引数の数を指定する必要があります。それをしないと動かないどころかそのフックを呼び出したところでエラーとなって止まってしまう。以前は動いていたのでいつからそうなったのかわからないですが・・・。
そして管理画面において独自のjavascript ファイルを読み込ませる部分。とまぁ、正確には管理画面においてはjQuery が使えるのでjQuery のファイルですが。自分の使っているテーマのフォルダに「my_admin_media.js」という名前で保存してあります。
下はネットでどなたかがお書きいただいていたものをほとんどそっくり使わせてもらったものだと思います。
そしていよいよそのjavascript というかjQuery ですが。
javascript においてやることはといえば、メディアパネルに表示されている画像の情報、wp-posts テーブルにおけるその画像を登録してある行のIDの値と、そしてファイル名順にソートする必要があるので画像のファイル名、を取得しそれらをまとめてAjax というかPOST でphp の関数へと渡すことです。
で、その動的に生成されたメディアパネルの、画像が表示されている部分のhtml はどうなっているかというと、
<li>タグの「data-id」の値がデータベースのIDの値であり、画像のファイル名は<img>タグの「src」から取得して加工すれば良いと。
すなわち.attachment のクラスを持つ要素をjQuery で取得すれば、「data-id」の値も、そして<li>の子要素である<img>のurlも取得することができます。
しかし、ここでちょっと注意しなければいけないことがあります。
それは、クリックして選択した状態の画像が存在する場合、上記の画像情報を保持している<li>要素の、<button>要素は除外して別の箇所に複製が作られています。と、いうことは.attachment の要素を取得した場合に、選択状態の画像情報はダブって取得してしまうということになります。まぁ、これは実際にやってみたところ、どうも返される結果の処理した個数が合わなくて調べたところ見つけたことなのです。ただし、その複製された画像データは、別に付加された.selection というクラスで判別することが可能でした。ですから、javascript で処理するときに、そのクラスを持つ要素を除外すればよいというわけです。
そしてもうひとつ。
メディアパネルを開いたときにすべての投稿における画像が表示されている場合もあります。もし、その状態で処理が動いてしまったらなかなかどんでもないことになってしまいます。ということで、その安全対策が必要になります。
・そこでひとつめは、「タイプで絞りこみ」メニューにおいて「この投稿へのアップロード」を選択したときにだけ動くようにすること。
・ふたつめは、処理する画像の数を制限する。
・そして保険としてもうひとつ加えるとすれば、SQL で更新する画像データを抽出するときに、その画像がアップされている親投稿のIDも抽出条件に加えること。まぁ、それだけでも十分だとは思いますが。なんといいますか・・・気が弱いもので・・・。
ということになり、親投稿のIDもどこかから取得したいわけですが、それはhtmlのはるか上の方に親投稿の情報がまとめてあります。データベースのID値は、id="post_ID" の<input>要素に入れられています。
そして、「タイプで絞込み」メニューはid="media-attachment-filters" の<select>タグになっているので、これのvalue が「この投稿へのアップロード」のときの値である「uploaded」のときに動作させればよいということになります。
と、言うようなことを含め、いろいろと試行錯誤を重ねて作ってみて実行させたところ、まぁ、それなりにうまくいったのですが、そこでまた気がつきます。
それは、「タイプで絞りこみ」メニューにおいて「この投稿へのアップロード」を選択したときにだけ動くようにしたわけですが、ということは、「タイプで絞込み」メニューを必ずクリックするということです。であれば、フックを使ってjavascript を動かすためのボタンとなる要素を仕込まなくても、そのメニューをクリックしたときに、前述したメディアパネルに常に表示されている「投稿に挿入」ボタンのあたりにjavascript で追加すればよいのだということに。であるなら、言うまでもなく、上記のattachment_fields_to_edit フィルターフックで要素を追加するコードも不要となります。
そして、試作コードを実際に使ってみるとわざわざ手動でドラッグして並び替える必要がなくなり、手間もそれに要する時間もぐっと少なくなってとても良かったということになりました。それにマウスの寿命が延びることも間違いないのです。なにせドラッグで押し続けるのはスイッチ部分の負担が大きそうだったので。
が、しかし、とは言っても、このボタンを押してもデータベース上のmenu_order の値が更新されるだけのことなので、メディアパネルに表示されている画像の並び順は元のままでなんら変化なく落ち着いています。これは一度パネルを閉じて、投稿の情報を再読み込みさせたときに並び順も読み込まれて再びパネルを開いたときに反映されるのですが、人間とは欲深いもので、やはりそれでは納得できずに要求は大きくなってしまいました。
それで、なにか良い手はないものかと、色々と考えを巡らせてみるとFlexbox を使えば簡単にできそうではあります。試してみたところなかなかそうすんなりとはいかないものです。親要素にflex をcss で設定して、子要素の画像が入っている<li>にorder で順番を指定してやればそれで出来そうではあるのですが、表示されている画像たちは静かに落ち着いたまま。
これはなぜなのかよくわからなかったのですが、コンソールにはそのorder を設定するところでエラーが出ていました。原因がなかなかわからなかったのですが、どうやらorder に関しては、その要素に元々設定がされていない場合は、後からjavascript で設定することが出来ないようです。(確かなことではありません。)
ということで、管理画面ページにおいてjavascript ファイルを読み込ませるのと同様にスタイルも設定しておけば良いのではないか、ということになります。
画像が入っている要素は<li>でありそのclassは「attachment」。そしてそれの親要素である<ul>のclass は「attachments」になっています。わかりやすいですね。親要素にはflex 関係、そしてorder の値をとりあえずすべて0 にて設定しています。
そしてjavascript においてorder の値を設定するわけなので、javascript の中で、その順番の値を取得する必要があります。上記の方法だと、並び替えをさせているのはphp においてなので、そのあたりも考えなくてはいけないということです。
単純にjavascript において並び替えをさせて、と、色々考えてみると、複数の値を関連させながらの並び替えなので連想配列を使うとか、ですね。とは思うものの、php 側でサーバーにてやらせたほうが早いのではないかという気もします。
で、結局、php 側でsort させることを選択しました。
javascript からAjax でphp に送るデータのなかに、取得した画像を含むclass 「.attachment」を持つ要素の順番を関連づけて一緒に送信し、データベース更新が成功した場合に返される文字列に、その順番と関連させて一緒に取得してorder の値を設定してやると言う具合です。
なんだか二度手間のような気もしますが・・・、まぁ、データベース更新が成功した場合だけ、画像の並び替えをさせたいわけなので、この方法を選択しました。
注:2021/5/17 追記
この部分、元ファイル名に ”-” が存在すると不具合が発生するので、62行目のデリミタとして使用している ”-” を ”\u0001” に変更しています。”\u0001” というのは、ASCII の小さい番号の方の文字で実際のデータの中に現れる可能性は無いという文字です。javascript なら ”\u0001”、php においては chr(1) で使用できます。
» my_admin_media.js
100~107行目の部分は、一気にorder を設定しているので、データベース更新が成功してアラートが表示された後、そのアラートを消すとすでに画像が並び替えられた状態になっています。
一方、111~124行目の部分は、アラートを消すと一枚づつ移動して並び替えが進行する状況が見て確認できます。ちゃんと並び替えが行われているのを確認したければこちらの方が楽しいかも。
そして次なるはjavascript からPOST送信データを受け取って肝心のmenu_order のデータベース上の値を更新するphp 側のコードです。
これもwordpress の Ajax の作法にのっとり、アクションフックにて対象の関数を登録します。
そのあたりは手前味噌ながらここのこのページをご覧あれ → «WordPress のFilesystemとかAjaxとか»
やらせること自体は簡単なことです。
受け取った画像情報の文字列をばらして個々にし、ファイル名で並び替えてそれぞれの順番の値でデータベースを更新するというだけのことですね。データベースの更新においてはwordpress で用意してくれている$wpdb-update を使っています。
注:2021/5/17追記
この部分、元ファイル名に ”-” が存在すると不具合が発生するので、7、34、37行目の三箇所、デリミタとして使用している ”-” を chr(1) に変更しています。
以上です。
と、これにてわざわざ手動でドラッグして並び替える必要はなくなったのです。
思ったよりも簡単だったのでもっと早くやればよかったんですね~!
まぁ、一つの投稿にたくさんの画像をアップロードするということもあまりないのかもしれませんが、私的な使い方をしている分には、とても重宝する機能をつける事ができたと、我ながら大満足なのでありました。
ただ、この機能にて並び替えを実行させた後は、ドラッグにての並び替えが機能しなくなります。その場合はこの自動並び替えを実行させることなくドラッグすれば大丈夫かと。あと、私的にはwordpress の管理画面において画像の編集機能などは一切つかいません。画像が入っている要素のスタイルにFlexbox を設定しているので、もしかしたら通常のレイアウトなどに支障をきたす場合があるかもしれません。ご留意のほど。
Post : 2018/02/05 19:28
Talking
2021年5月17日
元ファイル名に “-” が入っていると、不具合がありました。
php では Notice が出る具合です。
その件、修正しましたので、ご確認ください。
画像の自動並べ替え機能利用させて頂きました。singleで画像をたくさん利用してるのでとても助かります。ありがとうございました。
コメントありがとうございます。
お役に立てたならとてもうれしく思います。
Comments feed
Trackback URL : https://strix.main.jp/wp-trackback.php?p=107783