context_help 0.0.1
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 +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +17 -0
- data/Rakefile +1 -0
- data/context_help.gemspec +20 -0
- data/lib/context_help/base.rb +181 -0
- data/lib/context_help/patches/form_helper_patch.rb +69 -0
- data/lib/context_help/patches/formtastic_patch.rb +27 -0
- data/lib/context_help/patches/tag_helper_patch.rb +19 -0
- data/lib/context_help/version.rb +3 -0
- data/lib/context_help.rb +7 -0
- metadata +60 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= ContextHelp
|
2
|
+
|
3
|
+
ContexHelp is a ruby gem for discovering documentable elements in rails applications
|
4
|
+
and showing help for them. Currently ContextHelp detects form_tag elements, models and
|
5
|
+
attributes in forms rendered by form_for or formtastic, and other html elements rendered
|
6
|
+
by *_tag helpers.
|
7
|
+
|
8
|
+
== Features
|
9
|
+
|
10
|
+
* Autodetection of model and attributes present on a view from formtastic y form_for helpers.
|
11
|
+
* Autodetection of html tags rendered by *_tag helpers
|
12
|
+
* Custom documentation for custom elements through I18n like routes. Ej: 'en.context_help.custom.tree_view'
|
13
|
+
* Basic inline and contextual help HTML renderer
|
14
|
+
* Customizable renderers
|
15
|
+
* Internationalized text. ContextHelp gets help texts from I18n files.
|
16
|
+
|
17
|
+
==
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "context_help/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "context_help"
|
7
|
+
s.version = ContextHelp::VERSION
|
8
|
+
s.authors = ["Juan Pablo Marzetti"]
|
9
|
+
s.email = ["jmarzetti@sequre.com.ar"]
|
10
|
+
s.homepage = "http://sequre.com.ar"
|
11
|
+
s.summary = %q{A Rails context help facility to offer help about yor models and attributes}
|
12
|
+
s.description = %q{ContextHelp is a gem that allows you to show inline or aside help about every input item found in a form tag, a model, its attributes and even custom help about other HTML tags}
|
13
|
+
|
14
|
+
s.rubyforge_project = "context_help"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module ContextHelp
|
2
|
+
module Base
|
3
|
+
@help_items = []
|
4
|
+
@config = {
|
5
|
+
:show_inline => false,
|
6
|
+
:title_tag => 'h1',
|
7
|
+
:title_class => 'help_title',
|
8
|
+
:text_tag => 'span',
|
9
|
+
:text_class => 'help_text',
|
10
|
+
:level_classes => {
|
11
|
+
:model => 'help_level_1',
|
12
|
+
:model_attribute => 'help_level_2',
|
13
|
+
:html => {
|
14
|
+
:default => 'help_level_2',
|
15
|
+
|
16
|
+
:form => 'help_level_1',
|
17
|
+
:fieldset => 'help_level_2',
|
18
|
+
},
|
19
|
+
:custom => 'help_level_3'
|
20
|
+
},
|
21
|
+
:exclude_tags => [:script, :link, :li],
|
22
|
+
:exclude_models => [],
|
23
|
+
:show_missing => false,
|
24
|
+
:link_to_object => false,
|
25
|
+
:link_to_help => false
|
26
|
+
}
|
27
|
+
|
28
|
+
def self.help_for(options)
|
29
|
+
help_options = options[:context_help]
|
30
|
+
self.help_path_for(help_options)
|
31
|
+
self.inline_help(help_options)
|
32
|
+
end
|
33
|
+
def self.context_help(&block)
|
34
|
+
help = ''
|
35
|
+
@help_items.each do |item|
|
36
|
+
item[:calculated_path] = self.help_path_for(item, false) if !item[:calculated_path]
|
37
|
+
if block_given?
|
38
|
+
help += yield(item)
|
39
|
+
elsif !item[:skip] and item[:calculated_path]
|
40
|
+
help += self.html_help(item)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
help.strip
|
44
|
+
end
|
45
|
+
def self.help_items
|
46
|
+
@help_items
|
47
|
+
end
|
48
|
+
def self.config
|
49
|
+
@config
|
50
|
+
end
|
51
|
+
def self.flush_items
|
52
|
+
@help_items = []
|
53
|
+
end
|
54
|
+
def self.inline_help(options)
|
55
|
+
return '' if options[:skip] or !options[:calculated_path]
|
56
|
+
if options[:inline_help_builder].is_a?(Proc)
|
57
|
+
options[:inline_help_builder].call(options)
|
58
|
+
elsif options[:show_inline]
|
59
|
+
self.html_help(options)
|
60
|
+
else
|
61
|
+
''
|
62
|
+
end
|
63
|
+
end
|
64
|
+
def self.help_path_for(options,register=true)
|
65
|
+
path = options[:path]
|
66
|
+
return path if path.is_a?(String)
|
67
|
+
|
68
|
+
ruta = nil
|
69
|
+
if !options[:skip]
|
70
|
+
if path[:model] and @config[:exclude_models].index(path[:model].to_sym).nil?
|
71
|
+
ruta = 'context_help.models.'+model_name(path[:model])
|
72
|
+
options[:pre_level_class] = @config[:level_classes][:model]
|
73
|
+
|
74
|
+
if (path[:attribute])
|
75
|
+
ruta = ruta + '.attributes.'+ path[:attribute].to_s.underscore
|
76
|
+
options[:pre_level_class] = @config[:level_classes][:model_attribute]
|
77
|
+
end
|
78
|
+
elsif path[:tag] and @config[:exclude_tags].index(path[:tag].to_sym).nil?
|
79
|
+
ruta = 'context_help.html.'+path[:tag].to_s.downcase
|
80
|
+
ruta = ruta + '.' + path[:tag_options][:id].to_s if path[:tag_options][:id]
|
81
|
+
|
82
|
+
if @config[:level_classes][:html].include?(path[:tag])
|
83
|
+
options[:pre_level_class] = @config[:level_classes][:html][path[:tag]]
|
84
|
+
else
|
85
|
+
options[:pre_level_class] = @config[:level_classes][:html][:default]
|
86
|
+
end
|
87
|
+
elsif path[:custom]
|
88
|
+
ruta = 'context_help.custom.'+path[:custom]
|
89
|
+
options[:pre_level_class] = @config[:level_classes][:custom]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
if ruta
|
93
|
+
options[:calculated_path] = ruta if (I18n.t(ruta+'.title', :default => '') != '') or (Rails.env.development? and @config[:show_missing])
|
94
|
+
self.register_item(options) if register
|
95
|
+
return options[:calculated_path]
|
96
|
+
end
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
def self.html_help(options)
|
100
|
+
if options[:help_builder].is_a?(Proc)
|
101
|
+
options[:help_builder].call(options)
|
102
|
+
elsif options[:calculated_path]
|
103
|
+
title = options[:title] || I18n.t(options[:calculated_path]+'.title')
|
104
|
+
text = options[:text] || I18n.t(options[:calculated_path]+'.text')
|
105
|
+
html = "<#{options[:title_tag]} id=\"#{options[:item_id]}\" class=\"#{options[:title_class]} #{options[:level_class]}\">#{title}</#{options[:title_tag]}>
|
106
|
+
<#{options[:text_tag]} class=\"#{options[:text_class]} #{options[:level_class]}\">#{text}</#{options[:text_tag]}>"
|
107
|
+
html += self.link_to_object(options)
|
108
|
+
html
|
109
|
+
end
|
110
|
+
end
|
111
|
+
def self.link_to_help(options)
|
112
|
+
if options[:link_to_help_builder].is_a?(Proc)
|
113
|
+
options[:link_to_help_builder].call(options)
|
114
|
+
elsif options[:link_to_help] and !I18n.t(options[:calculated_path]+'.title', :default => {}).is_a?(Hash)
|
115
|
+
"<a href=\"##{options[:item_id]}\" id=\"#{options[:item_id]}_object\" class=\"context_help_link_to_help\">help</a>"
|
116
|
+
else
|
117
|
+
''
|
118
|
+
end
|
119
|
+
end
|
120
|
+
def self.link_to_object(options)
|
121
|
+
if options[:link_to_object_builder].is_a?(Proc)
|
122
|
+
options[:link_to_object_builder].call(options)
|
123
|
+
elsif options[:link_to_object]
|
124
|
+
"<a href=\"#link_to_help_#{options[:item_id]}\">help</a>"
|
125
|
+
else
|
126
|
+
''
|
127
|
+
end
|
128
|
+
end
|
129
|
+
def self.register_item(options)
|
130
|
+
def self.get_option(name, options)
|
131
|
+
return @config[name] if options[:calculated_path].nil?
|
132
|
+
value = I18n.t(options[:calculated_path]+'.'+name.to_s, :default => {})
|
133
|
+
if value.is_a?(Hash)
|
134
|
+
@config[name]
|
135
|
+
else
|
136
|
+
value
|
137
|
+
end
|
138
|
+
end
|
139
|
+
found = false
|
140
|
+
@help_items.each do |item|
|
141
|
+
found = (item[:calculated_path] == options[:calculated_path])
|
142
|
+
break if found
|
143
|
+
end
|
144
|
+
if not found
|
145
|
+
options[:show_inline] ||= get_option(:show_inline, options)
|
146
|
+
options[:title_tag] ||= get_option(:title_tag, options)
|
147
|
+
options[:title_class] ||= get_option(:title_class, options)
|
148
|
+
options[:text_tag] ||= get_option(:text_tag, options)
|
149
|
+
options[:text_class] ||= get_option(:text_class, options)
|
150
|
+
options[:link_to_object] ||= get_option(:link_to_object, options)
|
151
|
+
options[:link_to_help] ||= get_option(:link_to_help, options)
|
152
|
+
options[:level_class] ||= I18n.t(options[:calculated_path]+'.level_class', :default => (options[:pre_level_class] || 'help_level_1'))
|
153
|
+
options[:link_to_help_builder] ||= @config[:link_to_help_builder]
|
154
|
+
options[:link_to_object_builder] ||= @config[:link_to_object_builder]
|
155
|
+
options[:inline_help_builder] ||= @config[:inline_help_builder]
|
156
|
+
options[:help_builder] ||= @config[:help_builder]
|
157
|
+
|
158
|
+
options[:item_id] = "context_help_item_#{(@help_items.length+1).to_s}"
|
159
|
+
@help_items << options
|
160
|
+
end
|
161
|
+
end
|
162
|
+
def self.model_name(model)
|
163
|
+
model = model.to_s.underscore
|
164
|
+
if model =~ /^[a-z][a-z0-9_]*\[[a-z][a-z0-9_]*_attributes\]/
|
165
|
+
model.match(/^[a-z][a-z0-9_]*\[([a-z][a-z0-9_]*)_attributes\]/)[1].singularize
|
166
|
+
else
|
167
|
+
model
|
168
|
+
end
|
169
|
+
end
|
170
|
+
def self.merge_options(base, added)
|
171
|
+
if base.is_a?(Hash) and added.is_a?(Hash)
|
172
|
+
added.each do |key,value|
|
173
|
+
base[key] = self.merge_options(base[key], value)
|
174
|
+
end
|
175
|
+
return base
|
176
|
+
else
|
177
|
+
return base || added
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module FormHelper
|
4
|
+
def fields_for_with_context_help_fields_for(record_or_name_or_array, *args, &block)
|
5
|
+
case record_or_name_or_array
|
6
|
+
when String, Symbol
|
7
|
+
object_name = record_or_name_or_array
|
8
|
+
else
|
9
|
+
object_name = ActionController::RecordIdentifier.singular_class_name(record_or_name_or_array)
|
10
|
+
end
|
11
|
+
|
12
|
+
options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym} } }, args.last.is_a?(::Hash)? args.last : {})
|
13
|
+
help = ContextHelp::Base.help_for(options)
|
14
|
+
help + fields_for_without_context_help_fields_for(record_or_name_or_array, *args, &block)
|
15
|
+
end
|
16
|
+
def label_with_context_help_label(object_name, method, text = nil, options = {})
|
17
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
18
|
+
ContextHelp::Base.help_for(help_options)
|
19
|
+
link_to_help = ContextHelp::Base.link_to_help(help_options[:context_help])
|
20
|
+
label_without_context_help_label(object_name, method, text.to_s + link_to_help, options)
|
21
|
+
end
|
22
|
+
def text_field_with_context_help_text_field(object_name, method, options = {})
|
23
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
24
|
+
help = ContextHelp::Base.help_for(help_options)
|
25
|
+
text_field_without_context_help_text_field(object_name, method, options) + help
|
26
|
+
end
|
27
|
+
def password_field_with_context_help_password_field(object_name, method, options = {})
|
28
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
29
|
+
help = ContextHelp::Base.help_for(help_options)
|
30
|
+
password_field_without_context_help_password_field(object_name, method, options) + help
|
31
|
+
end
|
32
|
+
def hidden_field_with_context_help_hidden_field(object_name, method, options = {})
|
33
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
34
|
+
help = ContextHelp::Base.help_for(help_options)
|
35
|
+
hidden_field_without_context_help_hidden_field(object_name, method, options) + help
|
36
|
+
end
|
37
|
+
def file_field_with_context_help_file_field(object_name, method, options = {})
|
38
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
39
|
+
help = ContextHelp::Base.help_for(help_options)
|
40
|
+
file_field_without_context_help_file_field(object_name, method, options) + help
|
41
|
+
end
|
42
|
+
def text_area_with_context_help_text_area(object_name, method, options = {})
|
43
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
44
|
+
help = ContextHelp::Base.help_for(help_options)
|
45
|
+
text_area_without_context_help_text_area(object_name, method, options) + help
|
46
|
+
end
|
47
|
+
def check_box_with_context_help_check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
|
48
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
49
|
+
help = ContextHelp::Base.help_for(help_options)
|
50
|
+
check_box_without_context_help_check_box(object_name, method, options, checked_value, unchecked_value) + help
|
51
|
+
end
|
52
|
+
def radio_button_with_context_help_radio_button(object_name, method, tag_value, options = {})
|
53
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => object_name.to_sym, :attribute=> method.to_sym}}}, options)
|
54
|
+
help = ContextHelp::Base.help_for(help_options)
|
55
|
+
radio_button_without_context_help_radio_button(object_name, method, tag_value, options) +help
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method_chain :fields_for, :context_help_fields_for
|
59
|
+
alias_method_chain :label, :context_help_label
|
60
|
+
alias_method_chain :text_field, :context_help_text_field
|
61
|
+
alias_method_chain :password_field, :context_help_password_field
|
62
|
+
alias_method_chain :hidden_field, :context_help_hidden_field
|
63
|
+
alias_method_chain :file_field, :context_help_file_field
|
64
|
+
alias_method_chain :text_area, :context_help_text_area
|
65
|
+
alias_method_chain :check_box, :context_help_check_box
|
66
|
+
alias_method_chain :radio_button, :context_help_radio_button
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ContextHelp
|
2
|
+
class SemanticFormBuilder < Formtastic::SemanticFormBuilder
|
3
|
+
def inputs(*args, &block)
|
4
|
+
title = field_set_title_from_args(*args)
|
5
|
+
html_options = args.extract_options!
|
6
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:tag => 'fieldset', :tag_options => html_options}}}, html_options)
|
7
|
+
help_options[:context_help][:title] = title if help_options[:context_help][:path][:tag]
|
8
|
+
help = ContextHelp::Base.help_for(help_options)
|
9
|
+
super *(args<<help_options), &block
|
10
|
+
end
|
11
|
+
def input(method, options = {})
|
12
|
+
options = ContextHelp::Base.merge_options({:context_help => {:path => {:model => model_name.to_sym, :attribute=> method.to_sym}}}, options || {})
|
13
|
+
html = super
|
14
|
+
end
|
15
|
+
def legend_tag(method, options = {})
|
16
|
+
if options[:label] == false
|
17
|
+
Formtastic::Util.html_safe("")
|
18
|
+
else
|
19
|
+
text = localized_string(method, options[:label], :label) || humanized_attribute_name(method)
|
20
|
+
text += required_or_optional_string(options.delete(:required))
|
21
|
+
text = Formtastic::Util.html_safe(text)
|
22
|
+
text += ContextHelp::Base.link_to_help(options[:context_help])
|
23
|
+
template.content_tag :legend, template.label_tag(nil, text, :for => nil), :class => :label
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module TagHelper
|
4
|
+
def tag_with_context_help_tag(name, options = {}, open = false, escape = true)
|
5
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:tag => name.to_sym, :tag_options => options}}}, options)
|
6
|
+
help = ContextHelp::Base.help_for(help_options)
|
7
|
+
tag_without_context_help_tag(name, options, open, escape) + help
|
8
|
+
end
|
9
|
+
def content_tag_with_context_help_content_tag(name, content_or_options_with_block = nil, options = {}, escape = true, &block)
|
10
|
+
help_options = ContextHelp::Base.merge_options({:context_help => {:path => {:tag => name.to_sym, :tag_options => options}}}, options)
|
11
|
+
help = ContextHelp::Base.help_for(help_options)
|
12
|
+
html = content_tag_without_context_help_content_tag(name, content_or_options_with_block, options, escape, &block) + help
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method_chain :tag, :context_help_tag
|
16
|
+
alias_method_chain :content_tag, :context_help_content_tag
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/context_help.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'context_help/patches/tag_helper_patch'
|
2
|
+
require 'context_help/patches/form_helper_patch'
|
3
|
+
require 'context_help/patches/formtastic_patch'
|
4
|
+
require "context_help/version"
|
5
|
+
require 'context_help/base'
|
6
|
+
|
7
|
+
Formtastic::SemanticFormHelper.builder = ContextHelp::SemanticFormBuilder if defined?(Formtastic)
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: context_help
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Juan Pablo Marzetti
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-10 00:00:00.000000000 -03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
description: ContextHelp is a gem that allows you to show inline or aside help about
|
16
|
+
every input item found in a form tag, a model, its attributes and even custom help
|
17
|
+
about other HTML tags
|
18
|
+
email:
|
19
|
+
- jmarzetti@sequre.com.ar
|
20
|
+
executables: []
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- .gitignore
|
25
|
+
- Gemfile
|
26
|
+
- README.rdoc
|
27
|
+
- Rakefile
|
28
|
+
- context_help.gemspec
|
29
|
+
- lib/context_help.rb
|
30
|
+
- lib/context_help/base.rb
|
31
|
+
- lib/context_help/patches/form_helper_patch.rb
|
32
|
+
- lib/context_help/patches/formtastic_patch.rb
|
33
|
+
- lib/context_help/patches/tag_helper_patch.rb
|
34
|
+
- lib/context_help/version.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://sequre.com.ar
|
37
|
+
licenses: []
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project: context_help
|
56
|
+
rubygems_version: 1.6.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: A Rails context help facility to offer help about yor models and attributes
|
60
|
+
test_files: []
|