Ajax.InPlaceEditorでバリデーションに引っかかったら

nil.to_sが"nil"になるような言語は(ry というのは置いといて、まだまだPythonをリハビリ中。
Rubyより関数志向での開発がしやすくて楽しいですよねえ。

リハビリを兼ねてweb.pyで個人的なツールを作ってます。web.pyはシンプルで軽いので、個人用途(非公開でツールとして使う)だったらレンタルサーバーでCGIとして動作させても問題なさそうです。(XREAでは簡単なものなら負荷率0ptでした。Railsとかならいれるだけでダメなんで、素晴らしい)

そこで、scriptaculousのAjax.InPlaceEditorを使っているわけですが、困ったことがひとつ。InPlaceEditorなわけで、値を当然入力します。でその値がサーバー側でバリデーションエラーな時どうしたもんかと。

理想的な動作としては

  • エラーをユーザーに通知する

  • サブミットする前の値のままtextareaを表示しておく

なんですが、コンストラクタの中のoptionsあたりをのぞいてもそれらしきオプションはなさげ。

ということでとりあえず場当たり的に書いてみたものが以下。

javascript code
  1. (function(){
  2. Ajax.RollbackableInPlaceEditor = Class.create();
  3. var dummy = function(){};
  4. dummy.prototype = Ajax.InPlaceEditor.prototype;
  5. Ajax.RollbackableInPlaceEditor.prototype = new dummy;
  6. Ajax.RollbackableInPlaceEditor.prototype.constructor = Ajax.RollbackableInPlaceEditor;
  7. })();
  8. Object.extend(Ajax.RollbackableInPlaceEditor.prototype, {
  9.   initialize : function(element, url, options) {
  10.     var self = this;
  11.     options = Object.extend({
  12.       callback: function(form) {
  13.         self.oldValue = self.editField.value;
  14.         return Form.serialize(form);
  15.       },
  16.       onFailure : Prototype.emptyFunction
  17.     }, options || {});
  18.     Ajax.InPlaceEditor.prototype.initialize.apply(this, [element, url, options]);
  19.   },
  20.   onclickCancel: function() {
  21.     this.onComplete();
  22.     this.element.innerHTML = this._oldInnerHTML;
  23.     this.element.show();
  24.     return false;
  25.   },
  26.   onComplete: function(transport) {
  27.     this.leaveEditMode();
  28.     if(transport && !Ajax.Base.prototype.responseIsSuccess.call({transport:transport})) {
  29.       this.options.onFailure.bind(this)(transport, this.element);
  30.       return this.enterEditMode();
  31.     }else {
  32.       this.oldValue = null;
  33.     }
  34.     this.options.onComplete.bind(this)(transport, this.element);
  35.   },
  36.   onFailure: function(transport) {
  37.     return false;
  38.   },
  39.   getText : function() {
  40.      if(this.oldValue != null && this.oldValue != undefined){var v = this.oldValue; this.oldValue = null; return v;}
  41.     this._oldInnerHTML = this.element.innerHTML;
  42.     return this.element.innerHTML;
  43.   }
  44. });
  45.  

サーバー側でエラーがあったときは適当に500とか406とかでレスポンスを返せばオッケーです。

なのでサーバー側ではたとえばweb.pyなら

python code
  1.     # errors = ['データが長すぎます。'] など
  2.     if len(errors) != 0:
  3.       web.header("Content-Type", "text/javascript"),
  4.       web.ctx["status"] = "406 Not Acceptable"
  5.       print "".join(["alert('", "\n".join(errors), "');"])
  6.       return
  7.  

とすればエラーになって(エラーメッセージがアラートされる)、サブミットした内容のままで再度編集できます。

豆知識ですが、以上のようにサーバー側でtext/javascriptでレスポンスを返すとprototype.jsでは自動的にjavascriptとして評価してくれます。

うーむ、まさに場当たり的。いろいろまずそうだけど、まぁ動いてるっぽいし気にしないことにしとこう・・・・

Related posts:

07.27.08/12am

No comments yet

trackback uri
  • ajax-loading
  • ajax-loading
  • ajax-loading

Leave a Comment

You can use these tags: <code>, <i>, <em>, <strong>, <a>

About

Author:yuin(http://inforno.net/)

文学部文化学科卒という生粋の文系趣味プログラマ。

主にRuby、Javascript、PHP、JAVA,Python,C,Scala,Schemeなどを使っています。今はPythonな感じかもしれない。今後作曲活動なども復活するかもしれない。

Pages