dynamic_fields 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README.md +22 -0
  2. data/app/assets/javascripts/dynamic_fields/jquery.dynamic_fields.js +15 -3
  3. data/app/helpers/dynamic_fields_helper.rb +5 -2
  4. data/lib/dynamic_fields/version.rb +1 -1
  5. data/test/dummy/app/assets/javascripts/application.js +1 -0
  6. data/test/dummy/app/assets/javascripts/category.js +10 -0
  7. data/test/dummy/app/controllers/categories_controller.rb +47 -0
  8. data/test/dummy/app/models/available_language.rb +4 -0
  9. data/test/dummy/app/models/category.rb +6 -0
  10. data/test/dummy/app/models/subcategory.rb +5 -0
  11. data/test/dummy/app/views/categories/_form.html.erb +31 -0
  12. data/test/dummy/app/views/categories/edit.html.erb +3 -0
  13. data/test/dummy/app/views/categories/new.html.erb +3 -0
  14. data/test/dummy/config/application.rb +1 -0
  15. data/test/dummy/config/database.yml +1 -5
  16. data/test/dummy/config/initializers/simple_form.rb +136 -0
  17. data/test/dummy/config/locales/simple_form.en.yml +24 -0
  18. data/test/dummy/config/routes.rb +1 -54
  19. data/test/dummy/db/development.sqlite3 +0 -0
  20. data/test/dummy/db/migrate/20120329183323_add_test_tables.rb +31 -0
  21. data/test/dummy/db/schema.rb +39 -0
  22. data/test/dummy/db/test.sqlite3 +0 -0
  23. data/test/dummy/lib/templates/erb/scaffold/_form.html.erb +13 -0
  24. data/test/dummy/log/development.log +2182 -0
  25. data/test/dummy/log/test.log +2369 -0
  26. data/test/dummy/tmp/cache/assets/C83/130/sprockets%2Fa08d178d4b71a990f163b46504982c28 +0 -0
  27. data/test/dummy/tmp/cache/assets/CB3/A30/sprockets%2F6d04c8476e080a28d55b11065d189ef7 +0 -0
  28. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  29. data/test/dummy/tmp/cache/assets/D11/D80/sprockets%2F5e7bc8e026400c478735f2a673f8c1cc +0 -0
  30. data/test/dummy/tmp/cache/assets/D14/530/sprockets%2F6aa64648434ac72bf70c8762f30be78d +0 -0
  31. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  32. data/test/dummy/tmp/cache/assets/D33/600/sprockets%2F70c187184f18b0ac1a4d4ea4be84d606 +0 -0
  33. data/test/dummy/tmp/cache/assets/D4B/CD0/sprockets%2F604268dd58a3c8cbed88c9d61f269e00 +0 -0
  34. data/test/dummy/tmp/cache/assets/D4D/1F0/sprockets%2Fe25fe62f6eac4e9ff1920398e20f7515 +0 -0
  35. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  36. data/test/dummy/tmp/cache/assets/D52/600/sprockets%2F574f4d5dc4fb44d4f453391f29e6ee65 +0 -0
  37. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  38. data/test/dummy/tmp/cache/assets/D81/A70/sprockets%2F7e6bf1374cf493fafa8c58838c4f351d +0 -0
  39. data/test/dummy/tmp/cache/assets/DBC/D50/sprockets%2Fcde339a8b08aa2150fda4ff4a2175bf1 +0 -0
  40. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  41. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  42. data/test/dummy/tmp/capybara/capybara-20120329164214784023357.html +13 -0
  43. data/test/dummy/tmp/pids/server.pid +1 -0
  44. data/test/factories.rb +19 -0
  45. data/test/integration/navigation_test.rb +39 -4
  46. data/test/test_helper.rb +27 -0
  47. metadata +135 -10
data/README.md CHANGED
@@ -57,6 +57,28 @@ Add this to your js file
57
57
  That is all you have to do to get it to work.
58
58
 
59
59
 
60
+ Override Defaults
61
+ -----------------
62
+
63
+ The default wrapper node generate from `dynamic_fields_wrapper_for` is "fieldset" with class "item".
64
+ You can override them by passing a hash to the helper method like this:
65
+
66
+ = dynamic_fields_wrapper_for(qa, :node => 'div', :class => 'nested_field') do
67
+ = your code block
68
+
69
+ If you override the :class option, you will need to apply that to the Javascript as well:
70
+
71
+ $("#qas").cloneFields({
72
+ itemWrapper: ".nested_field"
73
+ })
74
+
75
+
76
+ Example
77
+ --------
78
+
79
+ If you want to take a look at an example, you can checkout the dummy app that used for testing.
80
+
81
+
60
82
 
61
83
  Copyright
62
84
  --------
