顯示具有 jQuery 標籤的文章。 顯示所有文章
顯示具有 jQuery 標籤的文章。 顯示所有文章

2016年10月31日 星期一

Cloud9-RoR-jquery-validation-rails

參考來源(安裝):https://github.com/meowsus/jquery-validation-rails
參考來源(使用方式):http://tudip.blogspot.tw/2013/05/jquery-validate-in-rails-applications-by-tudip-technologies.html
doc說明:https://jqueryvalidation.org/validate/

因為我是另外用$.get及jquery-ui的dialog套件相互配合來載入編輯頁面,所以js碼必需寫在被載入的頁面裡,不然其實可以直接寫在coffee檔裡的。

首先,安裝jquery-validation-rails,編輯Gemfile,加上
# validation
gem 'jquery-validation-rails'

執行指令
$ bundle

編輯app/assets/javascripts/application.js檔,加上
//= require jquery.validate
//= require jquery.validate.additional-methods

編輯app/assets/stylesheets/application.css檔,加上
.error {
  color: #FF0000;
}

veiw檔及js的部份,需要套入驗證的text_field記得加上:class => "required",js的debug如果打開來的話,表單就算全部驗證通過也不會被送出哦!如果已測試完成,記得要把那行註解掉。
<%= form_for @rcalendar, :url => rcalendars_path do |f| %>
  <%= f.hidden_field :v_calendar_id, :value => params[:vid] %>
  <div>
  <%= f.label :fb_nickname, "Facebook姓名" %><span style="color:#FF0000">(必填)</span>
  <%= f.text_field :fb_nickname, :class => "required" %>
  </div>
  <div>
  <%= f.label :fb_urls, "Facebook網址" %><span style="color:#FF0000">(必填)</span>
  <%= f.text_field :fb_urls, size: "57", :class => "required" %>
  </div>
  <div>
  <%= f.label :content, "內容" %>
  <%= f.text_area :content, size: "50x10"  %>
  </div>
  <div>
  <%= f.label :password, "取消預約密碼" %><span style="color:#FF0000">(必填)</span>
  <%= f.password_field :password, :class => "required", autocomplete: "off" %>
  </div> 
  <div>
  <%= f.label :password_confirmation, "確認取消密碼" %><span style="color:#FF0000">(必填)</span>
  <%= f.password_field :password_confirmation, :class => "required", autocomplete: "off" %>
  </div>      
  <%= f.submit "確定" %>
<% end %>

<script type="text/javascript">
$('#new_rcalendar').validate({
  //debug: true,
  rules: {
    'rcalendar[fb_nickname]': {
      required: true
    },
    'rcalendar[fb_urls]': {
      required: true,
      url: true
    },
    'rcalendar[password]': {
      required: true,
      minlength: 5
    },
    'rcalendar[password_confirmation]': {
      required: true,
      minlength: 5,
      equalTo: "#rcalendar_password"
    }
  },
  messages: {
    'rcalendar[fb_nickname]': {
      required: '必須填寫'
    },
    'rcalendar[fb_urls]': {
      required: '必須填寫',
      url: '請輸入有效的網址'
    },
    'rcalendar[password]': {
      required: '必須填寫',
      minlength: '長度不得小於5位數'
    },
    'rcalendar[password_confirmation]': {
      required: '必須填寫',
      minlength: '長度不得小於5位數',
      equalTo: '密碼不符'
    }
  }
});
</script>

測試時欄位如果一開始就為空,保持在空值狀態時是不會秀出錯誤的,除非輸入資料後再清空才會有錯誤的提醒,就這點比較讓我匪夷所思,在此提醒一下大家,免得像我一樣一直鬼打牆。

2016年10月25日 星期二

Cloud9-RoR-fullcalendar-rails & CRUD Part.1

*2016/11/1-更新calendar.coffee、calendar.controller,將_form.html.erb改回new.html.erb。

參考來源(jquery-ui):https://rubygems.org/gems/fullcalendar-rails/versions
參考來源(CRUD):http://vinsol.com/fullcalendar-demo

C:會套用前幾篇中提到的one-to-many頁面。
R:使用jquery-ui的套件,將事件的detail顯示在dialog裡。
U:本篇不做。
D:依附在read底下,點選某一日曆上的事件時才會載入delete按鈕,如該事件已有人回復/預訂,則不可刪除。

