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です。

<?php
	function my_add_attachment_sortimg_field( $form_fields ) {
		$form_fields['sortimage'] = array(
			'input'=> 'html',
			'html' => '<a href="javascript:void(0)" class="button media-button" id="sortimgs">sort images</a>',
		);
		return $form_fields;
	}

	add_filter( 'attachment_fields_to_edit', 'my_add_attachment_sortimg_field' );
?>
PHP
CopyExpand

追加する要素のタグは <a> でも <p> でも何でもいいと思います。
これにより、「メディアを追加」ボタンでメディアパネルを開き、画像を選択したときに表示される右側のパネルの「添付ファイルの表示設定」の上あたりに「sort images」のボタンが表示されることになります。ちなみにフィルターフックにおいて、引数を二つ以上受け取る場合は、引数の数を指定する必要があります。それをしないと動かないどころかそのフックを呼び出したところでエラーとなって止まってしまう。以前は動いていたのでいつからそうなったのかわからないですが・・・。

そして管理画面において独自のjavascript ファイルを読み込ませる部分。とまぁ、正確には管理画面においてはjQuery が使えるのでjQuery のファイルですが。自分の使っているテーマのフォルダに「my_admin_media.js」という名前で保存してあります。
下はネットでどなたかがお書きいただいていたものをほとんどそっくり使わせてもらったものだと思います。

<?php
	function my_admin_script() {
		wp_enqueue_script( 'my_admin_script', get_template_directory_uri().'/my_admin_media.js', array('jquery'));
	}

	add_action( 'admin_enqueue_scripts', 'my_admin_script' );
?>
PHP
CopyExpand

そしていよいよそのjavascript というかjQuery ですが。
javascript においてやることはといえば、メディアパネルに表示されている画像の情報、wp-posts テーブルにおけるその画像を登録してある行のIDの値と、そしてファイル名順にソートする必要があるので画像のファイル名、を取得しそれらをまとめてAjax というかPOSTphp の関数へと渡すことです。
で、その動的に生成されたメディアパネルの、画像が表示されている部分のhtml はどうなっているかというと、

<li tabindex="0" role="checkbox" aria-label="1609090465" aria-checked="false" data-id="346" class="attachment save-ready">
	<div class="attachment-preview js--select-attachment type-image subtype-jpeg landscape">
		<div class="thumbnail">
			<div class="centered">
				<img src="https://localhost/wp/wp-content/uploads/2016/10/1609090465-330x220.jpg" draggable="false" alt="">
			</div>
		</div>
	</div>
	<button type="button" class="check" tabindex="-1">
		<span class="media-modal-icon"></span>
		<span class="screen-reader-text">選択を解除</span>
	</button>
</li>
HTML
CopyExpand

<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 にて設定しています。

<?php
	function my_admin_images_flex_style() {
		echo '<style>' . "\n";
		echo '.attachments{display:flex;flex-wrap:wrap;}' . "\n";
		echo '.attachment{order:0;}' . "\n";
		echo '</style>' . "\n";
	}
	add_action( 'admin_print_styles', 'my_admin_images_flex_style' );
?>
PHP
CopyExpand

そして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

