bc-htmlful 0.0.0
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/README +11 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/javascripts/dynamic_fields.js +56 -0
- data/javascripts/dynamic_fields.prototype.js +41 -0
- data/lib/htmlful/dynamic_fields.rb +138 -0
- data/lib/htmlful.rb +0 -0
- data/rails/init.rb +0 -0
- data/stylesheets/dynamic_fields.sass +12 -0
- metadata +64 -0
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
begin
|
3
|
+
require 'jeweler'
|
4
|
+
rescue LoadError
|
5
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rake/testtask'
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
require 'rcov/rcovtask'
|
12
|
+
|
13
|
+
Jeweler::Tasks.new do |s|
|
14
|
+
s.name = "bc-htmlful"
|
15
|
+
s.summary = "Form dynamic fields"
|
16
|
+
s.description = s.summary
|
17
|
+
s.email = "info@byclosure.com"
|
18
|
+
s.homepage = "http://github.com/Byclosure/"
|
19
|
+
s.authors = ["Duarte Henriques", "Vasco Andrade e Silva"]
|
20
|
+
# s.add_dependency "activerecord", ['>= 1.1']
|
21
|
+
# s.has_rdoc = true
|
22
|
+
# s.extra_rdoc_files = [ "README.rdoc"]
|
23
|
+
# s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
|
24
|
+
# s.test_files = Dir['test/**/*.{yml,rb}']
|
25
|
+
end
|
26
|
+
|
27
|
+
Jeweler::GemcutterTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,56 @@
|
|
1
|
+
$('input[type="hidden"]').addClass('hide');
|
2
|
+
// buttons UI
|
3
|
+
$('.create_element').addClass('ui-state-default ui-corner-all').hover(function() {
|
4
|
+
$(this).addClass("ui-state-hover");
|
5
|
+
}, function() {
|
6
|
+
$(this).removeClass("ui-state-hover");
|
7
|
+
}).mousedown(function() {
|
8
|
+
$(this).addClass("ui-state-active");
|
9
|
+
}).mouseup(function() {
|
10
|
+
$(this).removeClass("ui-state-active");
|
11
|
+
});
|
12
|
+
|
13
|
+
$('.remove_fieldset').live('click', function(event) {
|
14
|
+
if (event.which != 3) {
|
15
|
+
$(this).parent().prev().find('input[type=hidden]').val(1);
|
16
|
+
$($(this).closest('fieldset')).hide('blind');
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
return true;
|
20
|
+
});
|
21
|
+
$('form div.new_nested_element').each(function() {
|
22
|
+
var create_button = $(this).children('a.create_element');
|
23
|
+
var remove_button = $(this).children('a.remove_element').remove();
|
24
|
+
var fragment = $($(this).find('fieldset')[0]).remove();
|
25
|
+
var remove_button_function = function(event) {
|
26
|
+
if (event.which != 3) {
|
27
|
+
$($(this).closest('fieldset')).hide('blind', {}, 1000, function(){$(this).remove();});
|
28
|
+
return false;
|
29
|
+
}
|
30
|
+
return true;
|
31
|
+
}
|
32
|
+
create_button.click(function(event) {
|
33
|
+
var new_fragment = fragment.clone().hide();
|
34
|
+
|
35
|
+
var new_remove_button = remove_button.clone();
|
36
|
+
new_remove_button.click(remove_button_function);
|
37
|
+
|
38
|
+
var nested_inputs = $(this).parent().children('div.nested_inputs');
|
39
|
+
nested_inputs.append(new_fragment);
|
40
|
+
|
41
|
+
// this is a necessary hack for rails http://groups.google.com.au/group/formtastic/browse_thread/thread/9358a13bd26a6108
|
42
|
+
var unique_id = new Date().getTime();
|
43
|
+
new_fragment.find('input').each(function() {
|
44
|
+
this.id = this.id && this.id.replace(/NEW_RECORD/, unique_id);
|
45
|
+
this.name = this.name && this.name.replace(/NEW_RECORD/, unique_id);
|
46
|
+
});
|
47
|
+
new_fragment.find('label').each(function() {
|
48
|
+
this.htmlFor = this.htmlFor && this.htmlFor.replace(/NEW_RECORD/, unique_id);
|
49
|
+
});
|
50
|
+
|
51
|
+
$($(this).closest('form')).trigger('element-added', new_fragment);
|
52
|
+
new_fragment.append(new_remove_button);
|
53
|
+
new_fragment.show('blind');
|
54
|
+
return false;
|
55
|
+
});
|
56
|
+
});
|
@@ -0,0 +1,41 @@
|
|
1
|
+
// TODO: finish conversion from jquery
|
2
|
+
document.observe('click', function(event) {
|
3
|
+
if (element = event.findElement('.remove_fieldset')) {
|
4
|
+
element.up().previous().select('input[type=hidden]').value = 1;
|
5
|
+
element.up('fieldset').hide();
|
6
|
+
event.stop();
|
7
|
+
}
|
8
|
+
});
|
9
|
+
$$('form div.new_nested_element').each(function(element) {
|
10
|
+
var create_button = element.down('a.create_element');
|
11
|
+
var remove_button = element.down('a.remove_element').remove();
|
12
|
+
var fragment = element.down('fieldset').remove();
|
13
|
+
var remove_button_function = function(event) {
|
14
|
+
this.up('fieldset').remove();
|
15
|
+
event.stop();
|
16
|
+
}
|
17
|
+
create_button.observe('click', function(event) {
|
18
|
+
var new_fragment = fragment.cloneNode(true);
|
19
|
+
|
20
|
+
var new_remove_button = remove_button.cloneNode(true);
|
21
|
+
new_remove_button.observe('click', remove_button_function);
|
22
|
+
|
23
|
+
var nested_inputs = create_button.parent().children('div.nested_inputs');
|
24
|
+
nested_inputs.insert(new_fragment);
|
25
|
+
|
26
|
+
// this is a necessary hack for rails http://groups.google.com.au/group/formtastic/browse_thread/thread/9358a13bd26a6108
|
27
|
+
var unique_id = new Date().getTime();
|
28
|
+
new_fragment.select('input').each(function(e) {
|
29
|
+
e.id = e.id && e.id.gsub(/NEW_RECORD/, unique_id);
|
30
|
+
e.name = e.name && e.name.gsub(/NEW_RECORD/, unique_id);
|
31
|
+
});
|
32
|
+
new_fragment.select('label').each(function(e) {
|
33
|
+
e.htmlFor = e.htmlFor && e.htmlFor.replace(/NEW_RECORD/, unique_id);
|
34
|
+
});
|
35
|
+
|
36
|
+
new_fragment.insert(new_remove_button);
|
37
|
+
new_fragment.show();
|
38
|
+
//this.up().insert({top: new_fragment.insert(new_remove_button)});
|
39
|
+
event.stop();
|
40
|
+
});
|
41
|
+
});
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Htmlful
|
2
|
+
module DynamicFields
|
3
|
+
def _dynamic_fields(form, resource, relationship_name, block1, block2)
|
4
|
+
form.inputs :title => relationship_name do
|
5
|
+
unless resource.send(relationship_name).empty?
|
6
|
+
form.semantic_fields_for(relationship_name) do |sub_form|
|
7
|
+
sub_form.inputs do
|
8
|
+
block1.call(sub_form)
|
9
|
+
concat sub_form.input(:_delete, :as => :hidden, :wrapper_html => {:class => 'remove'}, :input_html => {:class => "checkbox_remove"})
|
10
|
+
concat content_tag(:li, link_to(t(:remove_nested_element, :resource_name => t(resource.class.name)), '#', :class => "remove_fieldset"))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
concat content_tag(:div, :class => "new_nested_element") {
|
15
|
+
concat content_tag(:div, :class => "nested_inputs") {
|
16
|
+
form.inputs do
|
17
|
+
form.semantic_fields_for relationship_name, resource.send(relationship_name).build, :child_index => "NEW_RECORD" do |sub_form|
|
18
|
+
block2.call(sub_form)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
relationship_i18n_name = resource.class.human_attribute_name(relationship_name).to_s
|
23
|
+
concat link_to(t(:remove_nested_element, :resource_name => relationship_i18n_name), '#', :class => "remove_element")
|
24
|
+
concat link_to(t(:create_nested_element, :resource_name => relationship_i18n_name), "#", :class => "create_element")
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def dynamic_fields(form, resource, relationship_name, *attributes)
|
30
|
+
block1 = lambda do |sub_form|
|
31
|
+
sub_object = sub_form.object
|
32
|
+
attributes.each do |attribute|
|
33
|
+
if is_date(sub_object, attribute)
|
34
|
+
concat sub_form.input(attribute, :as => :string, :wrapper_html => {:class => 'datepick'})
|
35
|
+
elsif is_document(sub_object, attribute)
|
36
|
+
if is_document_empty?(sub_object, attribute)
|
37
|
+
concat content_tag(:li, content_tag(:p, t(:no_document)))
|
38
|
+
else
|
39
|
+
if is_image(sub_object, attribute)
|
40
|
+
concat image_tag(sub_form.object.send(attribute).url(:thumb))
|
41
|
+
else
|
42
|
+
concat content_tag(:li, content_tag(:p, link_to(sub_object.send("#{attribute}_file_name"), sub_object.send(attribute).url)))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
concat sub_form.input(attribute)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
block2 = lambda do |sub_form|
|
51
|
+
sub_object = sub_form.object
|
52
|
+
attributes.each do |attribute|
|
53
|
+
if is_date(sub_object, attribute)
|
54
|
+
concat sub_form.input(attribute, :as => :string, :wrapper_html => {:class => 'datepick ignore'})
|
55
|
+
else
|
56
|
+
concat sub_form.input(attribute) # takes care of everything else
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
_dynamic_fields(form, resource, relationship_name, block1, block2)
|
61
|
+
end
|
62
|
+
|
63
|
+
def show_dynamic_fields(form, resource, relationship_name, *attributes)
|
64
|
+
form.inputs :title => relationship_name do
|
65
|
+
if resource.send(relationship_name).empty?
|
66
|
+
concat t(:no_resource_name_plural, :resource_name_plural => resource.class.human_name(:count => 2).mb_chars.downcase)
|
67
|
+
else
|
68
|
+
form.semantic_fields_for(relationship_name) do |sub_form|
|
69
|
+
sub_form.inputs do
|
70
|
+
attributes.each do |attribute|
|
71
|
+
concat show_attribute(sub_form, sub_form.object, attribute)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def show_attribute(form, resource, attribute)
|
80
|
+
if is_date(resource, attribute)
|
81
|
+
form.input(attribute, :as => :string, :wrapper_html => {:class => 'datepick'}, :input_html => {:disabled => true})
|
82
|
+
elsif is_document(resource, attribute)
|
83
|
+
content_tag(:fieldset) do
|
84
|
+
content_tag(:legend) do
|
85
|
+
content_tag(:label, I18n.t("formtastic.labels.#{resource.class.name.underscore}.#{attribute}"))
|
86
|
+
end +
|
87
|
+
if is_document_empty?(resource, attribute)
|
88
|
+
t(:no_document)
|
89
|
+
else
|
90
|
+
if is_image(resource, attribute)
|
91
|
+
image_tag(resource.send(attribute).url(:thumb))
|
92
|
+
else
|
93
|
+
link_to(resource.send("#{attribute}_file_name"), resource.send(attribute).url)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
else
|
98
|
+
form.input(attribute, :input_html => {:disabled => true})
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def show_subcollection(form, resource, association)
|
103
|
+
collection = resource.send(association)
|
104
|
+
resource_name_plural = resource.class.reflect_on_association(association.to_sym).klass.human_name(:count => 2)
|
105
|
+
content_tag(:label, resource_name_plural) +
|
106
|
+
if collection.empty?
|
107
|
+
content_tag(:p, I18n.t(:no_resource_name_plural, :resource_name_plural => resource_name_plural.mb_chars.downcase))
|
108
|
+
else
|
109
|
+
content_tag(:ul, collection.inject("") { |html, sub_resource|
|
110
|
+
html + content_tag(:li, link_to(sub_resource.send(form.send(:detect_label_method, [sub_resource])), sub_resource))
|
111
|
+
}, :class => "sub-collection")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
protected
|
116
|
+
def is_date(resource, attribute)
|
117
|
+
col = resource.column_for_attribute(attribute)
|
118
|
+
col && col.type == :date
|
119
|
+
end
|
120
|
+
|
121
|
+
# taken from formtastic
|
122
|
+
@@file_methods = [:file?, :public_filename]
|
123
|
+
def is_document(resource, attribute)
|
124
|
+
file = resource.send(attribute) if resource.respond_to?(attribute)
|
125
|
+
file && @@file_methods.any? { |m| file.respond_to?(m) }
|
126
|
+
end
|
127
|
+
|
128
|
+
def is_document_empty?(resource, attribute)
|
129
|
+
resource.send("#{attribute}_file_name").blank?
|
130
|
+
end
|
131
|
+
|
132
|
+
# XXX: if image is missing, this will return false because it queries the styles. Find out what we want
|
133
|
+
def is_image(resource, attribute)
|
134
|
+
file = resource.send(attribute) if resource.respond_to?(attribute)
|
135
|
+
is_document(resource, attribute) && file && file.respond_to?(:styles) && !file.styles.blank?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/htmlful.rb
ADDED
File without changes
|
data/rails/init.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bc-htmlful
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Duarte Henriques
|
8
|
+
- Vasco Andrade e Silva
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2010-02-15 00:00:00 +00:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Form dynamic fields
|
18
|
+
email: info@byclosure.com
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files:
|
24
|
+
- README
|
25
|
+
files:
|
26
|
+
- README
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- javascripts/dynamic_fields.js
|
30
|
+
- javascripts/dynamic_fields.prototype.js
|
31
|
+
- lib/htmlful.rb
|
32
|
+
- lib/htmlful/dynamic_fields.rb
|
33
|
+
- rails/init.rb
|
34
|
+
- stylesheets/dynamic_fields.sass
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/Byclosure/
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --charset=UTF-8
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Form dynamic fields
|
63
|
+
test_files: []
|
64
|
+
|