<div id="ips_table_div"> <%= render "ips_table" %> </div>
Then, we create the table and the javascript code in our partial view (app/views/ips/_ips_table.html.erb).
<table cellpadding="10"><tbody> <% unless @ips.nil? %> <tr> <td id="ip_new_ip_td_div"> <%= form_tag url_for(:controller => :ips, :action => :create_ip), :remote => true, :id => "new_ip" %> <%= text_field_tag "ip" %> <%= submit_tag t(:add_button, :scope => [:application]), :id => "new_ip_submit" %> </form> </td> <td> </td> </tr> <% @ips.each do |ip| %> <tr> <td id="ip_ip_td_div_<%=ip.id %>"> <div id="ip_ip_text_div_<%=ip.id %>"><%= ip.ip %></div> </td> <td> <%= link_to t(:delete_link, :scope => [:application]), url_for(:controller => :ips, :action => :delete_ip, :id => ip.id), :remote => true, :confirm => t(:ip_delete_confirm, :scope => [:application])%> </td> </tr> <% end %> <% end %> </tbody></table> <script type="text/javascript"> var ip_validate_background_color_error = "#fff999"; var ip_validate_border_color_error = "#f80000"; var ip_validate_background_color = "#ffffff"; var ip_validate_border_color = "#999999"; var ipModifyFormOptions= $H({ cancelText:'<%=t :cancel_link, :scope => [:application] %>', okText: 'ok', savingText: '<%=t :saving_text, :scope => [:application] %>', loadingText: '<%=t :loading_text, :scope => [:application] %>', clickToEditText: '<%=t :click_to_edit_text, :scope => [:application] %>', }); <% unless @ips.nil? %> Form.findFirstElement('new_ip').style.borderColor = ip_validate_border_color; Form.findFirstElement('new_ip').style.backgroundColor = ip_validate_background_color; Form.findFirstElement('new_ip').setAttribute("onkeypress","return input_filter_exact(event, 'ip')"); $('new_ip_submit').disabled=true; new Form.Observer('new_ip', 0.3, function(form, value) { if(validateIpAddress(Form.findFirstElement('new_ip').value, false) == true) { Form.findFirstElement('new_ip').style.borderColor = ip_validate_border_color; Form.findFirstElement('new_ip').style.backgroundColor = ip_validate_background_color; $('new_ip_submit').disabled=false; } else { Form.findFirstElement('new_ip').style.borderColor = ip_validate_border_color_error; Form.findFirstElement('new_ip').style.backgroundColor = ip_validate_background_color_error; $('new_ip_submit').disabled=true; } }); <% @ips.each do |ip| %> new Ajax.InPlaceEditor('ip_ip_text_div_<%=ip.id %>', '<%= url_for :controller => :ips, :action => :modify_ip, :id => ip.id %>', ipModifyFormOptions.merge({ formId: 'ip_ip_form_<%=ip.id %>', onEnterEditMode: function(form, value) { setTimeout(function() { Form.findFirstElement('ip_ip_form_<%=ip.id %>').style.borderColor = ip_validate_border_color; Form.findFirstElement('ip_ip_form_<%=ip.id %>').style.backgroundColor = ip_validate_background_color; Form.findFirstElement('ip_ip_form_<%=ip.id %>').setAttribute("onkeypress","return input_filter_exact(event, 'ip')"); new Form.Observer('ip_ip_form_<%=ip.id %>', 0.3, function(form, value) { if(validateIpAddress(Form.findFirstElement('ip_ip_form_<%=ip.id %>').value, false) == true) { Form.findFirstElement('ip_ip_form_<%=ip.id %>').style.borderColor = ip_validate_border_color; Form.findFirstElement('ip_ip_form_<%=ip.id %>').style.backgroundColor = ip_validate_background_color; $('ip_ip_form_<%=ip.id %>').elements[1].disabled=false; } else { Form.findFirstElement('ip_ip_form_<%=ip.id %>').style.borderColor = ip_validate_border_color_error; Form.findFirstElement('ip_ip_form_<%=ip.id %>').style.backgroundColor = ip_validate_background_color_error; $('ip_ip_form_<%=ip.id %>').elements[1].disabled=true; } }); }, 1000); } }).toObject()); <% end %> <% end %> </script>
Then we should make the controller (app/controllers/ips_controller.rb):
respond_to :js, :only => [:delete_ip, :create_ip] respond_to :html, :except => [:delete_ip, :create_ip] layout :application, :except => [:delete_ip, :create:ip, :modify_ip] layout false, :only => [:delete_ip, :create:ip, :modify_ip] def index @ips=Ip.all respond_with(@ips) end def delete_ip Ip.destroy(params[:id]) # it will returns a javascript code by default, so have to do the # app/views/ips/delete_ip.js.erb, what will loads the table completely @ips=Ip.all respond_with(@ips) end def create_ip ip=Ip.new(params[:ip]).save # it will returns a javascript code, so have to do the # app/views/ips/create_ip.js.erb, what will loads the table completely @ips=Ip.all respond_with(@ips) end def modify_ip ip=Ip.find(params[:id]) ip.update_attribute(:ip, params[:value]) # don't forget some validations here also # it will returns a html code, so have to do the # app/views/ips/modify_ip.html.erb, what will contains the new text only, or: respond_to do |format| format.html { render :text => ip.ip } end end
Then we can create returned javascript codes app/views/ips/create_ip.js.erb and delete_ip.js.erb:
$("ips_table_div").innerHTML=''; $("ips_table_div").update("<%=escape_javascript(render(:template => "/ips/_ips_table.html.erb", :locals => {:ips => @ips})) %>");
Finally we must define javascipt validation functions in public/apllication.js:
function validateIpAddress(value, can_be_empty) { if (arguments.length == 1) { can_be_empty = false; } if (can_be_empty == true) { if (value == null) { return false; } if (value == "") { return true; } } if (value.match(/\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/)) { if (value.length>0 && value.length<256) { return true; } else { return false; } } else { return false; } } function input_filter_exact(e, type) { var enabled_chars; switch (type) { case "ip": enabled_chars="0123456789."; break; default: enabled_chars="-/.,_?[]()!abcdefghijklmnopqrstvuwxyzABCDEFGHIJKLMNOPQRSTVUWXYZ0123456789éáőúűóüöíÉÁŐÚÓÜÖÍ "; } var key; var keychar; if (window.event) key = window.event.keyCode; else if (e) key = e.which; else return true; keychar = String.fromCharCode(key); if ((key==null) || (key==0) || (key==8) || (key==9) || (key==13) || (key==27) ) return true; else if (((enabled_chars).indexOf(keychar) > -1)) return true; else return false; }
That's all. Works with Rails 3.0.9, Prototype 1.7 and script.aculo.us v1.8.3
Thanks for post, but it seems too hard to implement and have much custom javascript and lots of non-restful actions in controller
ReplyDeleteI'm sure there's an easier way.
ReplyDelete