jQuery( function() {

	/*「タイプで絞込み」メニューをクリックした時に、
	「この投稿へのアップロード」の値である「uploaded」の場合、
	「投稿に挿入」ボタンの後に<a>タグを挿入。
	※動的に生成される要素の場合、この書き方をしないとイベントが登録できない。
	「タイプで絞込み」<select> → id="media-attachment-filters"
	「投稿に挿入」<button> → class="media-button-insert"*/
	jQuery( document ).on( 'click', '#media-attachment-filters', function(){
		var mediaselect = jQuery( '#media-attachment-filters' ).val();

		if ( 'uploaded' === mediaselect ) {
			if ( ! jQuery( '#sortimgs' ).length ) {
				jQuery( '.media-button-insert' ).after( '<a href="javascript:void(0)" class="button media-button" id="sortimgs">sort images</p>' );
			} else {
				jQuery( '#sortimgs' ).css( 'visibility', 'visible' );
			}

		} else {
			if ( jQuery( '#sortimgs' ).length ) {
				jQuery( '#sortimgs' ).css( 'visibility', 'hidden' );
			}
		}
	} );

	jQuery( document ).on( 'click', '#sortimgs', function(){
		sort_img();
	});

	function sort_img() {
		//画像の情報をまとめて取得 class="attachment"
		var imgs = jQuery( '.attachment' ),
			mediaselect = jQuery( '#media-attachment-filters' ).val(),//「タイプで絞込み」メニューの値
			postid = jQuery( '#post_ID' ).val(),// 親投稿ID
			sendflg = true;// POST送信の可否フラグ

		if ( 'uploaded' === mediaselect && imgs.length ) {
			var tmpid,
				tmpurl = '',
				imgstrs = '';

			//画像情報の配列でループ
			for ( var i = 0, len = imgs.length; i < len; i++ ) {

				//その画像情報のある<li>タグが"selection"というクラスを持っていない場合に限る
				//"selection"クラスを持っている場合は、画像が選択状態にあり複製されたデータということ
				if ( false === jQuery( imgs[ i ] ).hasClass( 'selection' ) ) {

					// 画像の情報が保存してあるデータベース上の行のID
					tmpid = jQuery( imgs[ i ] ).attr( 'data-id' );

					// 画像のurlを取得してファイル名の拡張子を除いた文字列に加工
					// サムネイルが指定してある場合は’x’の文字が入っている
					tmpurl = jQuery( 'img', imgs[ i ] ).attr( 'src' );
					if ( -1 !== tmpurl.indexOf( 'x' ) ) {
						tmpurl = tmpurl.slice( tmpurl.lastIndexOf( '/' ) + 1, tmpurl.lastIndexOf( '-' ) );
					} else {
						tmpurl = tmpurl.slice( tmpurl.lastIndexOf( '/' ) + 1, tmpurl.lastIndexOf( '.' ) );
					}
					// すべての画像のIDとファイル名、そしてその要素の順番をひとつの文字列にする
					// 注:2021/5/17に、この下のデリミタとして使用している ”-” を ”\u0001” に変更しています。
					imgstrs += '\u0001' + tmpid + ':'  + tmpurl + ':' + i;
				}

				// 安全対策:画像の数制限 40まで
				if ( i > 40 ) {
					sendflg = false;
					break;
				}
			}

			/* 送信可の場合、wordpressの作法でPOST送信
			 ajaxurl はwordpress によってあらかじめ設定されている送信先のurlで
			 admin-ajax.phpへのパス。管理画面内では何もせずとも使用可の変数。*/
			if ( sendflg ) {
				jQuery.post( ajaxurl,
					{ 'action' : 'sort_imgs', 'target' : imgstrs, 'postid' : postid },
					function( data, status ) {
						var retstr,
							orderval,
							classval = new Array(),
							classvallen,
							showstr,
							moveID,
							mcounter = 0;

						/* 返される文字列のなかに'^'が含まれていれば
						データベース更新が成功し、画像を並び替えるためのデータが
						含まれているということ*/
						if ( -1 !== data.indexOf( '^' ) ) {
							retstr = data.split( '^' );

							// データベース更新の結果を表示する文字列
							showstr = retstr[0];

							/* 並び替えるデータの処理
							まずはそれぞれの画像ごとに配列にいれる*/
							if ( retstr[1] ) {
								if ( -1 !== retstr[1].indexOf( ':' ) ) {
									classval = retstr[1].split( ':' );
								} else {
									classval[0] = retstr[1];
								}

								if ( classval.length > 0 && classval[0].length > 0 ) {
									classvallen = classval.length;

									/*この下のコメントアウトされている部分は、一気にorderを設定する方法。
									結果のアラートが表示された後に画像が全て並び変えられて表示される*/
									/*for ( var i = 0; i < classvallen; i++ ) {
										if ( -1 !== classval[ i ].indexOf( '-' ) ) {
											orderval = classval[ i ].split( '-' );
											jQuery( imgs[ orderval[0] ] ).css( 'order', orderval[1] );
										}
									}*/

									/*この下はアラートが表示された後、画像が一枚づつ並び変えられて視覚的に
									並び替えを確認することができる*/
									moveID = setInterval( function() {
										if ( null != classval[ mcounter ] ) {
											if ( -1 !== classval[ mcounter ].indexOf( '-' ) ) {
												orderval = classval[ mcounter ].split( '-' );
												jQuery( imgs[ orderval[0] ] ).css( 'order', orderval[1] );
											}
										} else {
											console.log( 'error classval: ' + mcounter );
										}
										mcounter++;
										if ( mcounter >= classvallen ) {
											clearInterval( moveID );
										}
									}, 50 );
								}
							}
						} else {
							showstr = data;
						}

						alert( showstr  );
					}
				);
			} else {
				alert( 'データ数が40を超えたため処理を中止しました!' );
			}
		}
	}
} );
JavaScript
CopyExpand

100~107行目の部分は、一気にorder を設定しているので、データベース更新が成功してアラートが表示された後、そのアラートを消すとすでに画像が並び替えられた状態になっています。
一方、111~124行目の部分は、アラートを消すと一枚づつ移動して並び替えが進行する状況が見て確認できます。ちゃんと並び替えが行われているのを確認したければこちらの方が楽しいかも。
media pannel

そして次なるはjavascript からPOST送信データを受け取って肝心のmenu_order のデータベース上の値を更新するphp 側のコードです。
これもwordpress Ajax の作法にのっとり、アクションフックにて対象の関数を登録します。
そのあたりは手前味噌ながらここのこのページをご覧あれ → «WordPress のFilesystemとかAjaxとか»
やらせること自体は簡単なことです。
受け取った画像情報の文字列をばらして個々にし、ファイル名で並び替えてそれぞれの順番の値でデータベースを更新するというだけのことですね。データベースの更新においてはwordpress で用意してくれている$wpdb-update を使っています。

