In-Place-Editor (その場で編集する UI) の jQuery プラグインを書いてみた

更新履歴

2011-07-05
Ver 0.1.5.1
リスト編集モードで値未入力時のラベル表示不具合等を修正しました
2011-06-20
Ver 0.1.5
表示テキストの整形処理を記述できる replaceLabel パラメータを追加しました。
2011-04-29
Ver 0.1.4.1
編集値の変換処理の不具合を修正しました
2011-04-21
Ver 0.1.4
リスト編集モード等の機能追加をしました
jQuery exInPlace Editor にリスト編集モード等の機能追加をしました - Cyokodog::Diary
2010-07-17
Ver 0.1.3
editorType パラメータを textarea にし元テキストに br もしくは p が含まれた場合、textarea 内で改行に置換されない不具合を修正しました
2010-07-16
Ver 0.1.2
block 要素限定で表示/編集モード切替時にエフェクトをかけられるようにしました
oninit , effect , dataSelect パラメータを追加しました(詳細はリファレンス参照)
2010-07-01
Ver 0.1.1
ESC のショートカットキーを、Safari , Chrome でも効くように修正しました。
2010-06-28
Ajax 関連の Demo ページに不具合があったので修正しました。
ESC のショートカットキーが、Safari , Chrome で効かないようなので原因を調査中です

今さら感はありますが、業務で使用することも多いので再利用しやすいようプラグイン化してみました。以前書いた記事「In-Place-Editor (その場で編集するUI) の実装方法を考えてみた」では網羅できなかった下記機能についても対応させてみました。

  • 初期化処理時のコールバック処理(内部生成された要素の初期化処理などが可能)
  • 編集、確定、取消に対する処理の割り込みとイベントのキャンセル
  • 確定/取消ボタンの表示/非表示オプション
  • テキスト/HTML編集モードの切替オプション
  • DB更新 / Validation 処理後の(表示位置が最適化された)メッセージ表示機能
In-Place-Editor (その場で編集するUI) の実装方法を考えてみた - Cyokodog::Diary

機能概要

下記のような input や textarea の入力要素にプラグインを適用すると

各要素が a 要素(もしくは普通のテキスト)に置換されます。

置換された要素をクリックすると、編集モードになります。

確定(save)、取消(cancel)ボタンのショートカットキーとして、エンターキー、 ESC キーを使用することができます。(ESC キーが Safari , Chrome で効かないようなので原因を調査中です)ESC や Tab 、Shift といった制御系のキーは Webkit 系ブラウザでの場合、keypress イベントで拾えないようです。keydown イベントで拾うように修正しました。

Demo

使い方

jQueryjQuery.exInPlaceEditor.js 、exInPlaceEditor.css を読み込みます。

<link rel="stylesheet" type="text/css" href="exinplaceeditor.css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.exinplaceeditor.js"></script>

適用した要素に対し exInPlaceEditor() メソッドを実行します。(対象要素が input や textarea でなくても動作します。詳しくは後述)

$('input,textarea').exInPlaceEditor();

Demo

編集ボタンの表示

directEdit パラメータを false にすると、置換後の要素がテキスト(span)になり、編集ボタンが表示されます。

$('input,textarea').exInPlaceEditor({
	directEdit : false
});

Demo

編集ボタンを右端に表示する

displayStyle と editLabelAlign パラメータを下記ように指定すると編集ボタンを右端に表示させることができます

$('input,textarea').exInPlaceEditor({
	directEdit : false,
	displayStyle : 'block',
	editLabelAlign : 'right'
});

Demo

textarea 内での改行を p 要素に置換する

textarea 内で改行を入力し表示モードに戻った場合、改行は br 要素に置換されます。

hoge<br/>

convertCR パラメータに "p" を指定することで p 要素に置換させることができます。

<p>hoge</p>
$('input,textarea').exInPlaceEditor({
	convertCR : 'p'
});

Demo

HTML 編集モードで編集する

デフォルトの状態では、編集モードにて入力した > や < といった文字列は、表示モードでは &anp; gt; や &anp; lt; にエスケープされますが、htmlEditor パラメータを true にすることでエスケープを抑止することができます。

$('input,textarea').exInPlaceEditor({
	htmlEditor : true
});

Demo

API を使用し値チェックする