首先安裝 jquery-ui-rails
打開Gemfile檔,加入
# jquery-ui
gem 'jquery-ui-rails'

編輯application.js,加入
//= require jquery-ui

編輯application.css,加入
*= require jquery-ui

執行指令
$ bundle install


CRUP實做
編輯calendars_controller.rb
  before_action :set_calendar, :only => [ :destroy]
  def index
    @calendars = Calendar.
    select("calendars.id", "IF(calendars.user_id = '#{current_user.id}', 1, 0) AS isedit",
    "IF(rcalendars.fb_nickname IS NULL, 1, 0) AS reserved",
    "CONCAT(calendars.vdate , ' ', calendars.vtime, ':00:00') AS dt", 
    "CONCAT(users.username, ' ', IFNULL(rcalendars.fb_nickname, '')) AS title",
    "CONCAT(calendars.vdate , ' ', calendars.vtime, '點<br/>', IFNULL(rcalendars.content, '')) AS description").
    joins("LEFT JOIN users ON users.id = calendars.user_id LEFT JOIN rcalendars ON rcalendars.calendar_id = calendars.id")
    #if json file(index.json.jbuilder) like to link use json.url calendar_path(calendar)
  end

  def new
    @calendar = []
    15.times do
      @calendar << Calendar.new
    end
    render :layout => false
  end
  
  def create
    if params.has_key?("calendar")
      @calendar = Calendar.create(calendar_params(params["calendar"]))
    else
      params["calendars"].each do |calendar|
        if calendar["issave"] && calendar["vdate"] != ""
          @calendar = Calendar.create(calendar_params(calendar))
        end
      end
    end
    
    #json
    respond_to do |format|
      if @calendar.save
        format.html { redirect_to calendars_url, notice: 'calendar was successfully created.' }
        format.json { render action: 'index', status: :created, location: @calendar }
      else
        format.html { render action: 'new' }
        format.json { render json: @calendar.errors, status: :unprocessable_entity }
      end
    end 
    #json
  end  

  def destroy
    @calendar.destroy
    redirect_to calendars_url
    flash[:alert] = "calendar was successfully deleted"
  end
  
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_calendar
      @calendar = Calendar.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def calendar_params(my_params)
      my_params.permit(:user_id, :vdate, :vtime)
    end  

編輯calendar.coffee
$(document).ready ->
  # page is now ready, initialize the calendar...
  $('#new_event').click (event) ->
    $.get '/calendars/new', (data) ->
      #初始將a.html include div#iframe
      $('#create_event').html data
      return
    $('#create_event_dialog').dialog
      title: '新增'
      modal: true
      width: 500
      close: (event, ui) ->
        $('#create_event_dialog').dialog 'destroy'
        return
    return
    
  $('#create_event_dialog, #desc_dialog').on 'submit', '#event_form', (event) ->
    $spinner = $('.spinner')
  
    show_spinner = ->
      $spinner.show()
      return
  
    hide_spinner = ->
      $spinner.hide()
      return
  
    handle_error = (xhr) ->
      alert xhr.responseText
      return
  
    event.preventDefault()
    $.ajax
      type: 'POST'
      data: $(this).serialize()
      url: $(this).attr('action')
      beforeSend: show_spinner
      complete: hide_spinner
      success: refetch_events_and_close_dialog
      error: handle_error
    return
    
  $('#calendar').fullCalendar
    header:
      left: 'prev,next today'
      center: 'title'
      right: 'month'
    defaultView: 'month'
    loading: (bool) ->
      if bool
        $('#loading').show()
      else
        $('#loading').hide()
      return
    events: '/calendars.json'
    timeFormat: 'Ahh點'
    eventClick: (event, jsEvent, view) ->
      showEventDetails event
      return  
  return

showEventDetails = (event) ->
  $('#event_desc').html event.description
  title = event.title
  if event.isedit and event.reserved
    $('#delete_event').html '<form class="button_to" method="post" action="/calendars/' + event.id + '"><input type="hidden" name="_method" value="delete" /><input type="hidden" name="authenticity_token" value="' + $('meta[name="csrf-token"]').attr('content') + '" /><input data-confirm="Are you sure?" type="submit" value="Delete" /></form>'
  else
    $('#delete_event').html ''
  $('#desc_dialog').dialog
    title: title
    modal: true
    width: 500
    close: (event, ui) ->
      $('#desc_dialog').dialog 'destroy'
      return
  return

