jQuery を用いた in_place_editor_field
趣旨
インプレース編集を可能とする in_place_editor_field。prototype.js 系はアレなので、jQuery 版を作ってみた。といっても、完全互換ではない。mouse hover がらみの処理は省略。みなさんなりの実装をするときの参考にしてもらえれば幸いです。
使い方
- 下のソースコードを見て config/environment.rb を修正し、public/javascripts/ajax_in_place_editor.js を新たに作る。
- コントローラ・ビューを下のように設定する。
コントローラ (app/controllers/blog_controller.rb)
class BlogController < ApplicationController in_place_edit_for :post, :title def update_in_place @post = Post.find(1) end end
ビュー (app/views/blog/update_in_place.html.erb)
<%= javascript_include_tag 'jquery' %> <%= javascript_include_tag 'ajax_in_place_editor' %> # 基本 <%= in_place_editor_field :post, 'title' %> # 画像をクリックして編集開始(独自拡張) <%= in_place_editor_field :post, 'title', {}, click_to_edit_image => 'rails.png' %> # 編集フォームのカスタマイズ(独自拡張) <%= in_place_editor_field :post, 'title', {}, :form_inner_html => '<input type="text" name="value" value="" class="editor_text"/><input type="button" value="保存しちゃうぞ" class="editor_ok_button"/><input type="button" value="やっぱりやめる" class="editor_cancel_button"/>' %>
ソースコード
Ruby側 (config/environment.rb)
# Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license # Copyright (c) 2008 Eiji Sakai, released under the MIT license module InPlaceEditing def self.included(base) base.extend(ClassMethods) end # Example: # # # Controller # class BlogController < ApplicationController # in_place_edit_for :post, :title # end # # # View # <%= in_place_editor_field :post, 'title' %> # module ClassMethods def in_place_edit_for(object, attribute, options = {}) define_method("set_#{object}_#{attribute}") do @item = object.to_s.camelize.constantize.find(params[:id]) @item.update_attribute(attribute, params[:value]) render :text => @item.send(attribute).to_s end end end end module InPlaceMacrosHelper def in_place_editor(field_id, options = {}) function = "new Ajax.InPlaceEditor(" function << "'#{field_id}', " function << "'#{url_for(options[:url])}'" js_options = {} js_options['authParam'] = %('#{request_forgery_protection_token}=#{URI.encode(escape_javascript(form_authenticity_token))}') js_options['clickToEditImage'] = %('#{options[:click_to_edit_image].gsub(/\//, '_')}').gsub(/\./, "_") if options[:click_to_edit_image] js_options['formInnerHTML'] = %('#{options[:form_inner_html]}') if options[:form_inner_html] function << (', ' + options_for_javascript(js_options)) unless js_options.empty? function << ')' javascript_tag(function) end # Renders the value of the specified object and method with in-place editing capabilities. def in_place_editor_field(object, method, tag_options = {}, in_place_editor_options = {}) tag = ::ActionView::Helpers::InstanceTag.new(object, method, self) tag_options = {:tag => "span", :id => "#{object}_#{method}_#{tag.object.id}_in_place_editor", :class => "in_place_editor_field"}.merge!(tag_options) in_place_editor_options[:url] = in_place_editor_options[:url] || url_for({ :action => "set_#{object}_#{method}", :id => tag.object.id }) image_html = in_place_editor_options[:click_to_edit_image] ? image_tag(in_place_editor_options[:click_to_edit_image], :id => in_place_editor_options[:click_to_edit_image].gsub(/\//, '_').gsub(/\./, "_")) : "" image_html + tag.to_content_tag(tag_options.delete(:tag), tag_options) + in_place_editor(tag_options[:id], in_place_editor_options) end end ActionController::Base.send :include, InPlaceEditing ActionController::Base.helper InPlaceMacrosHelper
Javascript 側(public/javascripts/ajax_in_place_editor.js)
# Copyright (c) 2008 Eiji Sakai, released under the MIT license var Ajax = { InPlaceEditor: function(element, url, options) { var e = $("#" + element); options = options || {}; var formHtml = options["formInnerHTML"] || '<input type="text" name="value" value="" class="editor_text"/><input type="button" value="ok" class="editor_ok_button"/><input type="button" value="cancel" class="editor_cancel_button"/>'; var clickToEditSelector = "#" + (options["clickToEditImage"] || element) var clickToEditElement = $(clickToEditSelector); clickToEditElement.click(function() { var clickHandler = arguments.callee; clickToEditElement.unbind('click'); var oldValue = e.html(); e.html(formHtml); $("#" + element + " .editor_text").val(oldValue); $("#" + element + " .editor_ok_button").click(function() { var newValue = $("#" + element + " .editor_text").val(); $.ajax({ "url" : url, "type" : "post", "data" : "value=" + encodeURIComponent(newValue) + "&" + options["authParam"], "success" : function(data, status){ e.html(newValue); clickToEditElement.click(clickHandler); }, "failure" : function(data, status) { alert("failure"); } }); }); $("#" + element + " .editor_cancel_button").click(function() { e.html(oldValue); clickToEditElement.click(clickHandler); }); }); } };