編集モードにて入力した値を、確定のタイミングでチェックしたい場合があるかと思います。そのような場合は確定処理のコールバック関数内で API を使用した値チェック処理を記述します。

$('input,textarea').exInPlaceEditor({
	onsave : function( api ){  //・・・(1)
		if (!api.getValue().length) {  //・・・(2)
			api.saveError('値を入力してください');  //・・・(3)
			return false;  //・・・(4)
		}
	}
});
  • (1) 値確定時にコールバックされる関数を onsave パラメータに定義します。関数の第1パラメータには API オブジェクトが引き渡されます。
  • (2) API オブジェクトの getValue() メソッドで編集データを取得することができるのでこの値をチェックします。
  • (3) API オブジェクトの saveError() メソッドで、入力フィールドのそばにエラーメッセージを表示させることができます。
  • (4) エラーの場合は、コールバック関数の返却値を false にし、確定処理をキャンセルさせます。

Demo

Ajax を使用して値チェック・更新処理をする

Ajax を使った値チェック・更新処理を行う場合は以下のように記述します。

$('input,textarea').exInPlaceEditor({
	onsave : function( api ){
		var data = api.getEditor().attr('name') + '=' + api.getValue();  //・・・(1)
		api.saving();  //・・・(2)
		$.ajax({  //・・・(3)
			dataType : 'json',
			type : 'post',
			data : data,
			success : function( json ){
				if( json.errmsg ){
					api.saveError(json.errmsg);  //・・・(5)
					return;
				}
				api.saveComplete();  //・・・(6)
			}
		});
		return false;  //・・・(4)
	}
});
  • (1) サーバに送信するパラメータを組み立ててます。getEditor() メソッドで input(もしくは textarea) 要素が取得できます。
  • (2) 保存処理中のメッセージが表示され、入力フィールドがロック(disabled)され編集できなくなります。
  • (3) Ajax 通信をします。
  • (4) Ajax の処理結果が帰るまで編集モードを抜けないようにするため、確定処理を一時的にキャンセルします。
  • (5) Ajax の処理結果がエラーだった場合は、エラーメッセージを表示し、そのまま編集モードのままにします。
  • (6) Ajax の処理結果が正常終了の場合は、saveComplete() メソッドを実行で確定処理を行い、編集モードを抜けます。

Demo

input , textarea 要素以外に In-Place-Editor を適用する

input , textarea 要素以外にも適用することが可能です。

$('span , a').exInPlaceEditor();

但しこの場合、自動的に編集用の input 要素が生成されるため、Ajax を使用せず登録処理をする場合などは name 属性を設定する必要があります。また、生成され要素を textarea にしたい場合もあるかと思います。このような場合は以下のように記述します。

$('span.edit,a.edit').each(function(){  //…(1)
	var target = $(this);
	var api = target.exInPlaceEditor({
		api : true,  //…(2)
		displayStyle : 'block',
		editorType : target.hasClass('desc') ? 'textarea' : 'input',  //…(3)
		onsave : function( api ){
			alert(api.getEditor().attr('name'));  //…(7)
		}
	});
	$(['table-name','table-name-jp','desc']).each(function(){  //…(4)
		var className = this;
		if( target.hasClass( className ) ){  //…(5)
			api.getEditor().attr( 'name' , className );  //…(6)
		}
	});
});
  • (1) each() メソッドで適用対象要素を個別に取得します。((3)で要素によりパラメータを変更するため)
  • (2) api パラメータを true にすると返却値に api オブジェクトが返されます。((6)で使用します)
  • (3) editorType パラメータを使用すると自動生成される編集用の要素を textarea に変更することができます。例では、desc というクラスを持つ要素の場合は textarea にするようにしてます。
  • (4) 自動生成される編集用の要素に対し、name 属性を設定します。ここでは プラグインを適用する要素の保持するクラス名を name 属性に設定するため、クラス名でループさせます。
  • (5)(6) カレントのクラス名をプラグイン適用要素が保持してた場合は、そのクラス名を name 属性にします。
  • (7) サンプルでは name 属性の設定が正しく行われたか確認するため、編集を確定した際に自身の name 属性を表示させてます。

Demo

mouseover もしくは focus したタイミングで初期化を行う

table 表などのように大量の要素に対し、プラグインを適用すると初期化に時間がかかってしまう場合があります。そのような場合は、編集が行われる直前のイベント(mouseover , focus)で、プラグインを適用することで初期化の負荷を分散させることができます。

