0

これはフェイスボックスのポップアップコンテンツです

<div class="form_container">
  <% form_remote_tag :url => { :action => 'custom', :d=>params[:day], :h=>params[:hour]  },
        :class => 'general-form',
        :update => 'grid['+params[:day]+']['+params[:hour]+']',
        :success => 'handle_success('+params[:day]+','+params[:hour]+')' do -%>
    <table width="300px" style="border:none">
      <% @availability_hash.each_key do |availability_id| %>
        #some view related stuff
      <% end %>
    </table>
    <input type="submit" class="btn" value="Re-assign Coaches" />
  <% end %>
</div>

これがコントローラー方式です

  def custom
    master_scheduler
    h = params[:h].to_i
    d = params[:d].to_i
    render(:partial => "grid_item" , :locals => {:day=>d, :hour=>h})
  end

これは部分的なものです(_grid_item.html.erb)

<div class ="left_inner_element">
  <div class="l_upper_element">
    <div class="coaches_committed"><%= data[:committed_coaches] %></div>
    <div class="coaches_available"><%= data[:available_coaches] %></div>
  </div>
  <div class="l_lower_element"><%= data[:classes] %> : <%= data[:avg_attendance] %>
  </div>
</div>
<a id="link[<%= day %>][<%= hour %>]" rel="facebox" href="coach_selector_popup?(bla bla)" >
  <div class ="right_inner_element right_inner_color_<%= data[:color_code] %>">
    #some ui stuff
  </div>
</a>

これはメインページで使用されるスクリプトです

<script type="text/javascript">
  jQuery(document).ready(function($) {
    jQuery('a[rel*=facebox]').facebox()
    $.facebox.settings.opacity = 0.5
  })

  function handle_success(d,h){
    jQuery(document).trigger('close.facebox');
    var link_div = document.getElementById('link['+d+']['+h+']');
    jQuery(link_div).facebox();
  }
</script>

<div class="master_view">
  <table class="master_scheduler_table" id="master_scheduler_table" >
    <% HOURS_IN_A_DAY.each do |hour| %>
      <tr>
        <td><%= time(hour*2) %></td>
        <% DAYS_IN_A_WEEK.each do |day| %>
          <td id="grid[<%= day %>][<%= hour %>]" >
            <%= render(:partial => "grid_item" , :locals => {:day=>day, :hour=>hour, :data=>@data[day][hour]}) %>
          </td>
        <% end %>
      </tr>
    <% end %>
  </table>
</div>

このレンダリングが完了したら、javascriptを呼び出したいと思います。どうやってするか?ビューからform_remote_tagを使用しています。

部分レンダリングはAjaxコンテキストで行われ、ページのリロードは発生しません。form_remote_tagには、javascriptを呼び出すことができる:successメソッドがあります。残念ながら、successメソッドに入れたjavascriptは、レンダリングが行われる前に「呼び出されます」。ただし、レンダリングが完了した後、JavaScriptを呼び出す必要があります。

質問に明確にするためにアラートメッセージを入れただけです。実際、レンダリングしているDIV要素でfacebox()メソッドを呼び出しています。facebox()(jQueryの)メソッドは、レンダリングされた後でDIV要素に適用する必要があります。そうしないと、効果がなくなります。

編集:完全なコードを追加しました。ご覧のとおり、Ajaxが戻ったら、javascriptメソッドhandle_successを呼び出しています。(パーシャル内に:successメソッドを入れたことをお詫びします)。handle_successは、実際のレンダリングが完了する前に呼び出されます。それは「完了後」でなければなりません

4

3 に答える 3

3

どうぞ:

 <!-- IN HTML.ERB FILE -->
    <div class="form_container">
      <% form_tag({:action => :custom, :d => params[:day], :h => params[:hour]}, {:class => "general-form"}) do %>
        <table width="300px" style="border:none">
          <% @availability_hash.each_key do |availability_id| %>
            <tr>
              <td width="50%"><b><%= CoachAvailability.find(availability_id).coach_availability_template.coach.display_name %></b> (X/8)</td>
              <td><%= select_tag('template['+availability_id.to_s+']', options_for_select([["Available", 0],["Scheduled", 1]], :selected => CoachAvailability.find(availability_id).status )) %></td>
            </tr>
          <% end %>
        </table>
        <%= submit_tag "Re-assign Coaches", :class => "btn" %>
      <% end -%>