@@ -25,11 +25,23 @@
25
25
  item.find("input[name$='[_destroy]']").remove(); // don't need to copy the _destroy field
26
26
 
27
27
  item.find(':input').each(function(){
28
- new_id = $(this).attr('id').replace(/\d/, ''+item_num);
28
+ if ($(this).attr('id')) {
29
+ new_id = $(this).attr('id').replace(/\d/, ''+item_num);
30
+ $(this).attr('id', new_id);
31
+ }
32
+
29
33
  new_name = $(this).attr('name').replace(/\d/, ''+item_num);
30
- $(this).attr('id', new_id);
31
34
  $(this).attr('name', new_name);
32
- $(this).val("");
35
+
36
+ // reset all fields
37
+ if ($(this)[0].type == 'textarea' || $(this)[0].type == 'text' || $(this)[0].type.match(/select/)){
38
+ $(this).val("");
39
+ }else if ($(this)[0].type == 'radio'){
40
+ $(this).attr("checked", false)
41
+ }else if ($(this)[0].type == 'checkbox'){
42
+ $(this).attr("checked", false)
43
+ }
44
+
33
45
  })
34
46
 
35
47
  item.find('label').each(function(){
@@ -1,7 +1,10 @@
1
1
  module DynamicFieldsHelper
2
2
 
3
- def dynamic_fields_wrapper_for(form_object, options={:class => 'item'}, &block)
4
- content_tag("fieldset", :class => options[:class]) do
3
+ def dynamic_fields_wrapper_for(form_object, options={}, &block)
4
+ defaults = {:node => "fieldset", :class => 'item'}
5
+ opts = defaults.merge(options)
6
+
7
+ content_tag(opts[:node], :class => opts[:class]) do
5
8
  if form_object.object.persisted?
6
9
  concat form_object.hidden_field :_destroy
7
10
  end
@@ -1,3 +1,3 @@
1
1
  module DynamicFields
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -12,4 +12,5 @@
12
12
  //
13
13
  //= require jquery
14
14
  //= require jquery_ujs
15
+ //= require dynamic_fields
15
16
  //= require_tree .
@@ -0,0 +1,10 @@
1
+ $(function(){
2
+
3
+ $('#more_subcategories').click(function(){
4
+ $("#subcategories").cloneFields({
5
+ itemWrapper: ".nested_field"
6
+ });
7
+ })
8
+
9
+ })
10
+
@@ -0,0 +1,47 @@
1
+ class CategoriesController < ApplicationController
2
+
3
+ def index
4
+ @categories = Category.all
5
+ render :text => @categories.to_json
6
+ end
7
+
8
+ def new
9
+ @category = Category.new
10
+ @category.subcategories.build
11
+ end
12
+
13
+ def create
14
+ @category = Category.new(params[:category])
15
+
16
+ if @category.save
17
+ redirect_to categories_path, :notice => 'The new category was successfully created'
18
+ else
19
+ @category.subcategories.build
20
+ render 'new'
21
+ end
22
+ end
23
+
24
+ def edit
25
+ @category = Category.find(params[:id])
26
+ @category.subcategories.build if @category.subcategories.blank?
27
+ end
28
+
29
+ def update
30
+ @category = Category.find(params[:id])
31
+
32
+ if @category.update_attributes(params[:category])
33
+ redirect_to categories_path, :notice => 'The category was successfully updated'
34
+ else
35
+ @category.subcategories.build if @category.subcategories.blank?
36
+ render :action => "edit"
37
+ end
38
+ end
39
+
40
+ def destroy
41
+ @category = Category.find(params[:id])
42
+
43
+ @category.destroy
44
+ redirect_to categories_path, :notice => "The category was successfully deleted"
45
+ end
46
+
47
+ end
@@ -0,0 +1,4 @@
1
+ class AvailableLanguage < ActiveRecord::Base
2
+ has_and_belongs_to_many :categories
3
+
4
+ end
@@ -0,0 +1,6 @@
1
+ class Category < ActiveRecord::Base
2
+ has_many :subcategories
3
+
4
+ accepts_nested_attributes_for :subcategories, :allow_destroy => true, :reject_if => proc { |attributes| attributes['name'].blank? }
5
+
6
+ end
@@ -0,0 +1,5 @@
1
+ class Subcategory < ActiveRecord::Base
2
+ belongs_to :category
3
+ has_and_belongs_to_many :available_languages
4
+
5
+ end
@@ -0,0 +1,31 @@
1
+ <%= simple_form_for category do |f| %>
2
+
3
+ <%= f.error_notification %>
4
+
5
+ <%= f.input :name %>
6
+
7
+ <div id="more_subcategories">Add More Subcategories</div>
8
+
9
+ <h3>Subcategories</h3>
10
+
11
+ <div id="subcategories">
12
+ <%= f.simple_fields_for :subcategories do |s| %>
13
+ <%= dynamic_fields_wrapper_for(s, :node => 'div', :class => 'nested_field') do %>
14
+ <%= s.input :name %>
15
+ <%= s.input :description %>
16
+ <%= s.input :active, :as => :radio_buttons %>
17
+ <%= s.input :access_level, :collection => 1..4 %>
18
+ <%= s.association :available_languages, :as => :check_boxes %>
19
+ <% end %>
20
+ <% end %>
21
+ </div>
22
+
23
+ <div class="form-actions">
24
+ <%= f.button :submit %>
25
+ </div>
26
+
27
+ <% end %>
28
+
29
+
30
+
31
+
@@ -0,0 +1,3 @@
1
+ <h2>Edit Category</h2>
2
+
3
+ <%= render 'form', :category => @category %>
@@ -0,0 +1,3 @@
1
+ <h2>Create New Category</h2>
2
+
3
+ <%= render 'form', :category => @category %>
@@ -54,3 +54,4 @@ module Dummy
54
54
  end
55
55
  end
56
56
 
57
+ require "#{Rails.root}/../factories.rb"
@@ -18,8 +18,4 @@ test:
18
18
  pool: 5
19
19
  timeout: 5000
20
20
 
21
- production:
22
- adapter: sqlite3
23
- database: db/production.sqlite3
24
- pool: 5
25
- timeout: 5000
21
+
@@ -0,0 +1,136 @@
1
+ # Use this setup block to configure all options available in SimpleForm.
2
+ SimpleForm.setup do |config|
3
+ # Wrappers are used by the form builder to generate a
4
+ # complete input. You can remove any component from the
5
+ # wrapper, change the order or even add your own to the
6
+ # stack. The options given below are used to wrap the
7
+ # whole input.
8
+ config.wrappers :default, :class => :input,
9
+ :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
10
+ ## Extensions enabled by default
11
+ # Any of these extensions can be disabled for a
12
+ # given input by passing: `f.input EXTENSION_NAME => false`.
13
+ # You can make any of these extensions optional by
14
+ # renaming `b.use` to `b.optional`.
15
+
16
+ # Determines whether to use HTML5 (:email, :url, ...)
17
+ # and required attributes
18
+ b.use :html5
19
+
20
+ # Calculates placeholders automatically from I18n
21
+ # You can also pass a string as f.input :placeholder => "Placeholder"
22
+ b.use :placeholder
23
+
24
+ ## Optional extensions
25
+ # They are disabled unless you pass `f.input EXTENSION_NAME => :lookup`
26
+ # to the input. If so, they will retrieve the values from the model
27
+ # if any exists. If you want to enable the lookup for any of those
28
+ # extensions by default, you can change `b.optional` to `b.use`.
29
+
30
+ # Calculates maxlength from length validations for string inputs
31
+ b.optional :maxlength
32
+
33
+ # Calculates pattern from format validations for string inputs
34
+ b.optional :pattern
35
+
36
+ # Calculates min and max from length validations for numeric inputs
37
+ b.optional :min_max
38
+
39
+ # Calculates readonly automatically from readonly attributes
40
+ b.optional :readonly
41
+
42
+ ## Inputs
43
+ b.use :label_input
44
+ b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
45
+ b.use :error, :wrap_with => { :tag => :span, :class => :error }
46
+ end
47
+
48
+ # The default wrapper to be used by the FormBuilder.
49
+ config.default_wrapper = :default
50
+
51
+ # Define the way to render check boxes / radio buttons with labels.
52
+ # Defaults to :nested for bootstrap config.
53
+ # :inline => input + label
54
+ # :nested => label > input
55
+ config.boolean_style = :nested
56
+
57
+ # Default class for buttons
58
+ config.button_class = 'btn'
59
+
60
+ # Method used to tidy up errors.
61
+ # config.error_method = :first
62
+
63
+ # Default tag used for error notification helper.
64
+ config.error_notification_tag = :div
65
+
66
+ # CSS class to add for error notification helper.
67
+ config.error_notification_class = 'alert alert-error'
68
+
69
+ # ID to add for error notification helper.
70
+ # config.error_notification_id = nil
71
+
72
+ # Series of attempts to detect a default label method for collection.
73
+ # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
74
+
75
+ # Series of attempts to detect a default value method for collection.
76
+ # config.collection_value_methods = [ :id, :to_s ]
77
+
78
+ # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
79
+ # config.collection_wrapper_tag = nil
80
+
81
+ # You can define the class to use on all collection wrappers. Defaulting to none.
82
+ # config.collection_wrapper_class = nil
83
+
84
+ # You can wrap each item in a collection of radio/check boxes with a tag,
85
+ # defaulting to :span. Please note that when using :boolean_style = :nested,
86
+ # SimpleForm will force this option to be a label.
87
+ # config.item_wrapper_tag = :span
88
+
89
+ # You can define a class to use in all item wrappers. Defaulting to none.
90
+ # config.item_wrapper_class = nil
91
+
92
+ # How the label text should be generated altogether with the required text.
93
+ # config.label_text = lambda { |label, required| "#{required} #{label}" }
94
+
95
+ # You can define the class to use on all labels. Default is nil.
96
+ config.label_class = 'control-label'
97
+
98
+ # You can define the class to use on all forms. Default is simple_form.
99
+ # config.form_class = :simple_form
100
+
101
+ # You can define which elements should obtain additional classes
102
+ # config.generate_additional_classes_for = [:wrapper, :label, :input]
103
+
104
+ # Whether attributes are required by default (or not). Default is true.
105
+ # config.required_by_default = true
106
+
107
+ # Tell browsers whether to use default HTML5 validations (novalidate option).
108
+ # Default is enabled.
109
+ config.browser_validations = false
110
+
111
+ # Collection of methods to detect if a file type was given.
112
+ # config.file_methods = [ :mounted_as, :file?, :public_filename ]
113
+
114
+ # Custom mappings for input types. This should be a hash containing a regexp
115
+ # to match as key, and the input type that will be used when the field name
116
+ # matches the regexp as value.
117
+ # config.input_mappings = { /count/ => :integer }
118
+
119
+ # Default priority for time_zone inputs.
120
+ # config.time_zone_priority = nil
121
+
122
+ # Default priority for country inputs.
123
+ # config.country_priority = nil
124
+
125
+ # Default size for text inputs.
126
+ # config.default_input_size = 50
127
+
128
+ # When false, do not use translations for labels.
129
+ # config.translate_labels = true
130
+
131
+ # Automatically discover new inputs in Rails' autoload path.
132
+ # config.inputs_discovery = true
133
+
134
+ # Cache SimpleForm inputs discovery
135
+ # config.cache_discovery = !Rails.env.development?
136
+ end
@@ -0,0 +1,24 @@
1
+ en:
2
+ simple_form:
3
+ "yes": 'Yes'
4
+ "no": 'No'
5
+ required:
6
+ text: 'required'
7
+ mark: '*'
8
+ # You can uncomment the line below if you need to overwrite the whole required html.
9
+ # When using html, text and mark won't be used.
10
+ # html: '<abbr title="required">*</abbr>'
11
+ error_notification:
12
+ default_message: "Some errors were found, please take a look:"
13
+ # Labels and hints examples
14
+ # labels:
15
+ # password: 'Password'
16
+ # user:
17
+ # new:
18
+ # email: 'E-mail para efetuar o sign in.'
19
+ # edit:
20
+ # email: 'E-mail.'
21
+ # hints:
22
+ # username: 'User name to sign in.'
23
+ # password: 'No special characters, please.'
24
+
@@ -1,58 +1,5 @@
1
1
  Dummy::Application.routes.draw do
2
- # The priority is based upon order of creation:
3
- # first created -> highest priority.
4
2
 
5
- # Sample of regular route:
6
- # match 'products/:id' => 'catalog#view'
7
- # Keep in mind you can assign values other than :controller and :action
3
+ resources :categories
8
4
 
9
- # Sample of named route:
10
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
11
- # This route can be invoked with purchase_url(:id => product.id)
12
-
13
- # Sample resource route (maps HTTP verbs to controller actions automatically):
14
- # resources :products
15
-
16
- # Sample resource route with options:
17
- # resources :products do
18
- # member do
19
- # get 'short'
20
- # post 'toggle'
21
- # end
22
- #
23
- # collection do
24
- # get 'sold'
25
- # end
26
- # end
27
-
28
- # Sample resource route with sub-resources:
29
- # resources :products do
30
- # resources :comments, :sales
31
- # resource :seller
32
- # end
33
-
34
- # Sample resource route with more complex sub-resources
35
- # resources :products do
36
- # resources :comments
37
- # resources :sales do
38
- # get 'recent', :on => :collection
39
- # end
40
- # end
41
-
42
- # Sample resource route within a namespace:
43
- # namespace :admin do
44
- # # Directs /admin/products/* to Admin::ProductsController
45
- # # (app/controllers/admin/products_controller.rb)
46
- # resources :products
47
- # end
48
-
49
- # You can have the root of your site routed with "root"
50
- # just remember to delete public/index.html.
51
- # root :to => 'welcome#index'
52
-
53
- # See how all your routes lay out with "rake routes"
54
-
55
- # This is a legacy wild controller route that's not recommended for RESTful applications.
56
- # Note: This route will make all actions in every controller accessible via GET requests.
57
- # match ':controller(/:action(/:id))(.:format)'
58
5
  end