$('table.sample').delegate('span.edit,a.edit','mouseover focus',function(){  //...(1)
	var target = $(this);
	target.exInPlaceEditor({  //...(2)
		nowHover : true,  //...(3)
		displayStyle : 'block',
		editorType : target.hasClass('desc') ? 'textarea' : 'input'
	});
});
  • (1) 編集対象要素を保持する table 要素に対し、delegate() メソッドでイベントを割り当てます。このタイミングでの DOM 要素の取得は table 要素のみしか行わないので、データ数が大量にあっても問題はありません。ちなみ delegate() メソッドは jQuery 1.4.2 以降でないと使えません。
  • (2) table 要素内の編集対象要素を mouseover もしくは focus した場合、その要素に対し初期化を行います。
  • (3) 初期化のタイミングと同時に、対象要素に対し編集可能を示す色(薄黄色)を適用したい場合は、nowHover パラメータに true を指定します。

Demo

パラメータ

下記パラメータがあります。

api
初期値:false
true にすると api オブジェクトを返します。
editorType
初期値:input
動的に生成される編集用要素を指定できます。input か textarea を指定します。
htmlEditor
初期値:false
true にすると html 編集モードになります。
displayStyle
初期値:auto
block か inline が指定できます。auto の場合は 編集用要素が input なら inline 、textarea なら block となります。
saveLabel
初期値:SAVE
確定用のボタンラベルを指定できます。false を指定するとボタンを非表示にできます。
cancelLabel
初期値:CANCEL
取消し用のボタンラベルを指定できます。false を指定するとボタンを非表示にできます。
directEdit
初期値:true
false を指定すると編集用ボタンが表示されます。
editLabel
初期値:EDIT
編集用のボタンラベルを指定できます。false を指定するとボタンを非表示にできます。
editLabelAlign
初期値:left
displayStyle パラメータが block の場合、right を指定すると編集ボタンが右端に表示されます。
saveKey
初期値:13
確定処理のショートカットキーのキーコードを指定できます。false を指定するとショートカットキーを無効化できます。
escKey
初期値:27
取消し処理のショートカットキーのキーコードを指定できます。false を指定するとショートカットキーを無効化できます。
convertCR
初期値:br
textarea 内の改行コードを置換する html 要素を指定できます。br または p を指定します。
nulltext
初期値:"(none)"
編集内容が未入力の場合に表示するテキストを指定できます。
savingMessage
初期値:"Saving..."
API メソッドの saving() が実行時に表示されるメッセージを指定します。
hoverSpot
初期値:true
編集可能要素を mouseover した際、編集可能であることを表すために薄黄色になります。false を指定するとこれを抑止できます。
nowHover
初期値:false
プラグイン実行時のタイミングで対象要素を薄黄色にしたい場合は true を指定します。
dataSelect
初期値:false
true を指定すると編集モードに切り替わった際、データが選択された状態になります。
effect
初期値:"fast"
表示/編集モード切替時のエフェクトを指定できます。エフェクトの適用条件として、対象要素が textarea か displayStyle パラメータが "block" である必要があります。
onsave
初期値:なし
確定処理時のコールバック関数が指定できます。
oninit
初期値:なし
プラグイン適用時のコールバック関数が指定できます。

API

下記メソッドがあります。

getTarget()
プラグイン適用対象となった要素を jQuery 形式で返します。
getEditor()
編集用の要素(input 又は textarea)を jQuery 形式で返します。
getLabel()
表示用の要素を jQuery 形式で返します。
getValue()
編集した値を返します。api.getEditor().val() で得られる値の前後の無駄な空白を除去した値を返します。
getConvertValue()
編集した値を HTML の表示用に > や < をエスケープして返します。htmlEditor パラメータを true にしてた場合は、エスケープは行われません。
showEditor()
編集モードにします。
hideEditor()
表示モードにします。
cancel()
1つ前の編集前の値に戻し、表示モードにします。
saving( msg )
引数で指定した文字列を保存処理中のメッセージとして表示、保存中に編集ができないようにロックします。
saveComplete()
Ajax 経由で値のチェック、保存処理を行い正常終了した場合にこのメソッドを呼びます。値の確定処理を表示モードに切り替わります。
saveError( msg )
引数で指定した文字列をエラーメッセージとして表示します。

ダウンロード

こちらからどうぞ