//In your JS file
$(".general-form").live('submit', function() {
    $.post(this.action, $(this).serialize(), "_method=post");
    return false;
})


#In your controller
def custom
    master_scheduler
    h = params[:h].to_i
    d = params[:d].to_i
    @day = d
    @hour = h
    respond_to do |format|
      format.xml
    end
end

<!-- IN custom.xml.erb -->
<taconite>
    <append select="#div_changed_content">

         What ever changes you want to make. Your code is bit confusing. So i won't go deep into what should come here. You know what changes you want to make. :)

         Maybe you wanted to add this? How did you get data[:commited_coaches] and data[:available_coaches] without passing it through the partial?? 

         Anyways if you want to pass it now you can do so from the controller itself. By creating a @data_commited_coaches and @data_available_coaches and storing the above in that.



    <div class ="left_inner_element">
  <div class="l_upper_element">
    <div class="coaches_committed"><%= data[:committed_coaches] %></div>
    <div class="coaches_available"><%= data[:available_coaches] %></div>
  </div>
  <div class="l_lower_element"><%= data[:classes] %> : <%= data[:avg_attendance] %>
  </div>
</div>
<a id="link[<%= day %>][<%= hour %>]" rel="facebox" href="coach_selector_popup?(bla bla)" >
  <div class ="right_inner_element right_inner_color_<%= data[:color_code] %>">
    #some ui stuff
  </div>
</a>


    </append>   

    <eval>
       // You can call the handle_success here: If i guessed right, this is what you want to do.
       handle_success(<%= @day %>,<%= @hour %>);
    </eval>

</taconite>

&hourと を追加したことに懐疑的です&date。有効なxmlではない可能性があるため、例外をスローするfirebugを検出した場合は削除することをお勧めします。firebug で XML 解析エラーが発生した場合 (firebug コンソールで AJAX 投稿を行うときに XML タブを参照してください)、質問をエラーで編集してください。調べてみます。また、このコードについて説明していただけますか: :update => 'grid['+params[:day]+']['+params[:hour]+']'? ページのどの要素を更新していますか? また、ご覧のとおり、custom.xml.erb には<taconite>タグが含まれています。<append>の ID を持つタグがありdiv_changed_contentます。.html.erb動作させるには、ファイルにその ID を持つ div タグを作成する必要があります。

于 2010-06-21T06:03:42.170 に答える
2

レンダリングはサーバー側で行われ、ページ全体が構成されると、結果の HTML がクライアントに返されます。したがって、この場合、クライアント スクリプトを実行することはできません。onloadページがロードされた後に JavaScript を呼び出すには、イベント ハンドラーを使用できます。

<script type="text/javascript">
window.onload = function() {
    // put your code here
};
</script>

またはjQueryを使用する場合:

<script type="text/javascript">
$(function() {
    // put your code here
});
</script>

またはプロトタイプを使用する場合:

<script type="text/javascript">
document.observe("dom:loaded", function() {
  // put your code here
});
</script>
于 2010-06-20T09:43:53.830 に答える
1

あなたはそれを少し間違っています:

「submitタグには、javascriptを呼び出すことができる:successメソッドがあります。残念ながら、successメソッドに入れたjavascriptは、レンダリングが完了する前に呼び出されます。」

この:success方法は、送信が正常に行われた場合に使用します。送信後に行われるイベントは対象外です。送信ボタンがクリックされたときではなく、パーシャルがレンダリングされた後に実行する成功メソッドが必要です。jqueryに精通している場合は、目立たない方法で行うことをお勧めします。柔軟性がないために組み込みのヘルパーcozに依存したことはなく、インラインjavascriptを使用するのも嫌いです。キャッシュすることはできません。私はすべてのJavaScriptを1つの縮小されたjsファイルに入れ、コードがどこにでも広がるよりも一度キャッシュすることができます。とにかく、私は要点から逸脱しているだけです。

次に、ajax呼び出しのパーシャルをレンダリングしないでください。それは常にあなたのページを更新します。代わりに、その特定のコントローラーアクション用に.js.erbまたはファイルを作成する必要があります。.xml.erb

パーシャルでレンダリングしているものを正確に指定していないので、代わりに一般的な回答を提供します。あなたが何を望んでいるかを正確に知るために、あなたの部分的なコードを私たちと共有してください。また、selector id/class成功時に変更するHTMLタグのを提供します(つまり、レンダリング後)。

より良い方法が必要な場合は、ajaxに使用する構成を提供します。


application.jsの場合:

$.ajaxSetup({
  'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/xml")}
});

$(document).ready(function() {
    //  All non-GET requests will add the authenticity token
    //  If not already present in the data packet
    $("body").bind('ajaxSend', function(elm, xhr, s) {
      if (s.type == "GET") return;
      if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return;
      if (s.data) {
        s.data = s.data + "&";
        } else {
            s.data = "";
            // if there was no data, $ didn't set the content-type
            xhr.setRequestHeader("Content-Type", s.contentType);
        }
        s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token);
    });
  });

IEおよびSAFARIでは、acceptヘッダーのデフォルトはtext/xmlまたはtext/javascriptではなくtext/htmlです。これを修正するには、これをapplication.controller.rbに追加します。クロスブラウザのすべての問題を処理します。

  def correct_safari_and_ie_accept_headers
    ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml']
        request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr?
  end

レイアウトyour_layout.html.erbで、これをヘッダーに追加します。

<% if protect_against_forgery? %>
    <script type="text/javascript" charset="utf-8">
        //<![CDATA[
            window._auth_token_name = "#{request_forgery_protection_token}";
            window._auth_token = "#{form_authenticity_token}";
        //]]>
    </script>
<% end %>
<%= javascript_include_tag 'jquery.taconite.js','application.js', :cache => true %>

JQueryタコナイトプラグインを入手することをお勧めします!アプリでajaxを処理したい場合は、あまりにも優れています。一度に複数のDOM変更を実行できます。

MalsupによるJQueryタコナイト

これの使い方を少し説明します。


次に、これをapplication.jsファイルに追加します。

$("form").live('submit', function() {
   $.post(this.action, $(this).serialize(), "_method=post");
   return false;
 })

パーシャルをレンダリングするために使用したアクションでrender(:partial => "grid_item")、アクションをこれに変更します

   def your_action_here

      # CODE GOES HERE:
      # @instance_variable_to_store_stuff = some_stuff
      respond_to do |format|
        format.html {redirect_to :action => :index}
        format.xml #EXTREMELY IMPORTANT. THIS CORRESPONDS TO your_action_here.xml.erb
      end
   end

次に、ファイルをviews/your_controller/作成しyour_action_here.xml.erbます。このファイルには、レンダリングが行われた後に実行されるjavascriptコードを追加できます。このアクションは2つの方法で応答します。ユーザーがブラウザでjavascriptを無効にしている場合は、htmlデータで応答します。無効になっていない場合は、デフォルトでxmlデータになります。ここでタコナイトが登場します。タコナイトの利点は、jqueryベースのすべてのDOM修飾子をXML準拠のマークアップに変換することです。

行う代わりに、次の$("#div").append('<div>YO!</div>')ことができます。

<append select="#div">
  <div>YO!</div>
</append>

また、複数のDOM変更を行うことができます!100種類の修飾子を連鎖させたり、ビューコードを乱雑にしたりすることを忘れてください。単純なマークアップとしてレールヘルパーを使用する方が自然な感じがします。.js.erbファイルの使用をやめた主な理由の1つ。

ビュー<div>で、IDが「div」のdivタグがあるとします。

your_action_here.xml.erbで、

<taconite>
  <append select="#div">
    <%=h @instance_variable_to_store_stuff %>
  </append>
</taconite>

複数のDOM更新を実行する場合は、たとえば次のように実行できます。

<taconite>
  <replace select="#div">
    <%=h @instance_variable_to_store_stuff %>
  <replace>

  <append select="#someotherelement_id">
    <div>I got appended to #someotherelement_id</div>
  </append>

  <slideUp select=".someelementwithaclass" />

  <slideDown select=".someelementwithanotherclass" />
</taconite>

次のように、evalタグを使用してyour_action_here.xml.erb内でjavascriptを実行することもできます。

<taconite>
  <append select="#div">
    <%=h @instance_variable_to_store_stuff %>
  </append>

    <eval>
            alert("HO! HO! HO!"); 
            setTimeout(($("#flash").effect("highlight", {}, 3000).slideUp("slow")), 5000);
        $("form")[0].reset();

    </eval>
</taconite>

覚えておくべきことの1つは、すべてのxmlタグを閉じ、開いたままにしないことです。厳密にxhtmlに準拠しています。

言及するのを忘れました:Taconiteはfirebugのデバッグログも提供します。開発中にajaxリクエストから行われた変更を追跡したい場合の便利な機能。


于 2010-06-21T03:10:49.793 に答える