2

タイトルが示すように、私の主な目的は、ajax 呼び出しの後に動的な scss(.erb) ファイルをレンダリングすることです。

assets/javascripts/header.js

// onChange of a checkbox, a database boolean field should be toggled via AJAX
$( document ).ready(function() {
  $('input[class=collection_cb]').change(function() {

    // get the id of the item
    var collection_id = $(this).parent().attr("data-collection-id");
    // show a loading animation
    $("#coll-loading").removeClass("vhidden");

    // AJAX call
    $.ajax({
      type    : 'PUT',
      url      : "/collections/" + collection_id + "/toggle",
      success : function() {
        // removal of loading animation, a bit delayed, as it would be too fast otherwise
        setTimeout(function() {
          $("#coll_loading").addClass("vhidden");
        }, 300);
      },
    });
  });
});

コントローラー/collections_controller.rb

def toggle
  # safety measure to check if the user changes his collection
  if current_user.id == Collection.find(params[:id]).user_id
    collection = Collection.find(params[:id])

    # toggle the collection
    collection.toggle! :auto_add_item
  else
    # redirect the user to error page, alert page
  end

  render :nothing => true
end

データベース オブジェクトのみを切り替えると、すべてが非常にスムーズに機能しました。

ここで、いくつかのスパイスを追加li'sし、現在選択されているユーザーのコレクションに応じて 50+ の CSS を変更したいと考えました。

私の目的のCSSは次のようになります.li要素がコレクションに属しているかどうかをチェックし、そうであれば境界線の色を与えます.

ul#list > li[data-collections~='8'][data-collections~='2']
{
  border-color: #ff2900;
}

これをコントローラーに追加して、次を生成しました[]-conditions

def toggle
  # .
  # .
  # toggle function

  # return the currently selected collection ids in the [data-collections]-format
  @active_collections = ""
  c_ids = current_user.collections.where(:auto_add_item => true).pluck('collections.id')
  if c_ids.size != 0
    c_ids.each { |id| @active_collections += "[data-collections~='#{id}']" }
  end

  # this is what gets retrieved
  # @active_collections => [data-collections~='8'][data-collections~='2']
end

今、動的に生成される scss ファイルにこれらのブラケットを配置する方法が必要です。

追加してみました:

respond_to do |format|
  format.css
end

私のコントローラーに、ファイルviews/collections/toggle.css.erbを持っています

ul#list<%= raw active_collections %> > li<%= raw active_collections %> {
  border-color: #ff2900;
}

別の方法は、コントローラーから css ファイルをレンダリングし、Manuel Meurerの説明に従ってビューに渡すことでした。

ファイル名を間違えましたか?cssの代わりに使用するのが好きscssですか?どのように進めればよいか、何か考えはありますか?

ご協力いただきありがとうございます!

なぜ動的 CSS なのか? - 推論

これは通常、JavaScript を介してクラスを追加することで発生するはずです。動的 css が必要な理由についての私の推論は、ユーザーが選択したコレクションを変更することを決定したとき、彼はこれを非常に集中して行うということです。3 秒間に 4 回の呼び出し、5 分間の一時停止、4 秒間に 5 回の呼び出しのようなものです。li'sJavaScript は、呼び出しのたびに 50+ をループするのに時間がかかりすぎます。

アップデート

結局のところ、JavaScript は私の「長い」リストを非常に高速に処理していました...私の考えの誤りを指摘していただきありがとうございます!

4

3 に答える 3

2

私の意見では、あなたが抱えている問題は CSS に関するものではありません。それはあなたのシステムがどのように機能するかに関係しています

CSS は (http 要求から) 静的に読み込まれます。つまり、ページがレンダリングされるときに、サーバー上の CSS ファイルを変更しても更新されません。

JS はクライアント側であり、(DOM を介して) レンダリングされた HTML 要素と対話するように設計されています。これは、JS がその性質上動的であることを意味し、Ajax などのテクノロジーで使用してページの一部を変更できる理由です。

ここにあなたの問題があると思います...

JS 呼び出しはページをリロードしていません。つまり、CSS は静的なままです。現在、CSS をリロードして、リフレッシュ (HTTP 要求の送信) せずにレンダリングする方法はありません。これは、JS で行う更新には、読み込みごとの CSS を含める必要があることを意味します。

OPへのコメントによると、リスト要素のクラスの更新を実際に検討する必要があります。このようなものを使用すると、即座に機能するはずです。

$('li').addClass('new');

お役に立てれば?

于 2013-10-18T22:08:16.597 に答える
1

私があなたの機能を正しく理解していれば、実際に必要なことは JavaScript だけで簡単に実現でき、ハックする必要はありません。

最初に機能を整理させてください

  • ユーザーがページにアクセスした場合
  • 彼がチェックボックスをチェックすると
  • 彼は、これがサーバーとのやり取りであることを示す読み込み中のサインを見るでしょう。
  • 積み込みサインが止まったとき
  • チェックした行 (または 'li') に境界線があり、これは彼のアクションがサーバーによって受け入れられたことを意味します。

それから解決策が来ます。読みやすくするために、実際のコードではなく、ロード サイン コードを名前付き関数に単純化します。

$(document).ready(function() {
  $('input[class=collection_cb]').change(function() {

    // Use a variable to store parent of current scope for using later
    var $parent = $(this).parent();

    // get the id of the item
    var collection_id = $parent.attr("data-collection-id");

    show_loading_sign();

    // AJAX call
    $.ajax({
      type    : 'PUT',
      url      : "/collections/" + collection_id + "/toggle",
      success : function() {
        // This is the effect you need.
        $parent.addClass('green_color_border');
      },
      error: function() {
        $parent.addClass('red_color_border');
      },
      complete: function() {
        close_loading_sign(); /*Close the sign no matter success or error*/
      } 
    });
  });
});

機能についての私の理解が正しいかどうか、またこれで問題が解決できるかどうか教えてください。

于 2013-10-18T15:13:43.757 に答える
0

ユーザーがコレクションの選択を切り替えたときに、jquery を使用して1 つのクラスを変更しul、それに基づいて静的スタイルを定義するとどうなるでしょうか?

たとえば、元のマークアップは次のようになります。

ul#list.no_selection
  li.collection8.collection2
  li.collection1

そして、あなたのcssは静的に次のようになります:

ul.collection1 li.collection1,
ul.collection2 li.collection2,
...
ul.collection8 li.collection8 {
  border-color: #ff2900;
}

したがって、デフォルトでは境界線はありません。しかし、ユーザーがコレクション 8 を選択した場合、jquery は次のようになります。

$('ul#list').addClass('collection8')

ほら、liそこにあるの周りの境界線-javascriptのcollection8すべてのlis をループせず、スタイルシートを動的にロードすることもありません。

あなたの場合、これはうまくいくと思いますか?

于 2013-10-18T02:00:52.857 に答える