Contents |
in_place_editor/in_place_editor_field helperhttp://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptMacrosHelper.html#M000569
This is just a wrapper for scriptaculous's Ajax.InPlaceEditor
http://fora.pragprog.com/rails-recipes/discuss-the-book/post/57.
Michael,March 10 (06:52PM)I have a model say User with a: validates_length_of :zip, :minimum => 5 if I do: in_place_edit_for :user, :zip it updates the :zip, but it doesn’t run the validation. I can put whatever I want in the field and it will save.
...
Daniel Klein,April 08 (01:53PM)
Michael’s post covers most of it. I’d add that sending back an alert to the user would be more useful. Define the editor this way:
in_place_editor_field ‘custom_field’, ‘name’, {}, :script => trueAnd then in the controller, use RJS to evaluate:
def set_custom_field_name @i = CustomField.find(params[:id]) old = @i.name @i.name = params[:value] end[which controller action??]
if @i.save render :update do |page| page.replace_html( "custom_field_name_#{params[:id]}_in_place_editor", @i.send(:name) ) end else render :update do |page| page.replace_html( "custom_field_name_#{params[:id]}_in_place_editor", old ) page.call( "alert", "Sorry: you cannot have a field with the same name as another") end end...
Josh (December 20, 2005 at 8:40 am). Ajax the Great (http://shnoo.gr/articles/2005/12/20/ajax-the-great).
... But that’s about as far as you can go. Matias Pelenur points out (in the notes) that in_place_edit_for doesn’t validate nor sanitize the input from the user, which is not a good thing. He recommends defining your own actions instead:def set_product_name @product = Product.find(params[:id]) previous_name = @product.name @product.name = params[:value] @product.name = previous_name unless @product.save render :text => @product.name end
http://wiki.rubyonrails.org/rails/pages/HowToValidateWithAjaxInPlaceEditor HowToValidateWithAjaxInPlaceEditor in Ruby on Rails
Josh (December 20, 2005 at 8:40 am). Ajax the Great (http://shnoo.gr/articles/2005/12/20/ajax-the-great).
You want to allow the blog author to click on his post and edit it in-place. When the article field turns into a textarea for editing, you want the text to revert to its textile syntax, not the final html. ...
http://dev.rubyonrails.org/ticket/8475 #8475 ([PATCH] in_place_editor_field doesn't work for namespaced models) - Rails Trac - Trac
in_place_collection_editor_field helperDaniel Klein (April 08 (06:49PM)). When Your In-Place Editor Needs a Drop-Down (http://fora.pragprog.com/rails-recipes/write-your-own/post/223).
...<%= in_place_collection_editor_field 'custom_field', 'field_type', FieldType.find_all.collect{|x| [x.name,x.id]} %>The x.name is the plaintext description, to be displayed to the user, while the x.id is the internal id. Given that the selected object id will be passed to the controller, along with the id of the object to process, the controller is simply defined as:
def set_custom_field_field_type @i = CustomField.find(params[:id]) f = FieldType.find(params[:value]) @i.update_attribute( :field_type, f ) render :text => f.name end
#46627 - Pastie (http://pastie.caboo.se/46627).
def in_place_collection_editor_field(object,method,container, tag_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) url = url_for( :action => "set_#{object}_#{method}", :id => tag.object.id ) collection = container.inject([]) do |options, element| options << "[ '#{escape_javascript(element.last.to_s)}', '#{escape_javascript(element.first.to_s)}']" end function = "new Ajax.InPlaceCollectionEditor(" function << "'#{object}_#{method}_#{tag.object.id}_in_place_editor'," function << "'#{url}'," function << "{collection: [#{collection.join(',')}], id: '#{object}_#{method}'});" tag.to_content_tag(tag_options.delete(:tag), tag_options) + javascript_tag(function) end
editable_content helperThis is just a wrapper for scriptaculous's Ajax.InPlaceEditor.
This provides more flexibility (perhaps more than you need) than in_place_editor_field.
Coda Hale (2006-01-14). A Rails HOWTO: Simplify In-Place Editing with Script.aculo.us (http://blog.codahale.com/2006/01/14/a-rails-howto-simplify-in-place-editing-with-scriptaculous/).
[I modified this sligthly. Renamed:ajaxto:in_place_editorso that one wouldn't get it confused withajaxOptions, which just happens to be one of the options thatAjax.InPlaecEditortakes... — Tyler (]def editable_content(options) options[:content] = { :element => 'span' }.merge(options[:content]) options[:url] = {}.merge(options[:url]) options[:in_place_editor] = { :okText => "'Save'", :cancelText => "'Cancel'"}.merge(options[:in_place_editor] || {}) script = Array.new script << "new Ajax.InPlaceEditor(" script << " '#{options[:content][:options][:id]}'," script << " '#{url_for(options[:url])}'," script << " {" script << options[:in_place_editor].map{ |key, value| "#{key.to_s}: #{value}" }.join(", ") script << " }" script << ")" content_tag( options[:content][:element], options[:content][:text], options[:content][:options] ) + javascript_tag( script.join("\n") ) end<h1>Mortal Enemies</h1> <% unless @mortal_enemies.empty? %> <ul> <% for mortal_enemy in @mortal_enemies %> <li> <%=h mortal_enemy.name %><%= editable_content( :content => { :element => 'span', :text => mortal_enemy.reason_to_kill, :options => { :id => "mortal_enemy_edit_#{mortal_enemy.id}", :class => 'editable-content' } }, :url => { :controller => 'robot_hit_lists', :action => 'update', :id => mortal_enemy.id }, :ajax => { :okText => "'is why I want to kill them'", :cancelText => "'Nevermind'" } ) %> </li> <% end %> </ul> <% end %>...
Another example: Let's say we're editing the path to an image, and that after we save that field, we want it to update an img tag to show a preview of that image.
Here's how I did it:
html << image_tag("icons/#{node.icon}", :alt => '', :title => 'Preview of icon', :id => "menu_item_icon_#{node.id}_img")
html << content_tag('span',
editable_content(
:content => {
:element => 'span',
:text => node.icon,
:options => {
:id => "menu_item_icon_#{node.id}_in_place_editor",
:class => 'editable-content'
}
},
:url => {
:action => 'set_menu_item_icon',
:id => node.id
},
:in_place_editor => {
:onComplete => "function(transport, element) {
new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
$('menu_item_icon_#{node.id}_img').src = '/images/icons/' + transport.responseText;
}"
}
)
)