awesome_nested_fields 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in awesome_nested_fields.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,46 @@
1
+ module AwesomeNestedFieldsHelper
2
+ def nested_fields_items(builder, association, options={})
3
+ options = nested_fields_process_default_options(options, builder, association)
4
+
5
+ items = ''
6
+ builder.fields_for(association) do |f|
7
+ items << render(options[:partial], options[:builder_local] => f)
8
+ end
9
+
10
+ if options[:none_partial] and builder.object.send(association).empty?
11
+ items << render(options[:none_partial], options[:builder_local] => f)
12
+ end
13
+
14
+ items.html_safe
15
+ end
16
+
17
+ def nested_fields_template(builder, association, options={})
18
+ options = nested_fields_process_default_options(options, builder, association)
19
+
20
+ templates = content_tag(:script, type: 'text/html', class: options[:item_template_class]) do
21
+ builder.fields_for(association, options[:new_object], child_index: 'new_nested_item') do |f|
22
+ render(options[:partial], options[:builder_local] => f)
23
+ end
24
+ end
25
+
26
+ if options[:none_partial]
27
+ templates << content_tag(:script, type: 'text/html', class: options[:none_template_class]) do
28
+ builder.fields_for(association, options[:new_object], child_index: 'new_nested_item') do |f|
29
+ render(options[:none_partial], options[:builder_local] => f)
30
+ end
31
+ end
32
+ end
33
+
34
+ templates.html_safe
35
+ end
36
+
37
+ protected
38
+ def nested_fields_process_default_options(options, builder, association)
39
+ options[:new_object] ||= builder.object.class.reflect_on_association(association).klass.new
40
+ options[:partial] ||= association.to_s.singularize
41
+ options[:builder_local] ||= :builder
42
+ options[:item_template_class] ||= 'template item'
43
+ options[:none_template_class] ||= 'template none'
44
+ options
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/awesome_nested_fields/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'awesome_nested_fields'
6
+ s.version = AwesomeNestedFields::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = %q[Lailson Bandeira]
9
+ s.email = %q[lailson@guava.com.br]
10
+ s.homepage = 'http://rubygems.org/gems/awesome_nested_fields'
11
+ s.summary = 'Awesome nested fields for Rails'
12
+ s.description = 'Awesome dynamic nested fields for Rails and jQuery'
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "awesome_nested_fields"
16
+
17
+ s.add_development_dependency 'bundler', '>= 1.0.0'
18
+ s.add_runtime_dependency 'rails', '>= 3.0.0'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
22
+ s.require_path = 'lib'
23
+ end
@@ -0,0 +1,11 @@
1
+ module AwesomeNestedFields
2
+ class Engine < Rails::Engine
3
+ initializer 'awesome_nested_fields.add_middleware' do |app|
4
+ app.middleware.use ActionDispatch::Static, "#{root}/public"
5
+ end
6
+
7
+ config.to_prepare do
8
+ ApplicationController.helper(AwesomeNestedFieldsHelper)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module AwesomeNestedFields
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,195 @@
1
+ (function($) {
2
+
3
+ var defaultSettings = {
4
+ beforeInsert: function(item, callback) { callback() },
5
+ afterInsert: function(item) {},
6
+ beforeRemove: function(item, callback) { callback() },
7
+ afterRemove: function(item) {},
8
+ itemTemplate: '.item.template',
9
+ noneTemplate: '.none.template',
10
+ container: '.container',
11
+ item: '.item',
12
+ none: '.none',
13
+ addHandler: '.add',
14
+ removeHandler: '.remove',
15
+ newItemIndex: 'new_nested_item'
16
+ };
17
+
18
+ // PUBLIC API
19
+ var methods = {
20
+ init: function(options) {
21
+ var $this = $(this);
22
+ if($(this).data('nested-fields.options')) {
23
+ console.log('Nested fields already defined for this element. If you want to redefine options, destroy it and init again.');
24
+ return $this;
25
+ } else if(getOptions($this)) {
26
+ console.log('You cannot nest nested fields. Who would say that, uh?');
27
+ return $this;
28
+ }
29
+
30
+ options = $.extend({}, defaultSettings, options);
31
+ options.itemTemplate = $(options.itemTemplate, $this);
32
+ options.noneTemplate = $(options.noneTemplate, $this);
33
+ options.container = $(options.container, $this);
34
+ options.addHandler = $(options.addHandler, $this);
35
+ $this.data('nested-fields.options', options);
36
+
37
+ options.addHandler.bind('click.nested-fields', function(e) {
38
+ e.preventDefault();
39
+ var newItem = prepareTemplate(options);
40
+ insertItemWithCallbacks(newItem, null, options);
41
+ });
42
+
43
+ $(options.item, options.container).each(function(i, item) {
44
+ bindRemoveEvent(item, options);
45
+ });
46
+
47
+ return $this;
48
+ },
49
+
50
+ insert: function(callback, options) {
51
+ options = $.extend({}, getOptions(this), options);
52
+ var newItem = prepareTemplate(options);
53
+
54
+ insertItemWithCallbacks(newItem, callback, options);
55
+ },
56
+
57
+ remove: function(element, options) {
58
+ options = $.extend({}, getOptions(this), options);
59
+ return removeItem(element, options);
60
+ },
61
+
62
+ removeAll: function(options) {
63
+ options = $.extend({}, getOptions(this), options);
64
+ $(methods.items.apply(this)).each(function(i, el) {
65
+ methods.remove(el, options);
66
+ });
67
+ },
68
+
69
+ items: function() {
70
+ return findItems(getOptions(this));
71
+ },
72
+
73
+ destroy: function() {
74
+ $(this).removeData('nested-fields.options');
75
+ $('*', this).unbind('.nested-fields');
76
+ }
77
+ };
78
+
79
+ $.fn.nestedFields = function(method) {
80
+ if (methods[method]) {
81
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
82
+ } else if (typeof method === 'object' || !method) {
83
+ return methods.init.apply(this, arguments);
84
+ } else {
85
+ $.error( 'Method ' + method + ' does not exist on jQuery.nestedFields' );
86
+ }
87
+ };
88
+
89
+ function getOptions(element) {
90
+ element = $(element);
91
+ while(element.length > 0) {
92
+ var data = element.data('nested-fields.options');
93
+ if(data) {
94
+ return data;
95
+ } else {
96
+ element = element.parent();
97
+ }
98
+ }
99
+ return null;
100
+ }
101
+
102
+ function prepareTemplate(options) {
103
+ var regexp = new RegExp(options.newItemIndex, 'g');
104
+ var newId = new Date().getTime();
105
+
106
+ var contents = options.itemTemplate.html();
107
+ var newItem = $(contents.replace(regexp, newId));
108
+ newItem.attr('data-new-record', true);
109
+ newItem.attr('data-record-id', newId);
110
+
111
+ bindRemoveEvent(newItem, options);
112
+
113
+ return newItem;
114
+ }
115
+
116
+ function insertItem(newItem, options) {
117
+ removeNone(options);
118
+ options.container.append(newItem);
119
+ }
120
+
121
+ function insertItemWithCallbacks(newItem, onInsertCallback, options) {
122
+ function insert() {
123
+ if(onInsertCallback) {
124
+ onInsertCallback(newItem);
125
+ }
126
+ insertItem(newItem, options);
127
+ }
128
+
129
+ if(!options.skipBefore) {
130
+ options.beforeInsert(newItem, insert);
131
+ } else {
132
+ insert();
133
+ }
134
+
135
+ if(!options.skipAfter) {
136
+ options.afterInsert(newItem);
137
+ }
138
+
139
+ return newItem;
140
+ }
141
+
142
+ function removeItem(element, options) {
143
+ function remove() {
144
+ if($element.attr('data-new-record')) { // record is new
145
+ $element.remove();
146
+ } else { // record should be marked and sent to server
147
+ $element.find("INPUT[name$='[_destroy]']").val('true');
148
+ $element.hide();
149
+ }
150
+ insertNone(options);
151
+ }
152
+
153
+ var $element = $(element);
154
+ if(!options.skipBefore) {
155
+ options.beforeRemove($element, remove);
156
+ } else {
157
+ remove();
158
+ }
159
+
160
+ if(!options.skipAfter) {
161
+ options.afterRemove($element);
162
+ }
163
+
164
+ return $element;
165
+ }
166
+
167
+ function bindRemoveEvent(item, options) {
168
+ var removeHandler = $(item).find(options.removeHandler);
169
+ var needsConfirmation = removeHandler.attr('data-confirm');
170
+
171
+ var event = needsConfirmation ? 'confirmed' : 'click';
172
+ removeHandler.bind(event + '.nested-fields', function(e) {
173
+ removeItem(item, options);
174
+ });
175
+ }
176
+
177
+ function insertNone(options) {
178
+ if(findItems(options).length == 0) {
179
+ options.container.append(options.noneTemplate.html());
180
+ }
181
+ }
182
+
183
+ function removeNone(options) {
184
+ findNone(options).remove();
185
+ }
186
+
187
+ function findItems(options) {
188
+ return options.container.find(options.item + ':visible');
189
+ }
190
+
191
+ function findNone(options) {
192
+ return options.container.find(options.none);
193
+ }
194
+
195
+ })(jQuery);
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awesome_nested_fields
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - Lailson Bandeira
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-12 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rails
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 3
48
+ - 0
49
+ - 0
50
+ version: 3.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Awesome dynamic nested fields for Rails and jQuery
54
+ email: lailson@guava.com.br
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files: []
60
+
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - Rakefile
65
+ - app/helpers/awesome_nested_fields_helper.rb
66
+ - awesome_nested_fields.gemspec
67
+ - lib/awesome_nested_fields.rb
68
+ - lib/awesome_nested_fields/version.rb
69
+ - public/javascripts/jquery.nested-fields.js
70
+ has_rdoc: true
71
+ homepage: http://rubygems.org/gems/awesome_nested_fields
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options: []
76
+
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 23
94
+ segments:
95
+ - 1
96
+ - 3
97
+ - 6
98
+ version: 1.3.6
99
+ requirements: []
100
+
101
+ rubyforge_project: awesome_nested_fields
102
+ rubygems_version: 1.3.7
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Awesome nested fields for Rails
106
+ test_files: []
107
+