注:2021/5/17追記
この部分、元ファイル名に ”-” が存在すると不具合が発生するので、7、34、37行目の三箇所、デリミタとして使用している ”-” を chr(1) に変更しています。

<?php
function sort_imgs() {
	global $wpdb;

	// 画像情報がまとめてある文字列
	// この下の部分において、デリミタとして使用していた ”-” を chr(1) に変更しています。 
	$target = isset ( $_POST['target'] ) ? trim( $_POST['target'], chr(1) ) : '';

	// データベースにある親投稿データのID
	$postid = isset ( $_POST['postid'] ) ? $_POST['postid'] : '';

	// 個々の画像情報を入れるための配列
	$imgsary = array();

	// 画像のデータベースのIDを入れる配列
	$imgid = array();

	// 画像が入っている要素の順番の値を入れる配列
	$classid = array();

	// 画像のファイル名を入れる配列
	$imgurl = array();
	$resultstr = array();
	$ansstr = '';
	$ansnum = 0;
	$orderval = 1;
	$orderstr = '';

	if ( $postid ) {
		if ( $target ) {

			// 画像が複数ある場合
			// この下の部分二箇所において、デリミタとして使用していた ”-” を chr(1) に変更しています。 
			if ( false !== strpos( $target, chr(1) ) ) {

				// 画像情報を個々にばらす
				$imgsary = explode( chr(1), $target );
			} else {
				$imgsary[] = $target;
			}

			// 画像情報をIDとファイル名、順番値に分ける
			foreach ( $imgsary as $val ) {
				if ( false !== strpos( $val, ':' ) ) {
					list( $imgid[], $imgurl[], $classid[] ) = explode( ':', $val );
				}
			}
			if ( $imgurl ) {
				arsort( $imgurl );// 逆順にソート

				/* データベースのmenu_orderの値の更新
				成功した場合$result にはそれによって影響のあったデータの個数が返る
				失敗した場合はfalse*/
				foreach ( $imgurl as $key=>$val ) {
					$result = $wpdb->update( 
						$wpdb->posts, 
						array(
							'menu_order' => $orderval,
						), 
						array(
							'ID' => $imgid[ $key ],
							'post_type' => 'attachment',
							'post_parent'=> $postid,
						), 
						array( 
							'%d',
						), 
						array(
							'%d',
							'%s',
							'%d',
						 ) 
					);

					// ひとつでも更新に失敗したデータがあった場合は処理を中止する
					if ( false === $result ) {
						$resultstr[] = $imgid[ $key ];
						break;
					} else {
						// 送り返す要素の順番値と並び替えした順番値の文字列を作る
						$orderstr .= ':' . $classid[ $key ] . '-' . $orderval;
						// menu_order 値の加算と成功したデータの加算
						$orderval++;
						$ansnum += $result;
					}
				}

				// echo した文字列がPOST送信元のjavascriptへと返されて表示することができる
				if ( $resultstr ) {
					foreach ( $resultstr as $val ) {
						$ansstr .= ':' . $val;
					}
					$ansstr = 'database update error' . $ansstr;
					echo $ansstr;
				} else {
					// 並び替えが成功した場合
					if ( $orderstr ) {
						$orderstr = '^' . trim( $orderstr, ':' );
					} 
					echo 'Success sort image data update for database! : ' . $ansnum . '件' . $orderstr;
				}
			} else {
				echo 'Empty images data array!';
			}
		} else {
			echo 'None images data!';
		}
	} else {
		echo 'None post-ID!';
	}

	die();
}

add_action( 'wp_ajax_sort_imgs', 'sort_imgs' );
?>
PHP
CopyExpand

以上です。
と、これにてわざわざ手動でドラッグして並び替える必要はなくなったのです。
思ったよりも簡単だったのでもっと早くやればよかったんですね~!
まぁ、一つの投稿にたくさんの画像をアップロードするということもあまりないのかもしれませんが、私的な使い方をしている分には、とても重宝する機能をつける事ができたと、我ながら大満足なのでありました。
ただ、この機能にて並び替えを実行させた後は、ドラッグにての並び替えが機能しなくなります。その場合はこの自動並び替えを実行させることなくドラッグすれば大丈夫かと。あと、私的にはwordpress の管理画面において画像の編集機能などは一切つかいません。画像が入っている要素のスタイルにFlexbox を設定しているので、もしかしたら通常のレイアウトなどに支障をきたす場合があるかもしれません。ご留意のほど。

Talking

  • admin より:

    2021年5月17日
    元ファイル名に “-” が入っていると、不具合がありました。
    php では Notice が出る具合です。
    その件、修正しましたので、ご確認ください。

    edit
  • iwama より:

    画像の自動並べ替え機能利用させて頂きました。singleで画像をたくさん利用してるのでとても助かります。ありがとうございました。

    edit
    • admin より:

      コメントありがとうございます。
      お役に立てたならとてもうれしく思います。

      edit

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=107783

Sanbanse Funabashi
2011.01.01 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。

×

Comment ID :
Comment Author :



save edited comment with an edit button.

Delete this comment. Because you cannot go back up, please be careful.

Simplistic Comment User Editable v4.0