开发者

Rails 3 jQuery identifying "this" object

My setup: Rails 3.0.9, Ruby 1.9.2, jQuery 1.6.2

HTML

<textarea id="photo-42-9" class="comment_box">Write a comment...</textarea>

jQuery

$('#newsfeed').delegate('.comment_box', 'keydown', function (event){
   if(event.keyCode == 13) {
    event.preventD开发者_运维问答efault();
    $.post('/comments', { title: ..., description: ... });
  }
});

Rails

comments_controller.rb    
  def create
    @comment = Comment.new

    respond_to do |format|
      format.html # new.html.erb
      format.js
    end
  end

create.js.erb
$("<%= escape_javascript( render 'show_comments') %>").insertBefore(???);

render 'show_comments' returns a <div>stuff</div> that I wish to insert before textarea. I could use the selector on #photo-42-9 but that id is dynamic depending on which textarea element I clicked on. How do I access this object in create.js.erb?


in js:

$('#newsfeed').delegate('.comment_box', 'keydown', function (event){
   if(event.keyCode == 13) {
    event.preventDefault();
    var params = { title: ..., description: ... };
    var $this = $(event.target);
    $.post('/comments', params, function(response) {
        $this.before(response);
    });
  }
});

and in ruby (i guess, I don't do ruby):

"<%= escape_javascript( render 'show_comments') %>"

As you see, "this" isn't passed to rb. Instead, the $.post function waits for the rb response, and pastes it before the text area (the event target). This way is better as all your js code is actually in your js code.

note: "$(response).insertBefore($this)" would work the same.

note: if you move the $this assigination out of the "if", you can easily check if the fresh comment is not empty and different than the ones already existing (event.keyCode == 13 && $this.val() != '' && $this.val() != $this.prev().text()). As well, you can empty the textarea with $this.val('') right after the "$this.before" insertion.


There is no way to access this -- which is determined in a client-side script -- from the create action on your controller which is executing server side in a different scope and different programming language.

You have two options. Either you can pass selector information along with your request so that it can be determined by the server, OR, you can name your selectors systematically so that your selector will be able to be determined by the properties of the object itself.

The latter is simpler. It looks like your form is posting comments on a photo, so for instance, if you use

div_for @photo

to generate the container for the photos you're commenting on, then you can always access that container using:

dom_id @photo

So then you could use inheritance to select the textarea you want to insert before.

In your create.js.erb:

$(...content...).append('#<%= dom_id @photo %>')

Obviously you'll have to structure that to fit the content that you are interacting with. It may be easier to append to the inside of the outer photo container or to select a comment you want to insertAfter or something like that.

Alternatively, you could put a hidden field in your form containing the generated ID of the form, something like hidden_field_tag :form_id, form_id_goes_here.

Then in your controller set:

@selector = params[:form_id]

And in your create.js.erb:

$(...content...).insertBefore('<%= escape_javascript @selector %>')
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