Wonderful! WordPress

いまさらの Ajax でのコメントの編集機能プラグイン

Page No.3

プラグインの JavaScript

そして、JavaScript
ページ読み込み時のリクエストをへらすために、スタイルシートの読み込みを排除したので、コメント編集用のポップアップウィンドウなどのスタイル設定は、JavaScript の方から実行する。
まずは、各初期化やらそのスタイル設定の部分など。
最近は、JavaScript を書き始める時に、document.getElementById とか、要素にスタイルを設定するとか、Ajax とか決まりきった使い方でよく使うものは、打ち込みが楽なように、自前の関数たちを並べることにしてる。

( function () {
	// console.log( 'loaded new version splstc_comedit.js' );

	// id で要素を取得する関数。doc.getElementById を何度も打ち込むのが面倒なのだ。
	const Gi = ( name ) => {
		let ans = null;
	
		ans = document.getElementById( name );
		return ans;
	}

	// style.cssText を += では使いたくないのでその代わりの関数
	// target は要素の id、prop は複数あるスタイル設定を連想配列で指定
	const SSi = ( target, prop )  => {
		const tar = document.getElementById( target );
	
		for ( const key in prop ) {
			if ( prop.hasOwnProperty( key ) ) {
				tar.style[ key ] = prop[ key ];
			}
		}
	}

	// 自ファイルをロードさせた<script> タグの src 属性値から自url を取得
	const selfFile = Gi( 'splstc_comedit_js-js' ),
		ownurl = selfFile.src.substr( 0, selfFile.src.indexOf( 'wp-content' ) ),
		en_style = null !== Gi( 'comeditfrm') ? Gi( 'comeditfrm' ).getAttribute( 'data-style' ) : 'disstyle';

	let editkey = '';

	// en_style は編集用ポップアップウィンドウのスタイル設定を吐き出すか否かのオプション値を反映している値
	if ( 'enstyle' === en_style ) {
		let dynamicStyles = null;

		function addStylesheet( cssstr ) {
			const doc = document;

			if ( ! dynamicStyles ) {
				dynamicStyles = doc.createElement( 'style' );
				doc.head.appendChild( dynamicStyles );
			}
			
			dynamicStyles.sheet.insertRule( cssstr, dynamicStyles.length );
		}

		const styles = [
			'#dircomfrm{padding:10px;border:4px double #A09E9E;border-radius: 10px;}',
			'#dircomfrm label{font-size:0.8em;}',
			'#dircomfrm input[type=submit]{display:inline;}',
			'#comid{width:80px;}',
			'#direditkey{width:160px;}',
			'#comeditsec{display:none;position:fixed;width:100%;height:100%;top:0px;left:0px;z-index:30;text-align:center;background:linear-gradient(to right,#2F0301,#7F2A28,#DF7C6C,#7F2A28,#2F0301);}',
			'#comeditfrm{position:relative;margin:3% auto;padding:20px;background-color:#f5f5f5;border:4px double #ebebeb;border-radius: 10px;box-shadow:0px 5px 5px 5px rgba(0,0,0,0.4);}',
			'@media screen and (min-width:770px){#comeditfrm{width:600px;}#dircomfrm input[type=text]{display:inline;}}',
			'@media screen and (max-width:770px){#comeditfrm{width:80%;}#dircomfrm input[type=text]{display:block;}}',
			'#comeditfrm textarea{width:80%;}',
			'#erasecomfrm{position:absolute;top:5px;right:10px;font-size:1.2em;}',
			'#erasecomfrm:hover{cursor:pointer;}',
			'.comeditorderbt{display:block;width:50px;margin:10px 0;padding:2px;color:#B8A329;text-align:center;background:linear-gradient(#ffffff 0%,#CCCACA 100%);border:solid 1px #aaa;border-radius:5px;text-shadow: 0 1px #fff;box-shadow:0px 1px 2px 2px rgba(50,50,50,0.2);}',
			'.comeditorderbt:hover{cursor:pointer;background-color:#01DFB3;background:linear-gradient(#ffffff 0%,#01DFB3 100%);}'
		];

		for( let i = 0, ss_len = styles.length; i < ss_len; ++ i ) {
			addStylesheet( styles[ i ] );
		}
	}

	// php 側からの返り値で処理が必要な場合の Ajax 関数
	function ajax_callback( url, str, callback, ope ) {

		if ( url ) {
			const operation = 'undefined' === typeof ope ? 'POST' : ope,
				tmpstr = 'undefined' === typeof str ? null : str,
				strsend = Array.isArray( tmpstr ) ? tmpstr.join( '&' ) : tmpstr,
				tarurl = 'wp' === url ? ownurl + 'wp-admin/admin-ajax.php' : url;

			let req=new XMLHttpRequest();
	
			req.onreadystatechange = function() {
				let result = '';
		
				if (req.readyState == 4) { // 通信の完了時
					if (req.status == 200) { // 通信の成功時
						result = req.responseText;
	
						callback( result );
					
					} else {
						console.log( 'error : disabled send' );
					}
				}
			}
	
			req.open( operation, tarurl, true );
			if ( 'POST' === operation ) {
				req.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
			}
			req.send( strsend );
	
		} else {
			console.log( 'error : no data url' );
		}
	}
	// ↓ 続く

JavaScript
CopyExpand

そして、後半。

	// ↓ 続き
	// 編集ポップアップウィンドウを非表示にする関数
	function hiddencomeditsec() {
		editkey = '';
		Gi( 'lcomid' ).innerText = '';
		Gi( 'lcomauth' ).innerText = '';
		Gi( 'lasthon' ).value = '';
		Gi( 'comeditsec' ).style.display = 'none';
	}

	// コメント本文の改行を<br>に、url があれば anchor タグに入れるための関数
	function nl2br( str ) {

		str = str.replaceAll( "\r\n", '<br>' ).replaceAll( "\r", '<br>' ).replaceAll( "\n", '<br>' );
		if ( -1 !== str.indexOf( 'http' ) ) {
			str = str.replace( /(http(s)?:\/\/[a-zA-Z0-9-.!'()*;/?:@&=+$,%#]+)/gi, "<a href='$1' target='_blank' rel='noopener nofollow'>$1</a>");
		}
		return str;
	}

	// 処理結果を吹き出しでお知らせする関数
	function baloon( ope = 'edit' ) {
		if ( null === Gi( 'baloon' ) ) {
			const baloon = document.createElement( 'div' ),
				styles = [
					[ 'position', 'fixed' ],
					[ 'width', '200px' ],
					[ 'height', '150px' ],
					[ 'top', '45%' ],
					[ 'right', '30%'],
					[ 'visibility', 'hidden' ],
					[ 'opacity', 0 ],
					[ 'z-index', 99 ]
				],
				child = '<p id="fukidasi" style="position:absolute;width:0px;height:0px;bottom:0px;right:0px;border:solid 2px red;background:white;border-radius:50%;font-size:0em;line-height:0px;transition:all 0.5s;"></p>';

			baloon.setAttribute( 'id', 'baloon' );

			for ( let i = 0, styles_len = styles.length; i < styles_len; ++i ) {
				baloon.style[ styles[ i ][0] ] = styles[ i ][1];
			}
			baloon.innerHTML = child;
			document.body.appendChild( baloon );
		}

		if ( -1 !== ope.indexOf( 'error' ) ) {
			Gi( 'fukidasi' ).innerText = ope.replace( 'error', 'Error' );
		} else {
			Gi( 'fukidasi' ).innerText = 'Success ' + ope + ' comment!';
		}
		SSi( 'baloon', { visibility: 'visible', opacity: 1 } );
		setTimeout( () => {
			SSi( 'fukidasi', { width: '100%', height: '100%', 'font-size': '1.0em', 'line-height': '150px' } );

			setTimeout( () => {
				Gi( 'fukidasi' ).innerText = '';
				SSi( 'fukidasi', { width: '0%', height: '0%', 'font-size': '0em', 'line-height': '0px' } );
				setTimeout( () => {
					SSi( 'baloon', { opacity: 0, visibility: 'hidden' } );
				}, 500 );
			}, 3000 );	
		}, 200 );

	}

	// 編集ポップアップウィンドウで、編集・削除のポタンを押された後のデータを更新するための Ajax の JavaScript 側。
	// コメントの情報を集めて Ajax で送信。返り値の如何でコメント欄の更新をする。
	function updatecomment( ope ) {

		const comid = Gi( 'lcomid' ).innerText,
			comauth = Gi( 'lcomauth' ).innerText,
			comcont = encodeURIComponent( Gi( 'lasthon' ).value ),
			lascont = encodeURIComponent( Gi( 'lascont' ).value ),
			nonce = Gi( 'com_nonce' ).value,
			strsend = 'action=updatecom&ope=' + ope + '&comid=' + comid + '&editkey=' + editkey + '&auth=' + comauth + '&nonce=' + nonce + '&cont=' + comcont + '&lcont=' + lascont;

		ajax_callback( 'wp', strsend, function( result ) {
			if ( 'error:' === result.substr( 0, 6 ) ) {
				hiddencomeditsec();
				console.log( result );
				baloon( result );
			} else {
				if ( 'edit' === ope ) {
					const cmeditbt = Gi( 'cmeditbt-' + comid ),
						parent = cmeditbt.parentNode,
						childs = parent.children;

					for ( let i = 0, childs_len = childs.length; i < childs_len; ++i ) {
						if ( 'p' === childs[ i ].tagName.toLowerCase() ) {
							if ( '' === childs[ i ].id ) {
								childs[ i ].innerHTML = '';
							}
						}
					}

					Gi( 'comcont-' + comid ).innerHTML = nl2br( decodeURIComponent( comcont ).replaceAll( '<', '' ) );
					hiddencomeditsec();
					baloon( 'edit' );
				} else if ( 'delete' === ope ) {
					Gi( 'div-comment-' + comid ).style.display = 'none';
					hiddencomeditsec();
					baloon( 'delete' );
				}
			}
		});
	}

	// onload イベント
	window.addEventListener( 'load', () => {

		if ( null !== Gi( 'comeditsec' ) ) {
		
			const ces = Gi( 'comeditsec' ),
				colorclass = ces.getAttribute( 'class' );
	
			let grad = '#033001,#077C00,#ACF8A8,#077C00,#033001';// gcolor === colorclass
			
			if ( 'ncolor' === colorclass ) {
				grad = '#010314,#022ADF,#637BF5,#022ADF,#010314';
			} else if ( 'wcolor' === colorclass ) {
				grad = '#100009,#420027,#880355,#420027,#100009';
			} else if ( 'bcolor' === colorclass ) {
				grad = '#000000,#4E5050,#dbdbdb,#4E5050,#000000';
			}
			ces.style.background = 'linear-gradient(to right,' + grad + ')';
	
			Gi( 'erasecomfrm' ).onclick = () => {
				hiddencomeditsec();
			}	
		}
	
		// onload イベントにエディットボタンを押されたときの処理を登録
		// Ajax で editkey の認証をして、よければ php 側でコメントの本文を取得して返り値として取得、ポップアップウィンドウを表示する
		const classlist = document.getElementsByClassName( 'comeditorderbt' );
	
		for ( let i = 0, clnum = classlist.length; i < clnum; ++i ) {
			classlist[ i ].onclick = () => {
				let comid = classlist[ i ].getAttribute( 'id' );
	
				comid = comid.replace( 'cmeditbt-', '' );
	
				const retstr = prompt( 'Enter editkey' );
	
				if ( retstr ) {
					const strsend = 'action=verifyeditkey&id=' + comid + '&editkey=' + retstr;
	
					ajax_callback( 'wp', strsend, function( result ) {
						if ( 'error:' === result.substr( 0, 6 ) ) {
							alert( 'Please input correct editkey!' )
						} else {
							const editbt = Gi( 'cmeditbt-' + comid ),
								comauth = editbt.getAttribute( 'data-auth' ),
								comcont = result;
	
							editkey = retstr;
							Gi( 'lcomid' ).innerText = comid;
							Gi( 'lcomauth' ).innerText = comauth;
							Gi( 'lasthon' ).value = comcont;
							Gi( 'lascont' ).value = comcont;
							Gi( 'comeditsec' ).style.display = 'block';
						}
					});
				}
			}
		}

		if ( null !== Gi( 'editlast' ) ) {
			Gi( 'editlast' ).onclick = () => {
				updatecomment( 'edit' );
			}
		}

		if ( null !== Gi( 'dellast' ) ) {
			Gi( 'dellast' ).onclick = () => {
				updatecomment( 'delete' );
			}
		}
	});
}());
JavaScript
CopyExpand

そして残るは、uninstall.php。
プラグインを削除した時に、オプション値とかメタデータを一緒に削除するためのもの。

<?php
	// if uninstall.php is not called by WordPress, die
	if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	    die;
	}

	$option_name = 'smplstc_commedt_option';

	delete_metadata( 'comment', null, 'my_comment_editkey', '', true );
	delete_option( $option_name );

	// for site options in Multisite
	delete_site_option( $option_name );
?>
PHP
CopyExpand

と、いうことでこれにて終了。
プラグイン内包のファイルもほぼこれらと同じ内容。ちょっと関数の書いてある順番が違ったりするだけ。
とりえず、ローカルとここのサイトにてテストしてますが、問題なく動いてます。
ローカル php v8.2.3 WordPress 6.2-beta3、
ロリポップ php v8.1.6 WordPress 6.1.1 で動作確認。

問題無く動くと思うんですけど。動かなかったらご勘弁ください。
何も起こりえないのですが、一応、決まり事を。
このプラグインを使用する場合は完全自己責任で行ってください。
何らかの損害が発生しても一切関知しません。
下のリンクからダウンロードできると思います。
ご興味があればどうぞ。

ダウンロードリンク
-> « Simplistic Comment User Editable plugin »

Sanbanse Funabashi
2010.10.24 sunrise

Top

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