Ajax.InPlaceEditorでバリデーションに引っかかったら
nil.to_sが"nil"になるような言語は(ry というのは置いといて、まだまだPythonをリハビリ中。
Rubyより関数志向での開発がしやすくて楽しいですよねえ。
リハビリを兼ねてweb.pyで個人的なツールを作ってます。web.pyはシンプルで軽いので、個人用途(非公開でツールとして使う)だったらレンタルサーバーでCGIとして動作させても問題なさそうです。(XREAでは簡単なものなら負荷率0ptでした。Railsとかならいれるだけでダメなんで、素晴らしい)
そこで、scriptaculousのAjax.InPlaceEditorを使っているわけですが、困ったことがひとつ。InPlace___Editor___なわけで、値を当然入力します。でその値がサーバー側でバリデーションエラーな時どうしたもんかと。
理想的な動作としては
エラーをユーザーに通知する
サブミットする前の値のままtextareaを表示しておく
なんですが、コンストラクタの中のoptionsあたりをのぞいてもそれらしきオプションはなさげ。
ということでとりあえず場当たり的に書いてみたものが以下。
- (function(){
- Ajax.RollbackableInPlaceEditor = Class.create();
- var dummy = function(){};
- dummy.prototype = Ajax.InPlaceEditor.prototype;
- Ajax.RollbackableInPlaceEditor.prototype = new dummy;
- Ajax.RollbackableInPlaceEditor.prototype.constructor = Ajax.RollbackableInPlaceEditor;
- })();
- Object.extend(Ajax.RollbackableInPlaceEditor.prototype, {
- initialize : function(element, url, options) {
- var self = this;
- options = Object.extend({
- callback: function(form) {
- self.oldValue = self.editField.value;
- return Form.serialize(form);
- },
- onFailure : Prototype.emptyFunction
- }, options || {});
- Ajax.InPlaceEditor.prototype.initialize.apply(this, [element, url, options]);
- },
- onclickCancel: function() {
- this.onComplete();
- this.element.innerHTML = this._oldInnerHTML;
- this.element.show();
- return false;
- },
- onComplete: function(transport) {
- this.leaveEditMode();
- if(transport && !Ajax.Base.prototype.responseIsSuccess.call({transport:transport})) {
- this.options.onFailure.bind(this)(transport, this.element);
- return this.enterEditMode();
- }else {
- this.oldValue = null;
- }
- this.options.onComplete.bind(this)(transport, this.element);
- },
- onFailure: function(transport) {
- return false;
- },
- getText : function() {
- if(this.oldValue != null && this.oldValue != undefined){var v = this.oldValue; this.oldValue = null; return v;}
- this._oldInnerHTML = this.element.innerHTML;
- return this.element.innerHTML;
- }
- });
サーバー側でエラーがあったときは適当に500とか406とかでレスポンスを返せばオッケーです。
なのでサーバー側ではたとえばweb.pyなら
- # errors = ['データが長すぎます。'] など
- if len(errors) != 0:
- web.header("Content-Type", "text/javascript"),
- web.ctx["status"] = "406 Not Acceptable"
- print "".join(["alert('", "\n".join(errors), "');"])
- return
とすればエラーになって(エラーメッセージがアラートされる)、サブミットした内容のままで再度編集できます。
豆知識ですが、以上のようにサーバー側でtext/javascriptでレスポンスを返すとprototype.jsでは自動的にjavascriptとして評価してくれます。
うーむ、まさに場当たり的。いろいろまずそうだけど、まぁ動いてるっぽいし気にしないことにしとこう・・・・