2015-05-12 16 views
2

腳本中的「ajax」向服務器發送帖子或刪除消息。包含ajax的javascript是添加複選框的。我們如何使創建的複選框元素持久化,以便用戶刷新頁面時仍然存在?如何使Javascript生成複選框持續?

enter image description here

習慣/ _form.html.erb

<label id="<%= @habit.id %>" class="habit-id"> Missed: </label> 
<% @habit.levels.each_with_index do |level, index| %> 
    <% if @habit.current_level >= (index + 1) %> 
    <p> 
     <label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label> 
     <%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %> 
     <%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %> 
     <%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %> 
    </p> 
    <% end %> 
<% end %> 

habit.js

$(document).ready(function() { 
    var handleChange = function() { 
    habit = $(this).parent().prev().attr("id"); 
    level = $('label', $(this).parent()).attr("id"); 
    if ($(this).is(":checked")) { 
     $.ajax({ 
     url: "/habits/" + habit + "/levels/" + level + "/days_missed", 
     method: "POST" 
     }); 
    } else { 
     $.ajax({ 
     url: "/habits/" + habit + "/levels/" + level + "/days_missed/1", 
     method: "DELETE" 
     }); 
    } 
    if (!$('input[type="checkbox"]:not(:checked)', $(this).parent()).length) { 
     /* this is just an example, you will have to ammend this */ 
     $(this).parent().append($('<input type="checkbox" class="habit-check">')); 
     $(this).parent().append($('<input type="checkbox" class="habit-check">')); 
     $(this).parent().append($('<input type="checkbox" class="habit-check">')); 
     $(".habit-check").on('change',handleChange); 
    } 
    } 
    $(".habit-check").on('change',handleChange); 
}); 

habit.rb

class Habit < ActiveRecord::Base 
    belongs_to :user 
    has_many :comments, as: :commentable 
    has_many :levels 
    serialize :committed, Array 
    validates :date_started, presence: true 
    before_save :current_level 
    acts_as_taggable 
    scope :private_submit, -> { where(private_submit: true) } 
    scope :public_submit, -> { where(private_submit: false) } 

attr_accessor :missed_one, :missed_two, :missed_three 

    def save_with_current_level 
     self.levels.build 
     self.levels.build 
     self.levels.build 
     self.levels.build 
     self.levels.build 
     self.save 
    end 

    def self.committed_for_today 
    today_name = Date::DAYNAMES[Date.today.wday].downcase 
    ids = all.select { |h| h.committed.include? today_name }.map(&:id) 
    where(id: ids) 
    end 

    def current_level_strike 
     levels[current_level - 1] # remember arrays indexes start at 0 
    end 

    def current_level 
      return 0 unless date_started 
      def committed_wdays 
      committed.map do |day|  
       Date::DAYNAMES.index(day.titleize) 
      end 
      end 

      def n_days 
      ((date_started.to_date)..Date.today).count do |date| 
       committed_wdays.include? date.wday 
      end - self.missed_days 
      end  

     case n_days  
      when 0..9 
      1 
      when 10..24 
      2 
      when 25..44 
      3 
      when 45..69 
      4 
      when 70..99 
      5 
      else 
      6 
     end 
    end 
    end 

days_missed_controller

class DaysMissedController < ApplicationController 
    before_action :logged_in_user, only: [:create, :destroy] 

    def create 
    habit = Habit.find(params[:habit_id]) 
    habit.missed_days = habit.missed_days + 1 
    habit.save! 
    level = habit.levels.find(params[:level_id]) 
    level.missed_days = level.missed_days + 1 
    level.save! 
    head :ok # this returns an empty response with a 200 success status code 
    end 

    def destroy 
    habit = Habit.find(params[:habit_id]) 
    habit.missed_days = habit.missed_days - 1 
    habit.save 
    level = habit.levels.find(params[:level_id]) 
    level.missed_days = level.missed_days - 1 
    level.save! 
    head :ok # this returns an empty response with a 200 success status code 
    end 
end 

這裏是它的要點https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2

請讓我知道如果你需要任何進一步的解釋,代碼或圖片:)

回答

1

最簡單的方法是使用本地存儲(存儲在用戶瀏覽器中)。該功能存在於現代瀏覽器中,因此當您不需要支持舊版瀏覽器時,這是最佳選擇。

的使用也是令人難以置信的簡單,只需設置和對「localStorage的」可變的讀取屬性:

# Set one value 
localStorage.myapp_level1_flag1 = true; 

# read the value 
if (localStorage.myapp_level1_flag1) { 
    ... 
} 

當然,你應該給變量有意義的名稱。分配給localStorage的值將在會話中保存。還有一個變量「sessionStorage」,只保存一個會話的數據。

此外,數據由設置的域分隔。因此,域X無法訪問由域Y設置的數據。

本地存儲大致支持自IE8以來,並且優於Cookie,即數據不會在每個請求上傳輸到服務器。在存在本地存儲之前,會使用Cookie,並附加一些性能開銷。

集成

我會推薦本地存儲的整合在你的代碼兩個位置(如果我的理解對不對您的JS大綱):

(當然,你說,那你不太瞭解JS,這讓 變得更加困難,因爲解決方案在瀏覽器端的本地存儲上完全取代了 - 但是否則您需要從服務器端傳輸所有數據(其中可能是必要的 從長遠來看,以避免數據重複))

第一位置:當您創建的複選框(只是一個粗略的例子這怎麼可能):

if (localStorage.habit_level1_flag1) { 
    $(this).parent().append($('<input type="checkbox" class="habit-check" checked>')); 
} 
else { 
    $(this).parent().append($('<input type="checkbox" class="habit-check">')); 
} 

另一個位置是在改變處理器:

if ($(this).is(":checked")) { 
    $.ajax({ 
    url: "/habits/" + habit + "/levels/" + level + "/days_missed", 
    method: "POST" 
    }); 
    localStorage.setItem("habit_"+habit+"_"+level, true); 
} else { 
    $.ajax({ 
    url: "/habits/" + habit + "/levels/" + level + "/days_missed/1", 
    method: "DELETE" 
    }); 
    localStorage.setItem("habit_"+habit+"_"+level, true); 
} 

在這裏尋找更多關於localStorage的信息。

+0

謝謝Juergen爲您精心設計的解釋:)我只是看不到我如何將它與我提供的代碼集成。你說它簡直令人難以置信,我當然希望你是對的。我把它放在habit.js的頂部嗎?我不熟悉JavaScript的內部工作原理。這是一種我還沒有教過自己的語言,但我希望在啓動我的應用程序之前完成這一功能。 –

+0

我添加了一些粗略的集成提示。但是你也可能會想,如果你想將信息存儲在服務器上,並以類似的方式從這裏獲取信息(在創建讀取AJAX調用的複選框時)。 – Juergen

+0

@ AnthonyGalli.com:抱歉忘了給你解決,我不知道,如果你沒有得到一個標誌。閱讀我以前的評論。 – Juergen