zena 1.2.1 → 1.2.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/History.txt +38 -1
- data/app/controllers/documents_controller.rb +7 -5
- data/app/controllers/nodes_controller.rb +47 -6
- data/app/controllers/user_sessions_controller.rb +12 -3
- data/app/controllers/virtual_classes_controller.rb +8 -2
- data/app/models/acl.rb +5 -2
- data/app/models/cached_page.rb +5 -5
- data/app/models/column.rb +27 -4
- data/app/models/group.rb +1 -1
- data/app/models/node.rb +106 -24
- data/app/models/note.rb +2 -1
- data/app/models/relation.rb +9 -4
- data/app/models/relation_proxy.rb +2 -2
- data/app/models/role.rb +12 -5
- data/app/models/site.rb +10 -9
- data/app/models/skin.rb +8 -0
- data/app/models/string_hash.rb +65 -0
- data/app/models/text_document.rb +1 -1
- data/app/models/user.rb +2 -0
- data/app/models/virtual_class.rb +43 -10
- data/app/views/comments/create.rjs +1 -32
- data/app/views/comments/edit.rjs +1 -1
- data/app/views/comments/update.rjs +1 -1
- data/app/views/documents/show.rhtml +1 -1
- data/app/views/groups/_form.rhtml +7 -0
- data/app/views/groups/_li.rhtml +1 -1
- data/app/views/nodes/500.html +2 -1
- data/app/views/nodes/destroy.rjs +2 -0
- data/app/views/sites/jobs.erb +2 -3
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_import.rhtml +4 -1
- data/app/views/templates/document_create_tabs/_template.rhtml +3 -0
- data/app/views/templates/document_create_tabs/_text_document.rhtml +3 -0
- data/app/views/versions/custom_tab.rhtml +1 -1
- data/app/views/versions/edit.rhtml +1 -1
- data/bricks/acls/lib/bricks/acls.rb +3 -3
- data/bricks/acls/zena/test/unit/acl_test.rb +15 -0
- data/bricks/fs_skin/lib/bricks/fs_skin.rb +190 -0
- data/bricks/fs_skin/zena/init.rb +1 -0
- data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +12 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image-edit.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+index.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+notFound.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+search.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node.zafu +1 -1
- data/bricks/{static → fs_skin}/zena/skins/blog/Post.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project--kml.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/comments.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/dict.yml +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/dateBg.jpg +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/header.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/mapPin.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menu.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menuover.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/style.css +0 -0
- data/bricks/fs_skin/zena/tasks.rb +26 -0
- data/bricks/{static/zena/test/integration/static_integration_test.rb → fs_skin/zena/test/integration/fs_skin_integration_test.rb} +6 -6
- data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +33 -0
- data/bricks/grid/lib/bricks/grid.rb +4 -3
- data/bricks/tags/lib/bricks/tags.rb +1 -7
- data/bricks/zena/zena/migrate/20120605091558_add_ssl_login_to_site.rb +7 -0
- data/bricks/zena/zena/migrate/20120630123551_add_auto_publish_to_group.rb +9 -0
- data/config/bricks.yml +3 -3
- data/config/gems.yml +2 -3
- data/lib/tasks/zena.rake +7 -3
- data/lib/zafu.rb +7 -0
- data/lib/zafu/all.rb +21 -0
- data/lib/zafu/compiler.rb +7 -0
- data/lib/zafu/controller_methods.rb +58 -0
- data/lib/zafu/handler.rb +57 -0
- data/lib/zafu/info.rb +4 -0
- data/lib/zafu/markup.rb +309 -0
- data/lib/zafu/mock_helper.rb +42 -0
- data/lib/zafu/node_context.rb +203 -0
- data/lib/zafu/ordered_hash.rb +53 -0
- data/lib/zafu/parser.rb +676 -0
- data/lib/zafu/parsing_rules.rb +382 -0
- data/lib/zafu/process/ajax.rb +530 -0
- data/lib/zafu/process/conditional.rb +92 -0
- data/lib/zafu/process/context.rb +186 -0
- data/lib/zafu/process/forms.rb +143 -0
- data/lib/zafu/process/html.rb +186 -0
- data/lib/zafu/process/ruby_less_processing.rb +321 -0
- data/lib/zafu/security.rb +15 -0
- data/lib/zafu/template.rb +25 -0
- data/lib/zafu/test_helper.rb +19 -0
- data/lib/zafu/view_methods.rb +6 -0
- data/lib/zena.rb +1 -1
- data/lib/zena/acts/enrollable.rb +1 -1
- data/lib/zena/app.rb +4 -17
- data/lib/zena/console.rb +18 -1
- data/lib/zena/core_ext/file_utils.rb +13 -1
- data/lib/zena/core_ext/fixnum.rb +4 -0
- data/lib/zena/core_ext/float.rb +7 -0
- data/lib/zena/deploy.rb +4 -2
- data/lib/zena/deploy/app_init.rhtml +2 -1
- data/lib/zena/deploy/database.rhtml +1 -1
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zazen_rules.rb +4 -4
- data/lib/zena/routes.rb +1 -1
- data/lib/zena/test_controller.rb +1 -1
- data/lib/zena/use.rb +14 -1
- data/lib/zena/use/action.rb +4 -2
- data/lib/zena/use/ajax.rb +86 -38
- data/lib/zena/use/authlogic.rb +16 -1
- data/lib/zena/use/calendar.rb +37 -17
- data/lib/zena/use/conditional.rb +2 -2
- data/lib/zena/use/context.rb +30 -9
- data/lib/zena/use/dates.rb +39 -3
- data/lib/zena/use/display.rb +6 -19
- data/lib/zena/use/forms.rb +100 -79
- data/lib/zena/use/i18n.rb +40 -16
- data/lib/zena/use/query_builder.rb +0 -6
- data/lib/zena/use/query_node.rb +17 -4
- data/lib/zena/use/relations.rb +1 -3
- data/lib/zena/use/rendering.rb +10 -8
- data/lib/zena/use/scope_index.rb +5 -1
- data/lib/zena/use/search.rb +2 -1
- data/lib/zena/use/urls.rb +82 -77
- data/lib/zena/use/workflow.rb +12 -4
- data/lib/zena/use/zafu_safe_definitions.rb +37 -9
- data/lib/zena/use/zafu_templates.rb +49 -20
- data/lib/zena/use/zazen.rb +6 -2
- data/locale/it/LC_MESSAGES/zena.mo +0 -0
- data/locale/it/zena.mo +0 -0
- data/locale/it/zena.po +1982 -0
- data/public/images/arrow_back.png +0 -0
- data/public/images/remove_tag.png +0 -0
- data/public/javascripts/grid.js +800 -199
- data/public/javascripts/window.js +1 -1
- data/public/javascripts/zena.js +130 -21
- data/public/stylesheets/grid.css +11 -2
- data/public/stylesheets/zena.css +2 -1
- data/test/custom_queries/complex.host.yml +5 -0
- data/test/fixtures/files/TestNode.zafu +36 -0
- data/test/functional/nodes_controller_test.rb +18 -1
- data/test/integration/zafu_compiler/action.yml +2 -2
- data/test/integration/zafu_compiler/ajax.yml +44 -26
- data/test/integration/zafu_compiler/asset.yml +12 -2
- data/test/integration/zafu_compiler/basic.yml +0 -16
- data/test/integration/zafu_compiler/calendar.yml +6 -6
- data/test/integration/zafu_compiler/complex_ok.yml +23 -1
- data/test/integration/zafu_compiler/conditional.yml +5 -5
- data/test/integration/zafu_compiler/context.yml +6 -5
- data/test/integration/zafu_compiler/dates.yml +23 -2
- data/test/integration/zafu_compiler/display.yml +46 -2
- data/test/integration/zafu_compiler/errors.yml +2 -2
- data/test/integration/zafu_compiler/eval.yml +35 -7
- data/test/integration/zafu_compiler/forms.yml +47 -13
- data/test/integration/zafu_compiler/i18n.yml +2 -2
- data/test/integration/zafu_compiler/meta.yml +35 -1
- data/test/integration/zafu_compiler/query.yml +23 -4
- data/test/integration/zafu_compiler/relations.yml +10 -6
- data/test/integration/zafu_compiler/roles.yml +4 -4
- data/test/integration/zafu_compiler/rubyless.yml +11 -1
- data/test/integration/zafu_compiler/safe_definitions.yml +23 -5
- data/test/integration/zafu_compiler/security.yml +10 -6
- data/test/integration/zafu_compiler/urls.yml +23 -6
- data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
- data/test/integration/zafu_compiler/zazen.yml +14 -0
- data/test/selenium/Add/add3.rsel +8 -8
- data/test/selenium/Destroy/0setup.rsel +12 -0
- data/test/selenium/Destroy/destroy1.rsel +16 -0
- data/test/selenium/Edit/edit2.rsel +9 -9
- data/test/selenium/Edit/edit5.rsel +9 -9
- data/test/selenium/Edit/edit6.rsel +9 -9
- data/test/selenium/Form/form4.rsel +17 -0
- data/test/selenium/Toggle/toggle1.rsel +2 -0
- data/test/selenium/Toggle/toggle2.rsel +18 -0
- data/test/sites/zena/columns.yml +3 -0
- data/test/sites/zena/versions.yml +7 -0
- data/test/unit/cached_page_test.rb +13 -13
- data/test/unit/column_test.rb +26 -0
- data/test/unit/node_test.rb +16 -1
- data/test/unit/project_test.rb +6 -1
- data/test/unit/relation_test.rb +1 -1
- data/test/unit/role_test.rb +1 -1
- data/test/unit/string_hash_test.rb +30 -0
- data/test/unit/virtual_class_test.rb +31 -17
- data/test/unit/zafu_markup_test.rb +414 -0
- data/test/unit/zafu_node_context_test.rb +375 -0
- data/test/unit/zafu_ordered_hash_test.rb +69 -0
- data/test/unit/zena/acts/enrollable_test.rb +1 -1
- data/test/unit/zena/parser/zafu_asset.yml +0 -10
- data/test/unit/zena/parser/zazen.yml +1 -1
- data/test/unit/zena/parser_test.rb +1 -72
- data/test/unit/zena/use/dates_test.rb +1 -1
- data/test/unit/zena/use/rendering_test.rb +24 -7
- data/test/unit/zena/use/scope_index_test.rb +17 -0
- data/test/unit/zena/use/zazen_test.rb +2 -1
- data/zena.gemspec +71 -37
- metadata +104 -83
- data/app/views/nodes/destroy.erb +0 -0
- data/bricks/static/lib/bricks/static.rb +0 -151
- data/bricks/static/zena/init.rb +0 -1
- data/bricks/static/zena/migrate/20110702010330_add_static_to_idx_templates.rb +0 -12
- data/bricks/static/zena/test/unit/static_test.rb +0 -33
- data/lib/zena/parser/zafu_rules.rb +0 -244
- data/lib/zena/parser/zafu_tags.rb +0 -198
- data/lib/zena/parser/zena_rules.rb +0 -23
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Zafu
|
|
2
|
+
module Process
|
|
3
|
+
# This module manages conditional rendering (if, else, elsif, case, when).
|
|
4
|
+
module Conditional
|
|
5
|
+
def r_if(cond = nil)
|
|
6
|
+
cond ||= get_condition
|
|
7
|
+
return unless cond
|
|
8
|
+
expand_if(cond)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def r_case
|
|
12
|
+
r_if('false')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def r_else
|
|
16
|
+
r_elsif('true')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def r_when
|
|
20
|
+
r_elsif
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def r_elsif(cond = nil)
|
|
24
|
+
return '' unless @context[:in_if]
|
|
25
|
+
cond ||= get_condition
|
|
26
|
+
return unless cond
|
|
27
|
+
|
|
28
|
+
res = expand_with(:in_if => false, :markup => nil)
|
|
29
|
+
|
|
30
|
+
# We use 'elsif' just in case there are more then one 'else' clause
|
|
31
|
+
if markup = @context[:markup]
|
|
32
|
+
if @markup.tag.blank?
|
|
33
|
+
# Copy markup tag
|
|
34
|
+
@markup.tag = markup.tag
|
|
35
|
+
@markup.steal_html_params_from(@params)
|
|
36
|
+
markup.params.each do |k, v|
|
|
37
|
+
next if @markup.params[k]
|
|
38
|
+
@markup.set_param(k, v)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
markup.dyn_params.each do |k, v|
|
|
42
|
+
next if @markup.params[k] || @markup.dyn_params[k]
|
|
43
|
+
@markup.set_dyn_param(k, v)
|
|
44
|
+
end
|
|
45
|
+
inner = wrap(res)
|
|
46
|
+
else
|
|
47
|
+
markup.done = false
|
|
48
|
+
# Wrap with both markup (ours and the else/elsif clause).
|
|
49
|
+
inner = markup.wrap(wrap(res))
|
|
50
|
+
end
|
|
51
|
+
out "<% elsif #{cond} %>#{inner}" # do not propagate
|
|
52
|
+
else
|
|
53
|
+
#@markup.done = true # never wrap else/elsif clause
|
|
54
|
+
out "<% elsif #{cond} %>#{res}" # do not propagate
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Expand blocks with conditional processing enabled (else, elsif, etc).
|
|
59
|
+
#
|
|
60
|
+
# ==== Parameters
|
|
61
|
+
#
|
|
62
|
+
# * +condition+ - ruby condition for the conditional execution.
|
|
63
|
+
# * +new_node_context+ - (optional) new node context to enter if the clause succeeds.
|
|
64
|
+
# * +alt_markup+ - (optional) alternative markup to use for the 'else', 'elsif' clauses.
|
|
65
|
+
def expand_if(condition, new_node_context = self.node, alt_markup = @markup)
|
|
66
|
+
res = ""
|
|
67
|
+
res << "<% if #{condition} %>"
|
|
68
|
+
with_context(:node => new_node_context) do
|
|
69
|
+
res << wrap(expand_with)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
only = method == 'case' ? %r{^[A-Z]|else|elsif|when} : %w{else elsif when}
|
|
73
|
+
res << expand_with(:in_if => true, :only => only, :markup => alt_markup)
|
|
74
|
+
res << "<% end %>"
|
|
75
|
+
res
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
def get_condition
|
|
80
|
+
if in_tag = @params[:in]
|
|
81
|
+
if in_tag == 'form' && @context[:make_form]
|
|
82
|
+
'true'
|
|
83
|
+
else
|
|
84
|
+
ancestor(in_tag) ? 'true' : 'false'
|
|
85
|
+
end
|
|
86
|
+
else
|
|
87
|
+
get_attribute_or_eval(false)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end # Context
|
|
91
|
+
end # Process
|
|
92
|
+
end # Zafu
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
module Zafu
|
|
2
|
+
module Process
|
|
3
|
+
# This module manages the change of contexts by opening (each) or moving into the NodeContext.
|
|
4
|
+
# The '@context' holds many information on the current compilation environment. Inside this
|
|
5
|
+
# context, the "node" context holds information on the type of "this" (first responder).
|
|
6
|
+
module Context
|
|
7
|
+
def r_each
|
|
8
|
+
if node.list_context?
|
|
9
|
+
if @params[:alt_class] || @params[:join]
|
|
10
|
+
out "<% #{var}_max_index = #{node}.size - 1 %>" if @params[:alt_reverse]
|
|
11
|
+
out "<% #{node}.each_with_index do |#{var},#{var}_index| %>"
|
|
12
|
+
|
|
13
|
+
if join = @params[:join]
|
|
14
|
+
join = RubyLess.translate_string(self, join)
|
|
15
|
+
out "<%= #{var}_index > 0 ? #{join} : '' %>"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if alt_class = @params[:alt_class]
|
|
19
|
+
alt_class = RubyLess.translate_string(self, alt_class)
|
|
20
|
+
alt_test = @params[:alt_reverse] == 'true' ? "(#{var}_max_index - #{var}_index) % 2 != 0" : "#{var}_index % 2 != 0"
|
|
21
|
+
|
|
22
|
+
alt_var = get_var_name('set_var', 'alt_class')
|
|
23
|
+
set_context_var('set_var', 'alt_class', RubyLess::TypedString.new(alt_var, :class => String))
|
|
24
|
+
out "<% #{alt_var} = #{alt_test} ? #{alt_class} : '' %>"
|
|
25
|
+
|
|
26
|
+
if @markup.tag
|
|
27
|
+
@markup.append_dyn_param(:class, "<%= #{alt_var} %>")
|
|
28
|
+
else
|
|
29
|
+
# Just declare 'alt_class'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
else
|
|
33
|
+
out "<% #{node}.each do |#{var}| %>"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
raw_dom_prefix = node.raw_dom_prefix
|
|
37
|
+
|
|
38
|
+
with_context(:node => node.move_to(var, node.klass.first, :query => node.opts[:query])) do
|
|
39
|
+
# We pass the :query option for RubyLess resolution by using the QueryBuilder finder
|
|
40
|
+
|
|
41
|
+
steal_and_eval_html_params_for(@markup, @params)
|
|
42
|
+
# The id set here should be used as prefix for sub-nodes to ensure uniqueness of generated DOM ids
|
|
43
|
+
if node.list_context?
|
|
44
|
+
# we are still in a list (example: previous context was [[Node]], current is [Node])
|
|
45
|
+
else
|
|
46
|
+
# Change dom_prefix if it isn't our own (inherited).
|
|
47
|
+
node.dom_prefix = dom_name unless raw_dom_prefix
|
|
48
|
+
node.propagate_dom_scope!
|
|
49
|
+
|
|
50
|
+
if need_dom_id?
|
|
51
|
+
@markup.set_id(node.dom_id)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
out wrap(expand_with)
|
|
56
|
+
end
|
|
57
|
+
out "<% end %>"
|
|
58
|
+
else
|
|
59
|
+
out expand_with
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# We need to return true for Ajax 'make_form'
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def helper
|
|
67
|
+
@context[:helper]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Return true if we need to insert the dom id for this element. This method is overwritten in Ajax.
|
|
71
|
+
def need_dom_id?
|
|
72
|
+
false
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Return the node context for a given class (looks up into the hierarchy) or the
|
|
76
|
+
# current node context if klass is nil.
|
|
77
|
+
def node(klass = nil)
|
|
78
|
+
return @context[:node] if !klass
|
|
79
|
+
@context[:node].get(klass)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Store some contextual value / variable inside a named group. This should be
|
|
83
|
+
# used to avoid key clashes between different types of elements to store.
|
|
84
|
+
def set_context_var(group, key, obj, context = @context)
|
|
85
|
+
context["#{group}::#{key}"] = obj
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Retrieve a value from a given contextual group. The value must have been
|
|
89
|
+
# previously set with 'set_context_var' somewhere in the hierarchy.
|
|
90
|
+
def get_context_var(group, key, context = @context)
|
|
91
|
+
context["#{group}::#{key}"]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Return a new context without contextual variables.
|
|
95
|
+
def context_without_vars
|
|
96
|
+
context = @context.dup
|
|
97
|
+
context.keys.each do |k|
|
|
98
|
+
context.delete(k) if k.kind_of?(String)
|
|
99
|
+
end
|
|
100
|
+
context
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Expand blocks in a new context.
|
|
104
|
+
# This method is partly overwriten in Ajax
|
|
105
|
+
def expand_with_finder(finder)
|
|
106
|
+
if finder[:nil]
|
|
107
|
+
open_node_context(finder, :form => nil) do # do not propagate :form
|
|
108
|
+
expand_if("#{var} = #{finder[:method]}", node.move_to(var, finder[:class], finder.merge(:nil => false)))
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
res = ''
|
|
112
|
+
res << "<% #{var} = #{finder[:method]} %>"
|
|
113
|
+
open_node_context(finder, :node => node.move_to(var, finder[:class], finder), :form => nil) do
|
|
114
|
+
res << wrap(expand_with)
|
|
115
|
+
end
|
|
116
|
+
res
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# def context_with_node(name, klass)
|
|
121
|
+
# context = @context.dup
|
|
122
|
+
# context[:node] = context[:node].move_to(name, klass)
|
|
123
|
+
# end
|
|
124
|
+
|
|
125
|
+
def var
|
|
126
|
+
return @var if @var
|
|
127
|
+
if node.name =~ /^var(\d+)$/
|
|
128
|
+
@var = "var#{$1.to_i + 1}"
|
|
129
|
+
else
|
|
130
|
+
@var = "var1"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# This method is called when we enter a new node context
|
|
135
|
+
def node_context_vars(finder)
|
|
136
|
+
# do nothing (this is a hook for other modules like QueryBuilder and RubyLess)
|
|
137
|
+
{}
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Get a variable name and store the name in context variables for the given group.
|
|
141
|
+
#
|
|
142
|
+
# ==== Parameters
|
|
143
|
+
#
|
|
144
|
+
# * +group_name+ - name of the variable context group
|
|
145
|
+
# * +wanted_name+ - wanted variable name (used as key to get real var back later with #get_context_var)
|
|
146
|
+
# * +context+ - (optional) can be used if we do not want to store the variable definition in the current context
|
|
147
|
+
#
|
|
148
|
+
def get_var_name(group_name, wanted_name, context = @context)
|
|
149
|
+
secure_name = wanted_name.gsub(/[^a-zA-Z0-9]/,'')
|
|
150
|
+
name = "_z#{secure_name}"
|
|
151
|
+
i = 0
|
|
152
|
+
while get_context_var('var', name, context)
|
|
153
|
+
i += 1
|
|
154
|
+
name = "_z#{secure_name}#{i}"
|
|
155
|
+
end
|
|
156
|
+
set_context_var('var', name, true)
|
|
157
|
+
set_context_var(group_name, wanted_name, name)
|
|
158
|
+
name
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Change context for a given scope.
|
|
162
|
+
def with_context(cont, merge = true)
|
|
163
|
+
raise "Block missing" unless block_given?
|
|
164
|
+
cont_bak = @context
|
|
165
|
+
if merge
|
|
166
|
+
@context = @context.merge(cont)
|
|
167
|
+
else
|
|
168
|
+
@context = cont
|
|
169
|
+
end
|
|
170
|
+
res = yield
|
|
171
|
+
@context = cont_bak
|
|
172
|
+
res
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# This should be called when we enter a new node context so that the proper hooks are
|
|
176
|
+
# triggered (insertion of contextual variables).
|
|
177
|
+
def open_node_context(finder, cont = {})
|
|
178
|
+
sub_context = node_context_vars(finder).merge(cont)
|
|
179
|
+
|
|
180
|
+
with_context(sub_context) do
|
|
181
|
+
yield
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end # Context
|
|
185
|
+
end # Process
|
|
186
|
+
end # Zafu
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module Zafu
|
|
2
|
+
module Process
|
|
3
|
+
module Forms
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.expander :make_form
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def r_form
|
|
9
|
+
if node.dom_prefix
|
|
10
|
+
fnode = node
|
|
11
|
+
else
|
|
12
|
+
fnode = node.dup
|
|
13
|
+
fnode.dom_prefix = dom_name
|
|
14
|
+
end
|
|
15
|
+
with_context(:node => fnode) do
|
|
16
|
+
|
|
17
|
+
unless @params[:on].nil? || @params[:on].split(',').include?(@context[:ajax_action])
|
|
18
|
+
return ''
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
return parser_error('Cannot render update form in list context.') if node.list_context?
|
|
22
|
+
|
|
23
|
+
options = form_options
|
|
24
|
+
|
|
25
|
+
@markup.set_id(options[:id]) if options[:id]
|
|
26
|
+
@markup.set_param(:style, options[:style]) if options[:style]
|
|
27
|
+
|
|
28
|
+
if descendant('form_tag')
|
|
29
|
+
# We have a specific place to insert our form
|
|
30
|
+
out expand_with(:form_options => options, :form => self)
|
|
31
|
+
else
|
|
32
|
+
r_form_tag(options)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def r_form_tag(options = @context[:form_options])
|
|
38
|
+
form_tag(options) do |opts|
|
|
39
|
+
# Render error messages tag
|
|
40
|
+
form_error_messages(opts[:form_helper])
|
|
41
|
+
|
|
42
|
+
# Render form elements
|
|
43
|
+
out expand_with(opts)
|
|
44
|
+
|
|
45
|
+
# Render hidden fields (these must go after normal elements so that focusFirstElement works)
|
|
46
|
+
hidden_fields = form_hidden_fields(options)
|
|
47
|
+
|
|
48
|
+
out "<div class='hidden'>"
|
|
49
|
+
hidden_fields.each do |k,v|
|
|
50
|
+
if v.kind_of?(String)
|
|
51
|
+
v = "'#{v}'" unless v.kind_of?(String) && ['"', "'"].include?(v[0..0])
|
|
52
|
+
out "<input type='hidden' name='#{k}' value=#{v}/>"
|
|
53
|
+
elsif v.kind_of?(Array)
|
|
54
|
+
# We use ['ffff'] to indicate that the content is already escaped and ready for ERB.
|
|
55
|
+
out v.first
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
out '</div>'
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
def make_form
|
|
64
|
+
return nil unless @context[:make_form]
|
|
65
|
+
|
|
66
|
+
if method == 'each' || method == 'block'
|
|
67
|
+
r_form
|
|
68
|
+
else
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Return id, style, form and cancel parts of the form.
|
|
74
|
+
def form_options
|
|
75
|
+
opts = {}
|
|
76
|
+
|
|
77
|
+
# Do we need this ?
|
|
78
|
+
# opts[:klass] = node.master_class(ActiveRecord::Base).to_s
|
|
79
|
+
|
|
80
|
+
if @context[:in_add]
|
|
81
|
+
opts[:id] = "#{node.dom_prefix}_add"
|
|
82
|
+
opts[:style] = 'display:none;'
|
|
83
|
+
elsif @markup.tag == 'table'
|
|
84
|
+
# the normal id goes to the form wrapping the table
|
|
85
|
+
opts[:id] = "#{node.dom_prefix}_tbl"
|
|
86
|
+
form_id = node.dom_prefix
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
form_id ||= "#{node.dom_prefix}_form_t"
|
|
90
|
+
if @context[:template_url]
|
|
91
|
+
opts[:form_tag] = "<% remote_form_for(:#{node.form_name}, #{node}, :html => {:id => #{form_id.inspect}}) do |f| %>"
|
|
92
|
+
opts[:form_helper] = 'f'
|
|
93
|
+
else
|
|
94
|
+
opts[:form_tag] = "<% form_for(:#{node.form_name}, #{node}, :html => {:id => #{form_id.inspect}}) do |f| %>"
|
|
95
|
+
opts[:form_helper] = 'f'
|
|
96
|
+
end
|
|
97
|
+
opts[:form_prefix] = node.dom_prefix || dom_name
|
|
98
|
+
opts
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Return hidden fields that need to be inserted in the form.
|
|
102
|
+
def form_hidden_fields(opts)
|
|
103
|
+
if t_url = @context[:template_url]
|
|
104
|
+
{'t_url' => t_url}
|
|
105
|
+
else
|
|
106
|
+
{}
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Render the 'form' tag and set expansion context.
|
|
111
|
+
def form_tag(options)
|
|
112
|
+
opts = options.dup
|
|
113
|
+
|
|
114
|
+
if descendant('cancel') || descendant('edit')
|
|
115
|
+
# Pass 'form_cancel' content to expand_with (already in options).
|
|
116
|
+
else
|
|
117
|
+
# Insert cancel before form
|
|
118
|
+
out opts.delete(:form_cancel).to_s
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# form_for ... do |f|
|
|
122
|
+
out opts.delete(:form_tag)
|
|
123
|
+
# f.xxx
|
|
124
|
+
if markup.tag == 'table'
|
|
125
|
+
# Avoid <table><form> (invalid HTML)
|
|
126
|
+
bak = @result
|
|
127
|
+
@result = ''
|
|
128
|
+
yield(opts.merge(:in_form => true))
|
|
129
|
+
@result = bak + markup.wrap(@result)
|
|
130
|
+
else
|
|
131
|
+
yield(opts.merge(:in_form => true))
|
|
132
|
+
end
|
|
133
|
+
# close form
|
|
134
|
+
out opts[:form_helper] ? "<% end %>" : '</form>'
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def form_error_messages(f)
|
|
138
|
+
out "<%= #{f}.error_messages %>"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end # Forms
|
|
142
|
+
end # Process
|
|
143
|
+
end # Zafu
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
module Zafu
|
|
2
|
+
module Process
|
|
3
|
+
module HTML
|
|
4
|
+
SAFE_SRC_REGEX = %r{\A/[^\.]+\.[a-zA-Z]+\Z}
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.wrap :wrap_html
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Replace the 'original' element in the included template with our new version.
|
|
10
|
+
def replace_with(new_obj)
|
|
11
|
+
super
|
|
12
|
+
# [self = original_element]. Replace @markup with content of the new_obj (<ul do='with'>...)
|
|
13
|
+
if new_obj.markup.tag
|
|
14
|
+
@markup.tag = new_obj.markup.tag
|
|
15
|
+
else
|
|
16
|
+
# Steal 'class' param
|
|
17
|
+
@markup.steal_html_params_from(new_obj.params)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@markup.params.merge!(new_obj.markup.params)
|
|
21
|
+
|
|
22
|
+
# We do not have to merge dyn_params since these are compiled before processing (and we are in
|
|
23
|
+
# the pre-processor)
|
|
24
|
+
|
|
25
|
+
if new_obj.params[:method]
|
|
26
|
+
@method = new_obj.params[:method]
|
|
27
|
+
elsif new_obj.sub_do
|
|
28
|
+
@method = 'void'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Pass the caller's 'markup' to the included part.
|
|
33
|
+
def include_part(obj)
|
|
34
|
+
if @markup.tag
|
|
35
|
+
obj.markup = @markup.dup
|
|
36
|
+
end
|
|
37
|
+
@markup.tag = nil
|
|
38
|
+
|
|
39
|
+
if sub_do
|
|
40
|
+
obj.method = @blocks.first.method
|
|
41
|
+
obj.params = @blocks.first.params
|
|
42
|
+
elsif params[:method]
|
|
43
|
+
obj.method = params[:method]
|
|
44
|
+
end
|
|
45
|
+
super(obj)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def empty?
|
|
49
|
+
super && @markup.params == {} && @markup.tag.nil?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def compile_html_params
|
|
53
|
+
return if @markup.done
|
|
54
|
+
unless @markup.tag
|
|
55
|
+
if @markup.tag = @params.delete(:tag)
|
|
56
|
+
@markup.steal_html_params_from(@params)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Translate dynamic params such as <tt>class='#{visitor.lang}'</tt> in the context
|
|
61
|
+
# of the current parser
|
|
62
|
+
@markup.compile_params(self)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def wrap_html(text)
|
|
66
|
+
compile_html_params
|
|
67
|
+
@markup.wrap(text)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
#def restore_markup
|
|
71
|
+
# # restore @markup
|
|
72
|
+
# @markup = @markup_bak
|
|
73
|
+
#end
|
|
74
|
+
|
|
75
|
+
def inspect
|
|
76
|
+
@markup.done = false
|
|
77
|
+
res = super
|
|
78
|
+
if @markup.tag
|
|
79
|
+
if res =~ /\A\[(\w+)(.*)\/\]\Z/m
|
|
80
|
+
res = "[#{$1}#{$2}]<#{@markup.tag}/>[/#{$1}]"
|
|
81
|
+
elsif res =~ /\A\[([^\]]+)\](.*)\[\/(\w+)\]\Z/m
|
|
82
|
+
res = "[#{$1}]#{@markup.wrap($2)}[/#{$3}]"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
res
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def r_ignore
|
|
89
|
+
@markup.done = true
|
|
90
|
+
''
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def r_rename_asset
|
|
94
|
+
return expand_with unless @markup.tag
|
|
95
|
+
case @markup.tag
|
|
96
|
+
when 'link'
|
|
97
|
+
key = :href
|
|
98
|
+
return parser_error("Missing 'rel' parameter.") unless rel = @params[:rel]
|
|
99
|
+
return parser_error("Missing 'href' parameter.") unless @params[:href]
|
|
100
|
+
if rel.downcase == 'stylesheet'
|
|
101
|
+
type = :stylesheet
|
|
102
|
+
else
|
|
103
|
+
type = :link
|
|
104
|
+
end
|
|
105
|
+
when 'style'
|
|
106
|
+
return expand_with.gsub(/url\(('|")(.*?)\1\)/) do
|
|
107
|
+
if $2[0..6] == 'http://'
|
|
108
|
+
$&
|
|
109
|
+
else
|
|
110
|
+
quote = $1
|
|
111
|
+
new_src = helper.send(:template_url_for_asset, :base_path=>@options[:base_path], :src => $2)
|
|
112
|
+
"url(#{quote}#{new_src}#{quote})"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
else
|
|
116
|
+
key = :src
|
|
117
|
+
type = @markup.tag.to_sym
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
src = @params.delete(key)
|
|
121
|
+
if src && src[0..7] != 'http://'
|
|
122
|
+
if new_value = helper.send(:template_url_for_asset, :src => src, :base_path => @options[:base_path], :type => type)
|
|
123
|
+
elsif src =~ SAFE_SRC_REGEX
|
|
124
|
+
fullpath = "#{SITES_ROOT}#{current_site.public_path}#{src}"
|
|
125
|
+
if File.exist?(fullpath) && File.stat(fullpath)
|
|
126
|
+
src = "#{src}?#{File.mtime(fullpath).to_i}"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
@markup.params[key] = new_value.blank? ? src : new_value
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
expand_with
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def steal_and_eval_html_params_for(markup, params)
|
|
136
|
+
markup.steal_keys.each do |key|
|
|
137
|
+
next unless value = params.delete(key)
|
|
138
|
+
append_markup_attr(markup, key, value)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
#def r_form
|
|
142
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
|
143
|
+
# @markup.done = true
|
|
144
|
+
# inner = expand_with
|
|
145
|
+
# if inner == ''
|
|
146
|
+
# res + "/>"
|
|
147
|
+
# else
|
|
148
|
+
# res + ">#{inner}"
|
|
149
|
+
# end
|
|
150
|
+
#end
|
|
151
|
+
#
|
|
152
|
+
#def r_select
|
|
153
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
|
154
|
+
# @markup.done = true
|
|
155
|
+
# inner = expand_with
|
|
156
|
+
# if inner == ''
|
|
157
|
+
# res + "></#{@markup.tag}>"
|
|
158
|
+
# else
|
|
159
|
+
# res + ">#{inner}"
|
|
160
|
+
# end
|
|
161
|
+
#end
|
|
162
|
+
#
|
|
163
|
+
#def r_input
|
|
164
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
|
165
|
+
# @markup.done = true
|
|
166
|
+
# inner = expand_with
|
|
167
|
+
# if inner == ''
|
|
168
|
+
# res + "/>"
|
|
169
|
+
# else
|
|
170
|
+
# res + ">#{inner}"
|
|
171
|
+
# end
|
|
172
|
+
#end
|
|
173
|
+
#
|
|
174
|
+
#def r_textarea
|
|
175
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
|
176
|
+
# @markup.done = true
|
|
177
|
+
# inner = expand_with
|
|
178
|
+
# if inner == ''
|
|
179
|
+
# res + "/>"
|
|
180
|
+
# else
|
|
181
|
+
# res + ">#{inner}"
|
|
182
|
+
# end
|
|
183
|
+
#end
|
|
184
|
+
end # HTML
|
|
185
|
+
end # Process
|
|
186
|
+
end # Zafu
|