refetch_events_and_close_dialog = ->
  $('#calendar').fullCalendar 'refetchEvents'
  $('.dialog:visible').dialog 'destroy'
  return

編輯calendars.scss
.fc-h-event {
    cursor: pointer;
}

編輯calendars/index.html.erb
<div><%=link_to '新增', new_calendar_path, :id => 'new_event' %></div>

<div id="calendar"></div>

<!--隱藏表單 //-->
<div id = "desc_dialog" class="dialog" style ="display:none;">
  <div id = "event_desc">
  </div>
  <br/>
  <br/>
  <div id = "event_actions">
    <span id = "edit_event"></span>
    <span id = "delete_event"></span>
  </div>
</div>
<div id = "create_event_dialog" class="dialog" style ="display:none;">
  <div id = "create_event">
  </div>
</div>

新增的畫面

點開日曆事件時的畫面
可編輯自己的部份:

不可編輯他人的資料:

後台總算告個段落,只剩下套版了。

2016年4月7日 星期四

Cloud9-RoR-jQuery套版

參考文章(1):http://openhome.cc/Gossip/Rails/Layout.html
參考文章(2):http://openhome.cc/Gossip/Rails/Assets.html
輔助文章(1):https://ihower.tw/rails4/assets-pipeline.html
輔助文章(2):http://guides.rubyonrails.org/asset_pipeline.html
輔助文章(3):http://api.rubyonrails.org/v3.0.9/classes/ActionView/Helpers/AssetTagHelper.html
輔助文章(2)-簡中:http://guides.ruby-china.org/asset_pipeline.html

因為我目前的打算是每頁都有屬於自己的版面功能,所以這篇是介紹怎麼替單獨的頁面套上jQuery版型。很多範例都是加在app/assets裡,但這樣會套用到所有的頁面,跟我要的不一樣,結果又花了好多時間研究…

在rails中,可以放js及css檔的地方其實有三個,輔助文章(1)裡面有做仔細的說明,因為我是要使用jQuery,所以放在vendor/assets裡。

在目錄處找到vendor/assets,將jQuery中的js檔及css檔分別放入javascripts和stylesheets folder中,不過為預防日後還會使用到不同的jQuery會混淆不清,所以我們先在javascripts和stylesheets的folder底下新增一個這次要使用的jQuery folder名稱,名稱建議取相同的,才知道是同一組jQuery的檔案,然後新增兩個檔案。

新增一個同樣名稱的js檔放在vendor/assets/javascripts,例如myjQuery.js
//= require_tree .

新增一個同樣名稱的css檔放在vendor/assets/stylesheets,例如myjQuery.css
 /*
 = require_tree .
*/

如果jQuery會使用到圖檔,請在vendor/assets下方建立一個images folder,一樣在images底下新增同名的folder,把會使用到的圖片上傳至此folder中。css檔裡的圖檔連結請一定要照規定寫,否則會找不到圖片哦!

我是將會使用到圖片的該隻css檔,副檔改為scss,只要有image連結的部份都一律改為「image-url」(括弧內一定要加雙引號,否則會出錯)
background-image: image-url("myjQuery/rails.png")

打開這次要套用jQuery的html.erb檔,我習慣將套件放在最下方
.
.
.
<!-- css //-->
<%= stylesheet_link_tag 'myjQuery' %>

<!-- jquery //-->
<%= javascript_include_tag 'myjQuery' %>

編輯config/initializers/assets.rb(我是使用rails4.2,config.assets.precompile已被移入assets.rb裡了,寫在config/environments/production.rb裡沒用哦!)
Rails.application.config.assets.precompile += %w( myjQuery.js myjQuery.css )
Rails.application.config.assets.precompile += %w( *.png *gif *.jpg )
註:第二行是我的css裡會用到的圖檔類型,如果你有用到其他更多類型的檔案(不一定是圖檔),可以自行加上*.你會用的檔案副檔名。

這樣就套版完成嘍!