dependent-select 0.0.2
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/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +1 -0
- data/dependent-select.gemspec +17 -0
- data/lib/assets/javascripts/dependent-select.js +56 -0
- data/lib/dependent-select.rb +1 -0
- data/lib/dependent_select.rb +10 -0
- data/lib/dependent_select/engine.rb +6 -0
- data/lib/dependent_select/semantic_form_builder.rb +55 -0
- data/lib/dependent_select/version.rb +5 -0
- metadata +67 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Dependent Select #
|
2
|
+
|
3
|
+
dependent-select is a Formtastic 1.2 compatible extension which provides a `select` where the available options depend on the current value of another field. When the parent field's value is changed, the options of the `dependent_select` are updated via an AJAX request. Much of the functionality is implemented in a [jQuery plugin](https://github.com/topsail/dependent-select/blob/master/lib/assets/javascripts/dependent-select.js) which could be used independenly of Formtastic.
|
4
|
+
|
5
|
+
## Simple Example ##
|
6
|
+
|
7
|
+
<%= semantic_form_for @user do |f| %>
|
8
|
+
<%= f.inputs do %>
|
9
|
+
<%= f.input :department, :as => :select, :collection => Department.find(:all) %>
|
10
|
+
<%= f.input :division, :as => :dependent_select, :parent_method => :department, :collection => (@user.department ? @user.department.divisions : []) %>
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
In this example each `Department` has many `Divisions`. Whenever the department field changes value, the division field is updated to contain only the `Divisions` of the selected `Department`.
|
15
|
+
|
16
|
+
## URL template ##
|
17
|
+
|
18
|
+
The URL used to request the updated option values is controlled by a simple template option, `url_template`, which defaults to:
|
19
|
+
|
20
|
+
/${plural_parent_resource_name}/${value}/${plural_resource_name}.json
|
21
|
+
|
22
|
+
In the above example, assuming the selected department ID is 47, this would translate to `/departments/47/divisions.json`
|
23
|
+
|
24
|
+
The default URL template can also be overridden globally:
|
25
|
+
|
26
|
+
DependentSelect.default_url_template = '/${plural_resource_name}.json?${parent_resource_name}=${value}'
|
27
|
+
|
28
|
+
## Option template ##
|
29
|
+
|
30
|
+
The server must return JSON records. The new `option` tags are then generated via the `option_template`, which defaults to:
|
31
|
+
|
32
|
+
<option value="${id}">${name}</option>
|
33
|
+
|
34
|
+
If the returned objects do not have an `id` and `name` attribute, `option_template` must be overridden.
|
35
|
+
|
36
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dependent_select/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dependent-select"
|
7
|
+
s.version = Dependent::Select::VERSION
|
8
|
+
s.authors = ["Mark Roghelia"]
|
9
|
+
s.email = ["mroghelia@topsailtech.com"]
|
10
|
+
s.summary = %q{Helper and Formtastic support for a select box whose value depends on another field.}
|
11
|
+
#s.rubyforge_project = "dependent-select"
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
#s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
#s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.add_dependency "formtastic"
|
17
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
(function($){
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Sets up a select that refreshes its options whenever another
|
5
|
+
* field changes value.
|
6
|
+
*
|
7
|
+
* parentId - the ID of the observed field
|
8
|
+
*
|
9
|
+
* urlTemplate - the URL used to request the new data from the
|
10
|
+
* server. The value of the parent field will be
|
11
|
+
* substituted for ${value} in the template
|
12
|
+
*
|
13
|
+
*/
|
14
|
+
$.fn.dependentSelect = function(parentId, urlTemplate, options) {
|
15
|
+
|
16
|
+
options = $.extend({
|
17
|
+
optionTemplate: '<option value="${id}">${name}</option>',
|
18
|
+
blankOptionHtml: '<option value=""></option>'
|
19
|
+
}, options || {});
|
20
|
+
|
21
|
+
var select = this;
|
22
|
+
|
23
|
+
$('#' + parentId).bind('change', function(event) {
|
24
|
+
|
25
|
+
select.empty().append(options.blankOptionHtml); // clear out the current options
|
26
|
+
|
27
|
+
var url = urlTemplate.replace('${value}', event.target.value);
|
28
|
+
|
29
|
+
$.getJSON(url, function(resources) {
|
30
|
+
|
31
|
+
var nodes = [ ];
|
32
|
+
|
33
|
+
if (options.includeBlank) {
|
34
|
+
nodes.push(options.blankOptionHtml);
|
35
|
+
}
|
36
|
+
|
37
|
+
for (var i = resources.length-1; i >= 0; i--) {
|
38
|
+
|
39
|
+
var optionNode = options.optionTemplate;
|
40
|
+
|
41
|
+
// substitute resource property values in optionTemplate
|
42
|
+
for (attr in resources[i]) {
|
43
|
+
optionNode = optionNode.replace('${' + attr + '}', resources[i][attr]);
|
44
|
+
}
|
45
|
+
|
46
|
+
nodes.push(optionNode);
|
47
|
+
}
|
48
|
+
|
49
|
+
select.empty().append(nodes.join(''));
|
50
|
+
});
|
51
|
+
});
|
52
|
+
|
53
|
+
return this;
|
54
|
+
};
|
55
|
+
|
56
|
+
})(jQuery);
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'dependent_select'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "formtastic"
|
2
|
+
require "dependent_select/version"
|
3
|
+
require 'dependent_select/semantic_form_builder'
|
4
|
+
require "dependent_select/engine"
|
5
|
+
|
6
|
+
module DependentSelect
|
7
|
+
mattr_accessor :default_url_template
|
8
|
+
end
|
9
|
+
|
10
|
+
DependentSelect.default_url_template = '/${plural_parent_resource_name}/${value}/${plural_resource_name}.json'
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Formtastic
|
2
|
+
class SemanticFormBuilder
|
3
|
+
|
4
|
+
# Options:
|
5
|
+
# parent_id - The DOM ID of the parent field to observe
|
6
|
+
# url_template - The jQuery-compatible template used to generate the URL
|
7
|
+
# parent_method - If provided, parent_id and url_template can be created automatically
|
8
|
+
# option_template - The jQuery-compatible template used to generate the select options
|
9
|
+
def dependent_select_input(method, options)
|
10
|
+
|
11
|
+
html = select_input(method, options)
|
12
|
+
|
13
|
+
options = {}.merge(options)
|
14
|
+
|
15
|
+
html_options = options.delete(:input_html) || {}
|
16
|
+
input_name = generate_association_input_name(method)
|
17
|
+
html_options[:id] ||= generate_html_id(input_name, "")
|
18
|
+
|
19
|
+
if options[:parent_method]
|
20
|
+
|
21
|
+
parent_input_name = generate_association_input_name(options[:parent_method])
|
22
|
+
options[:parent_id] ||= generate_html_id(parent_input_name, "")
|
23
|
+
|
24
|
+
child_reflection = reflection_for(method)
|
25
|
+
parent_reflection = reflection_for(options[:parent_method])
|
26
|
+
|
27
|
+
if child_reflection && parent_reflection && parent_reflection.macro == :belongs_to
|
28
|
+
options[:url_template] ||= DependentSelect.default_url_template
|
29
|
+
.gsub('${resource_name}', child_reflection.class_name.underscore)
|
30
|
+
.gsub('${plural_resource_name}', child_reflection.class_name.underscore.pluralize)
|
31
|
+
.gsub('${parent_resource_name}', parent_reflection.class_name.underscore)
|
32
|
+
.gsub('${plural_parent_resource_name}', parent_reflection.class_name.underscore.pluralize)
|
33
|
+
.gsub('${parent_parameter}', parent_reflection.foreign_key.to_s)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
unless options[:parent_id].blank? || options[:url_template].blank?
|
39
|
+
|
40
|
+
# convert to camelcase keys, which is the convention in Javascript
|
41
|
+
js_options = options.inject({}) do |hash, pair|
|
42
|
+
hash[pair[0].to_s.camelize(:lower)] = pair[1]
|
43
|
+
hash
|
44
|
+
end
|
45
|
+
|
46
|
+
html += "<script>$(document).ready(function() { $('##{html_options[:id]}').dependentSelect('#{options[:parent_id]}', '#{options[:url_template]}', #{js_options.to_json}) });</script>".html_safe
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
return html
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dependent-select
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mark Roghelia
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-06 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: formtastic
|
16
|
+
requirement: &71770510 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *71770510
|
25
|
+
description:
|
26
|
+
email:
|
27
|
+
- mroghelia@topsailtech.com
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- Gemfile
|
33
|
+
- README.md
|
34
|
+
- Rakefile
|
35
|
+
- dependent-select.gemspec
|
36
|
+
- lib/assets/javascripts/dependent-select.js
|
37
|
+
- lib/dependent-select.rb
|
38
|
+
- lib/dependent_select.rb
|
39
|
+
- lib/dependent_select/engine.rb
|
40
|
+
- lib/dependent_select/semantic_form_builder.rb
|
41
|
+
- lib/dependent_select/version.rb
|
42
|
+
homepage:
|
43
|
+
licenses: []
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.8.6
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Helper and Formtastic support for a select box whose value depends on another
|
66
|
+
field.
|
67
|
+
test_files: []
|