diff --git a/README.rdoc b/README.rdoc index 26e43435..db7899a8 100644 --- a/README.rdoc +++ b/README.rdoc @@ -34,7 +34,7 @@ Use this form just like normal, including the fields_for helper method for nesti <%= task_form.text_field :name %> <%= task_form.link_to_remove "Remove this task" %> <% end %> - <%= f.link_to_add "Add a task", :tasks %> +

<%= f.link_to_add "Add a task", :tasks %>

This generates links which dynamically add and remove fields. diff --git a/Rakefile b/Rakefile index 8eb48594..c5806454 100644 --- a/Rakefile +++ b/Rakefile @@ -3,14 +3,11 @@ Bundler::GemHelper.install_tasks require 'rubygems' require 'rake' -require 'spec/rake/spectask' - -spec_files = Rake::FileList["spec/**/*_spec.rb"] +require 'rspec/core/rake_task' desc "Run specs" -Spec::Rake::SpecTask.new do |t| - t.spec_files = spec_files - t.spec_opts = ["-c"] +RSpec::Core::RakeTask.new(:spec) do |t| + t.rspec_opts = ["-c"] end task :default => :spec diff --git a/lib/generators/nested_form/install_generator.rb b/lib/generators/nested_form/install_generator.rb index be785652..73fcd306 100644 --- a/lib/generators/nested_form/install_generator.rb +++ b/lib/generators/nested_form/install_generator.rb @@ -5,10 +5,13 @@ def self.source_root File.dirname(__FILE__) + "/templates" end - def copy_jquery_file - copy_file 'nested_form.js', 'public/javascripts/nested_form.js' + if File.exists?('public/javascripts/prototype.js') + copy_file 'prototype_nested_form.js', 'public/javascripts/nested_form.js' + else + copy_file 'jquery_nested_form.js', 'public/javascripts/nested_form.js' + end end end end -end \ No newline at end of file +end diff --git a/lib/generators/nested_form/templates/nested_form.js b/lib/generators/nested_form/templates/jquery_nested_form.js similarity index 78% rename from lib/generators/nested_form/templates/nested_form.js rename to lib/generators/nested_form/templates/jquery_nested_form.js index 5a805f11..dac6e831 100644 --- a/lib/generators/nested_form/templates/nested_form.js +++ b/lib/generators/nested_form/templates/jquery_nested_form.js @@ -6,7 +6,7 @@ $('form a.add_nested_fields').live('click', function() { // Make the context correct by replacing new_ with the generated ID // of each of the parent objects - var context = ($(this).closest('.fields').find('input:first').attr('name') || '').replace(new RegExp('\[[a-z]+\]$'), ''); + var context = ($(this).closest('.fields').find('input:first').attr('name') || '').replace(new RegExp('\[[a-z_]+\]$'), ''); // context will be something like this for a brand new form: // project[tasks_attributes][1255929127459][assignments_attributes][1255929128105] @@ -15,15 +15,17 @@ $('form a.add_nested_fields').live('click', function() { if(context) { var parent_names = context.match(/[a-z_]+_attributes/g) || []; var parent_ids = context.match(/[0-9]+/g); - - for(i = 0; i < parent_names.length; i++) { - if(parent_ids[i]) { - content = content.replace( - new RegExp('(\\[' + parent_names[i] + '\\])\\[.+?\\]', 'g'), - '$1[' + parent_ids[i] + ']' - ) - } - } + + if(parent_ids) { + for(i = 0; i < parent_names.length; i++) { + if(parent_ids[i]) { + content = content.replace( + new RegExp('(\\[' + parent_names[i] + '\\])\\[.+?\\]', 'g'), + '$1[' + parent_ids[i] + ']' + ) + } + } + } } // Make a unique ID for the new child diff --git a/lib/generators/nested_form/templates/prototype_nested_form.js b/lib/generators/nested_form/templates/prototype_nested_form.js new file mode 100644 index 00000000..86231bdc --- /dev/null +++ b/lib/generators/nested_form/templates/prototype_nested_form.js @@ -0,0 +1,50 @@ +document.observe('click', function(e, el) { + if (el = e.findElement('form a.add_nested_fields')) { + // Setup + var assoc = el.readAttribute('data-association'); // Name of child + var content = $(assoc + '_fields_blueprint').innerHTML; // Fields template + + // Make the context correct by replacing new_ with the generated ID + // of each of the parent objects + var context = (el.getOffsetParent('.fields').firstDescendant().readAttribute('name') || '').replace(new RegExp('\[[a-z_]+\]$'), ''); + + // context will be something like this for a brand new form: + // project[tasks_attributes][1255929127459][assignments_attributes][1255929128105] + // or for an edit form: + // project[tasks_attributes][0][assignments_attributes][1] + if(context) { + var parent_names = context.match(/[a-z_]+_attributes/g) || []; + var parent_ids = context.match(/[0-9]+/g); + + if(parent_ids) { + for(i = 0; i < parent_names.length; i++) { + if(parent_ids[i]) { + content = content.replace( + new RegExp('(\\[' + parent_names[i] + '\\])\\[.+?\\]', 'g'), + '$1[' + parent_ids[i] + ']' + ) + } + } + } + } + + // Make a unique ID for the new child + var regexp = new RegExp('new_' + assoc, 'g'); + var new_id = new Date().getTime(); + content = content.replace(regexp, new_id); + + el.insert({ before: content }); + return false; + } +}); + +document.observe('click', function(e, el) { + if (el = e.findElement('form a.remove_nested_fields')) { + var hidden_field = el.previous(0); + if(hidden_field) { + hidden_field.value = '1'; + } + el.ancestors()[0].hide(); + return false; + } +}); diff --git a/lib/nested_form/builder.rb b/lib/nested_form/builder.rb index ca370d0a..453678f7 100644 --- a/lib/nested_form/builder.rb +++ b/lib/nested_form/builder.rb @@ -1,6 +1,6 @@ module NestedForm class Builder < ActionView::Helpers::FormBuilder - def link_to_add(name, association) + def link_to_add(name, association, html_options = {}) @fields ||= {} @template.after_nested_form(association) do model_object = object.class.reflect_on_association(association).klass.new @@ -9,7 +9,15 @@ def link_to_add(name, association) output.safe_concat('') output end - @template.link_to(name, "javascript:void(0)", :class => "add_nested_fields", "data-association" => association) + #@template.link_to(name, "javascript:void(0)", :class => "add_nested_fields", "data-association" => association, html_options.merge!{html_options}) + linkclass = "add_nested_fields" + if html_options.has_key?(:class) + html_options[:class] << " #{linkclass}" + else + html_options.merge!({:class => linkclass}) + end + html_options.merge!({"data-association" => association}) + @template.link_to(name, "javascript:void(0)", html_options) end def link_to_remove(name) @@ -31,4 +39,4 @@ def fields_for_nested_model(name, association, args, block) output end end -end \ No newline at end of file +end diff --git a/spec/nested_form/view_helper_spec.rb b/spec/nested_form/view_helper_spec.rb index 08fc4234..94f18aba 100644 --- a/spec/nested_form/view_helper_spec.rb +++ b/spec/nested_form/view_helper_spec.rb @@ -26,7 +26,8 @@ @template.after_nested_form(:tasks) { @template.concat("123") } @template.after_nested_form(:milestones) { @template.concat("456") } @template.nested_form_for(Project.new) {} - @template.output_buffer.should include("123456") + @template.output_buffer.should include("123") + @template.output_buffer.should include("456") end end