Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inline editing with Rails gem 'best_in_place' - bug: new lines are lost after edit on textarea

I am using best_in_place gem to do some inline editing in a Rails app.

One of the property of my object is of type text, and I want it to be edited in a text area, so I did this:

<%= best_in_place @myobject, :description, :type => :textarea %>

It works, but when not being edited, all returns (\n) are removed.

I tried using simple_format, by adding :display_with => :simple_format to the options passed to best_in_place:

<%= best_in_place @myobject, :description, :type => :textarea, :display_with => :simple_format %>

When not being edited, the new lines are displayed as expected. But the click to enter edition is broken, and a new dash is added above. Clicking it display a textarea box, but it is empty, and the text entered there is not saved back to my object.

The content saved in my property is just plain text, it does not contain any html.


This issue (and patch) seemed related to my problem: https://github.com/bernat/best_in_place/pull/111
However, when applying the patch (manually, to the file .../gems/best_in_place-1.0.6/spec/spec_helper.rb), I still have the same problem.

like image 927
Guillaume Avatar asked Mar 08 '12 15:03

Guillaume


3 Answers

I had the same problem and solved it by binding to the "ajax:success" event as described in the best_in_place documentation and converting the new lines to <br />'s.

$('.best_in_place').bind('ajax:success', function(){ this.innerHTML = this.innerHTML.replace(/\n/g, '<br />') });

You could also choose to use a lightweight markup language like textile or markdown instead of simple line breaks. Javascript converters for these can be found here (textile) and here (markdown).

I went with Textile since I could just use the textilize method in best_in_place's display_with option.

The updated javascript:

$('.best_in_place').bind('ajax:success', function(){ $(this).JQtextile('textile', this.innerHTML) });

Also, if you only want this behavior on best_in_place textareas you can check for the data-type attribute:

$('.best_in_place').bind('ajax:success', function(){ 
    if ($(this).attr('data-type') == 'textarea')
        $(this).JQtextile('textile', this.innerHTML) 
});

Lastly, match the conversion on the server side:

:display_with => lambda { |v| textilize(v).html_safe } // the RedCloth gem may be required.
like image 120
Dan Sandland Avatar answered Nov 08 '22 18:11

Dan Sandland


Found a half-working solution.

In show.html.erb:

<%= best_in_place @myobject, :description, :type => :textarea, :display_as => 'description_format'  %>

and in myobject.rb:

def description_format
  self.description.gsub(/\n/, "<br>")
end

It works as expected. Almost.
The only remaining problem: when you edit the text, after you unfocused from the textarea, the new lines are lost again. If you refresh the page, it is displayed correctly again.

like image 39
Guillaume Avatar answered Nov 08 '22 17:11

Guillaume


If \n is replaced with <br> and the user chooses to do more modifications, the user will see all the text on only one line, making it harder to read and edit.

Based on the answers above I made this solution, which removes any \r upon success.

$('.best_in_place').bind('ajax:success', function(){ 
    if ($(this).attr('data-type') == 'textarea') {
        this.innerHTML = this.innerHTML.replace(/\r/g, '')
    }
});

This ensures that no extra lines are displayed. The advantage of this solution is that if the user chooses to edit the field again, everything is shown as before.

like image 1
Torben Avatar answered Nov 08 '22 17:11

Torben