WordPressのメディアライブラリ(Ajaxタイプ)

前回のメディアライブラリ(リロードウインドウ編)に続いてAjax版のメディアライブラリの実装方法をまとめます。基本的にはリロード版と同じ構成で作っていこうと思います。

実装したい機能

実装したい機能は以下の3つ。リロード版と実装する内容は同じです。

  1. テキストボックスの近くにボタンを設置
  2. ボタンクリックでメディアアップローダーのウインドウをポップアップ
  3. 画像を選択してテキストボックスに画像のURLを取得。その画像を表示。

という機能を実装します。

使用するJavaScriptやCSSの読み込み

wp_enqueue_media()関数

リロード版では自分で必要なライブラリを読み込みましたが、Ajax版では、メディアアップローダーに必要なライブラリを一式まとめて準備してくれる関数wp_enqueue_media()があるので、その関数をページ読み込み時にコールします。

class Media_Uploader_Load {
	public function __construct () {
		add_action( 'admin_menu', array( $this, 'admin_menu' ) );
	}

	public function admin_menu () {
		$page = add_menu_page(
			'Uploader Ajax Sample',
			'Uploader Ajax Sample',
			'manage_options',
			plugin_basename( __FILE__ ),
			array( $this, 'page_render' )
		);

		add_action( 'admin_print_scripts-' . $page, array( $this, 'admin_scripts') );
	}

	public function admin_scripts () {
		wp_enqueue_media();
	}

	public function page_render () {


	}
}

プラグインの基本型。管理メニューに「Uploader Ajax Sample」という名前のメニューを追加して、そのメニューで表示された画面でwp_enqueue_media()関数をコールします。

オリジナルのJavaScriptを読み込み

メディアアップローダーに必要なJavaScript・CSSはwp_enqueue_media()関数でまとめて読み込むので、そのライブラリを操作する用のJavaScriptも準備しておきます。作成したadmin_script関数内に読み込みたいJavaScriptを以下のように追記します。(2行目)

public function admin_scripts () {
	wp_enqueue_script( 'media-uploader-main-js', plugins_url( 'js/media-uploader-main.js', __FILE__ ), array( 'jquery' ) );
	wp_enqueue_media();
}

プラグインのjsフォルダ内にmedia-uploader-main.jsというファイルを作成します。このJavaScriptファイルの中に実装したい内容を記述していきます。jQueryを使用するので、jQuery依存関係の設定も忘れずに。

HTMLの準備

テスト用のHTMLの準備をします。イメージは以下のような感じ。

HTML出力イメージ

この辺りはリロード版と同じで、要素は3つ。img要素・input[type=”text”]要素・button要素でそれぞれJavaScriptから操作するので、それぞれid属性を設定。これらの要素を出力する関数を作ります。管理メニューを追加した時に設定したコールバック関数page_renderに以下のようなコードを書きました。

public function page_render () {
	echo '<div class="wrap">';
	echo '<h1>Media Uploader ( Load Type )</h1>';
	echo '<p><img id="image-view" src="' . plugins_url( 'images/no-image.gif', __FILE__ ) . '" width="260"></p>';
	echo '<p><input id="image-url" type="text" class="large-text"></p>';
	echo '<button id="media-upload">Choose Image</button>';
	echo '</div>';
}

media-uploader-main.js

ウインドウオブジェクトの準備

リロード版と違い、Ajax版はまず、JavaScriptのwp.media()というモデルを使用します。WordPressには、Backbone.jsというJavaScriptのMVCフレームワークとBackbone.jsと依存関係にあるUnderscore.jsというライブラリが同梱されています。これらを使用して、/wp-includes/js/media-models.jsというファイル内にwp.media()が定義されています。まずはこれを使用して設定を行います。

(function($) {
	$(function() {
		var custom_uploader = wp.media({
			title: 'Choose Image',
			library: {
				type: 'image'
			},
			button: {
				text: 'Choose Image'
			},
			multiple: false
		});

		$("#media-upload").on("click", function(e) {
			e.preventDefault();
			custom_uploader.open();
		});
	});
})(jQuery);

wp.mediaの定義はとりあえずこれだけ。それぞれの設定値はウインドウ表示時に以下のように反映されます。

メディアライブラリAjax版
  • library: {type: ‘image’} → ライブラリに表示するメディアを画像に設定
  • multiple: false → 複数選択可能にする場合は「true」を設定

ボタンのクリックイベントでcustom_uploader.open();メソッドを動作させます。すると「メディアを追加」ボタンでおなじみのポップアップウインドウが表示されます。
管理メニューのメディアでできるようにその場で画像の新規追加などができます。「メディアライブラリ」の画像を表示して「Choose Image」ボタンをクリックして値を返します。

ウインドウから値を返す処理

「Choose Image」ボタンが押された時にその値を受取る処理が必要です。先程のJavaScriptに、wp.mediaモデルにselectトリガーを準備して、wp.mediaモデルに定義されているstate().get('selection')をコールすること戻り値として受取ることができます。

custom_uploader.on("select", function () {
	var images = custom_uploader.state().get('selection');

	images.each(function(file) {
		$("#image-url").val(file.toJSON().url);
		$("#image-view").attr("src", file.toJSON().url);
	});
});

images変数に選択した画像情報がオブジェクトで返ってくるので、その内容をJSON形式に変換して必要な値を取得します。eachでループしている箇所は、multipleをtrueに設定したときに、複数選択した画像の繰り返し処理を行うためのものです。

Ajax版はロード版に比べて沢山の情報が取得できるのも特徴です。コンソールに出力した内容が以下のような感じなのですが、ほぼほぼ必要な情報が揃っているので汎用性を考えてもAjax版のほうが良いなと思いました。

alt: ""
author: "1"
authorName: "admin"
caption: ""
compat: Object
date: Thu Feb 16 2017 15:42:10 GMT+0900 (JST)
dateFormatted: "2017年2月16日"
description: ""
editLink: "http://vccw.dev/wp-admin/post.php?post=2259&action=edit"
filename: "kinoko.jpg"
filesizeHumanReadable: "2 MB"
filesizeInBytes: 1840144
height: 2000
icon: "http://vccw.dev/wp-includes/images/media/default.png"
id: 2259
link: "http://vccw.dev/kinoko/"
menuOrder: 0
meta: false
mime: "image/jpeg"
modified: Thu Feb 16 2017 15:42:10 GMT+0900 (JST)
name: "kinoko"
nonces: Object
orientation: "landscape"
sizes: Object
status: "inherit"
subtype: "jpeg"
title: "kinoko"
type: "image"
uploadedTo: 0
url: "http://vccw.dev/wp-content/uploads/2017/02/kinoko.jpg"
width: 3008

できた!\(^o^)/

画像選択後のHTML表示

これで完成です。うん、やっぱり画面のロードがかからないのでストレスを感じない。そのうち管理画面そのものもSPAのようになってほしいなという願望。

サンプルソース(GitHub)

以下のURLにサンプルソースのリポジトリがあります。
プラグイン形式で作成しているので、WordPressの環境の wp-content/plugins にディレクトリを作ってクローンすれば動きます。(プラグインを有効にしてください)

GitHub