nitro 0.31.0 → 0.40.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.
Files changed (174) hide show
  1. data/bin/nitro +135 -37
  2. data/doc/CHANGELOG.1 +108 -108
  3. data/doc/CHANGELOG.2 +89 -89
  4. data/doc/CHANGELOG.3 +105 -105
  5. data/{CHANGELOG → doc/CHANGELOG.4} +509 -509
  6. data/doc/{AUTHORS → CONTRIBUTORS} +49 -37
  7. data/doc/LIBRARIES +13 -0
  8. data/doc/LICENSE +2 -3
  9. data/doc/MIGRATION +45 -0
  10. data/doc/RELEASES +131 -11
  11. data/doc/TODO +67 -0
  12. data/lib/glue/magick.rb +0 -3
  13. data/lib/glue/sweeper.rb +30 -15
  14. data/lib/glue/thumbnails.rb +0 -2
  15. data/lib/glue/webfile.rb +23 -11
  16. data/lib/nitro.rb +37 -44
  17. data/lib/nitro/adapter/cgi.rb +0 -3
  18. data/lib/nitro/adapter/console.rb +0 -2
  19. data/lib/nitro/adapter/fastcgi.rb +6 -3
  20. data/lib/nitro/adapter/mongrel.rb +97 -58
  21. data/lib/nitro/adapter/script.rb +4 -6
  22. data/lib/nitro/adapter/webrick.rb +33 -87
  23. data/lib/nitro/adapter/webrick/vcr.rb +85 -0
  24. data/lib/nitro/caching.rb +0 -2
  25. data/lib/nitro/caching/actions.rb +0 -2
  26. data/lib/nitro/caching/fragments.rb +0 -2
  27. data/lib/nitro/caching/output.rb +45 -16
  28. data/lib/nitro/caching/proxy.rb +49 -0
  29. data/lib/nitro/cgi.rb +3 -6
  30. data/lib/nitro/cgi/cookie.rb +0 -3
  31. data/lib/nitro/cgi/request.rb +67 -24
  32. data/lib/nitro/cgi/response.rb +0 -2
  33. data/lib/nitro/cgi/{sendfile.rb → send_file.rb} +7 -6
  34. data/lib/nitro/compiler.rb +62 -55
  35. data/lib/nitro/compiler/cleanup.rb +0 -3
  36. data/lib/nitro/compiler/elements.rb +31 -28
  37. data/lib/nitro/compiler/errors.rb +2 -5
  38. data/lib/nitro/compiler/include.rb +10 -8
  39. data/lib/nitro/compiler/layout.rb +0 -2
  40. data/lib/nitro/compiler/localization.rb +0 -2
  41. data/lib/nitro/compiler/markup.rb +14 -6
  42. data/lib/nitro/compiler/morphing.rb +1 -5
  43. data/lib/nitro/compiler/script.rb +2 -4
  44. data/lib/nitro/compiler/squeeze.rb +0 -2
  45. data/lib/nitro/compiler/xslt.rb +0 -2
  46. data/lib/nitro/context.rb +10 -5
  47. data/lib/nitro/control.rb +18 -0
  48. data/lib/nitro/control/attribute.rb +88 -0
  49. data/lib/nitro/control/attribute/checkbox.rb +19 -0
  50. data/lib/nitro/control/attribute/datetime.rb +21 -0
  51. data/lib/nitro/control/attribute/file.rb +20 -0
  52. data/lib/nitro/control/attribute/fixnum.rb +26 -0
  53. data/lib/nitro/control/attribute/float.rb +26 -0
  54. data/lib/nitro/control/attribute/options.rb +38 -0
  55. data/lib/nitro/control/attribute/password.rb +16 -0
  56. data/lib/nitro/control/attribute/text.rb +16 -0
  57. data/lib/nitro/control/attribute/textarea.rb +16 -0
  58. data/lib/nitro/control/none.rb +16 -0
  59. data/lib/nitro/control/relation.rb +53 -0
  60. data/lib/nitro/control/relation/belongs_to.rb +0 -0
  61. data/lib/nitro/control/relation/has_many.rb +97 -0
  62. data/lib/nitro/control/relation/joins_many.rb +0 -0
  63. data/lib/nitro/control/relation/many_to_many.rb +0 -0
  64. data/lib/nitro/control/relation/refers_to.rb +29 -0
  65. data/lib/nitro/controller.rb +7 -296
  66. data/lib/nitro/dispatcher.rb +72 -34
  67. data/lib/nitro/element.rb +36 -10
  68. data/lib/nitro/element/javascript.rb +0 -2
  69. data/lib/nitro/flash.rb +23 -10
  70. data/lib/nitro/global.rb +36 -11
  71. data/lib/nitro/helper.rb +22 -8
  72. data/lib/nitro/helper/benchmark.rb +0 -2
  73. data/lib/nitro/helper/buffer.rb +0 -3
  74. data/lib/nitro/helper/css.rb +12 -0
  75. data/lib/nitro/helper/debug.rb +1 -3
  76. data/lib/nitro/helper/default.rb +1 -0
  77. data/lib/nitro/helper/feed.rb +400 -386
  78. data/lib/nitro/helper/form.rb +246 -116
  79. data/lib/nitro/helper/javascript.rb +28 -2
  80. data/lib/nitro/helper/javascript/morphing.rb +0 -2
  81. data/lib/nitro/helper/javascript/prototype.rb +0 -2
  82. data/lib/nitro/helper/javascript/scriptaculous.rb +0 -1
  83. data/lib/nitro/helper/layout.rb +0 -2
  84. data/lib/nitro/helper/navigation.rb +87 -0
  85. data/lib/nitro/helper/pager.rb +11 -22
  86. data/lib/nitro/helper/table.rb +9 -32
  87. data/lib/nitro/helper/url.rb +104 -0
  88. data/lib/nitro/helper/xhtml.rb +20 -4
  89. data/lib/nitro/helper/xml.rb +0 -2
  90. data/lib/nitro/markup.rb +131 -0
  91. data/lib/nitro/part.rb +52 -7
  92. data/lib/nitro/publishable.rb +328 -0
  93. data/lib/nitro/render.rb +30 -61
  94. data/lib/nitro/router.rb +12 -4
  95. data/lib/nitro/sanitize.rb +48 -0
  96. data/lib/nitro/scaffold.rb +9 -11
  97. data/lib/nitro/scaffold/controller.rb +25 -0
  98. data/lib/nitro/scaffold/model.rb +150 -0
  99. data/lib/nitro/scaffolding.rb +1 -3
  100. data/lib/nitro/server.rb +57 -32
  101. data/lib/nitro/server/drb.rb +16 -2
  102. data/lib/nitro/server/runner.rb +80 -102
  103. data/lib/nitro/service.rb +0 -1
  104. data/lib/nitro/service/xmlrpc.rb +0 -2
  105. data/lib/nitro/session.rb +26 -18
  106. data/lib/nitro/session/drb.rb +2 -16
  107. data/lib/nitro/session/memory.rb +0 -2
  108. data/lib/nitro/template.rb +219 -0
  109. data/lib/nitro/test/assertions.rb +1 -3
  110. data/lib/nitro/test/context.rb +0 -1
  111. data/lib/nitro/test/testcase.rb +0 -1
  112. data/lib/nitro/version.rb +6 -0
  113. data/lib/part/admin.rb +16 -0
  114. data/lib/part/admin/controller.rb +19 -0
  115. data/lib/part/admin/helper.rb +30 -0
  116. data/lib/part/admin/og/controller.rb +114 -0
  117. data/lib/part/admin/og/customize.rb +4 -0
  118. data/lib/part/admin/og/template/index.xhtml +27 -0
  119. data/lib/part/admin/og/template/list.xhtml +38 -0
  120. data/lib/part/admin/og/template/search.xhtml +20 -0
  121. data/lib/part/admin/og/template/update.xhtml +25 -0
  122. data/lib/part/admin/skin.rb +207 -0
  123. data/lib/part/admin/template/denied.xhtml +13 -0
  124. data/lib/part/admin/template/index.xhtml +12 -0
  125. data/lib/part/admin/todo.txt +2 -0
  126. data/proto/public/error.xhtml +4 -2
  127. data/proto/run.rb +0 -2
  128. data/test/glue/tc_webfile.rb +1 -0
  129. data/test/nitro/cgi/tc_request.rb +23 -0
  130. data/test/nitro/helper/tc_feed.rb +0 -3
  131. data/test/nitro/helper/tc_navbar.rb +74 -0
  132. data/test/nitro/helper/tc_table.rb +2 -0
  133. data/test/nitro/tc_cgi.rb +72 -19
  134. data/test/nitro/tc_controller.rb +35 -26
  135. data/test/nitro/tc_controller_aspect.rb +1 -0
  136. data/test/nitro/tc_controller_params.rb +864 -0
  137. data/test/nitro/tc_dispatcher.rb +2 -2
  138. data/test/nitro/tc_element.rb +16 -16
  139. data/test/nitro/tc_flash.rb +3 -3
  140. data/test/nitro/tc_markup.rb +31 -0
  141. data/test/nitro/tc_render.rb +12 -14
  142. data/test/nitro/tc_session.rb +9 -7
  143. data/test/nitro/tc_template.rb +34 -0
  144. metadata +217 -198
  145. data/INSTALL +0 -121
  146. data/ProjectInfo +0 -74
  147. data/README +0 -555
  148. data/doc/apache.txt +0 -9
  149. data/doc/config.txt +0 -28
  150. data/doc/faq.txt +0 -7
  151. data/doc/lhttpd.txt +0 -7
  152. data/lib/nitro/adapter/scgi.rb +0 -239
  153. data/lib/nitro/helper/form/builder.rb +0 -144
  154. data/lib/nitro/helper/form/controls.rb +0 -389
  155. data/lib/nitro/helper/rss.rb +0 -72
  156. data/proto/conf/apache.conf +0 -51
  157. data/proto/public/scaffold/advanced_search.xhtml +0 -30
  158. data/proto/public/scaffold/edit.xhtml +0 -11
  159. data/proto/public/scaffold/form.xhtml +0 -1
  160. data/proto/public/scaffold/index.xhtml +0 -20
  161. data/proto/public/scaffold/list.xhtml +0 -32
  162. data/proto/public/scaffold/new.xhtml +0 -11
  163. data/proto/public/scaffold/search.xhtml +0 -29
  164. data/proto/public/scaffold/view.xhtml +0 -8
  165. data/proto/script/scgi_ctl +0 -221
  166. data/proto/script/scgi_service +0 -128
  167. data/setup.rb +0 -1585
  168. data/src/part/admin.rb +0 -16
  169. data/src/part/admin/controller.rb +0 -81
  170. data/src/part/admin/skin.rb +0 -21
  171. data/src/part/admin/system.css +0 -135
  172. data/src/part/admin/template/denied.xhtml +0 -1
  173. data/src/part/admin/template/index.xhtml +0 -43
  174. data/test/nitro/helper/tc_rss.rb +0 -24
@@ -58,12 +58,12 @@ class Exception # :nodoc: all
58
58
  number = start
59
59
  extract = source[start..finish].collect do |line|
60
60
  number += 1
61
- line = line.gsub(/; @out << %\^/, ' ?>').gsub(/\^;/, '<?r ')
61
+ line = line.gsub(/; @out #{Nitro::TemplateMixin::START_DELIM}/, ' ?>').gsub(/#{Nitro::TemplateMixin::END_DELIM}/, '<?r ')
62
62
  "#{' ' * indent}#{number}: #{line}"
63
63
  end
64
64
 
65
65
  return extract.join("\n")
66
- rescue => ex
66
+ rescue Object => ex
67
67
  ''
68
68
  end
69
69
  end
@@ -110,6 +110,3 @@ class Exception # :nodoc: all
110
110
  end
111
111
 
112
112
  end
113
-
114
- # * George Moschovitis <gm@navel.gr>
115
- # * Rob Pitt <rob@motionpath.co.uk>
@@ -19,8 +19,10 @@ class StaticInclude
19
19
  # <?include href="root/myfile.sx" ?>
20
20
 
21
21
  def self.transform(text, compiler)
22
- controller = compiler.controller
23
-
22
+ resolve_include(text, compiler.controller)
23
+ end
24
+
25
+ def self.resolve_include(text, controller)
24
26
  return text.gsub(/<\?include href=["|'](.*?)["|'](.*)\?>/) do |match|
25
27
  found = false
26
28
 
@@ -29,7 +31,7 @@ class StaticInclude
29
31
  # root.
30
32
 
31
33
  href = $1[1, 999999] # hack!!
32
- template_stack = [ Glue::Template.root ]
34
+ template_stack = [ Nitro::Template.root ]
33
35
  else
34
36
  # Relative path, traverse the template_root stack.
35
37
 
@@ -60,13 +62,13 @@ class StaticInclude
60
62
 
61
63
  itext = File.read(filename)
62
64
  itext.gsub!(/<\?xml.*\?>/, '')
63
- itext.gsub!(/<\/?root(.*?)>/m, ' ');
64
- itext
65
+ itext.gsub!(/<\/?root(.*?)>/m, ' ')
66
+
67
+ # Recursively resolve to handle sub-includes.
68
+
69
+ resolve_include(itext, controller)
65
70
  end
66
71
  end
67
-
68
72
  end
69
73
 
70
74
  end
71
-
72
- # * George Moschovitis <gm@navel.gr>
@@ -17,5 +17,3 @@ class LayoutCompiler # :nodoc: all
17
17
  end
18
18
 
19
19
  end
20
-
21
- # * George Moschovitis <gm@navel.gr>
@@ -23,5 +23,3 @@ class Localization
23
23
  end
24
24
 
25
25
  end
26
-
27
- # * George Moschovitis <gm@navel.gr>
@@ -1,23 +1,31 @@
1
- require 'glue/markup'
1
+ require 'nitro/markup'
2
2
 
3
3
  module Nitro
4
4
 
5
- module Markup
6
-
7
- include Glue::Markup
5
+ module MarkupCompiler
6
+ include Markup
8
7
 
9
8
  # Transform the markup macros.
10
9
  # Maps #(..) to :sanitize.
11
10
  # Maps #|..| to :markup.
11
+ #
12
+ # Additional markup macros:
13
+ #
14
+ # Maps ''..'' to #{...to_link}
15
+ # Maps {{..}} to #{R ..}
16
+ # Maps #<..> to #{R ..}
12
17
 
13
18
  def self.transform(text, compiler = nil)
14
19
  text.gsub!(/\#\((.*?)\)/, '#{sanitize(\1)}')
15
20
  text.gsub!(/\#\|(.*?)\|/, '#{markup(\1)}')
21
+
22
+ text.gsub!(/\'\'(.*?)\'\'/, '#{\1.to_link}')
23
+ text.gsub!(/\{\{(.*?)\}\}/, '#{R \1}')
24
+ text.gsub!(/\#\<(.*?)\>/, '#{R \1}')
25
+
16
26
  return text
17
27
  end
18
28
 
19
29
  end
20
30
 
21
31
  end
22
-
23
- # * George Moschovitis <gm@navel.gr>
@@ -203,7 +203,7 @@ class Morphing
203
203
  end
204
204
 
205
205
  def comment(c)
206
- unless Glue::Template.strip_xml_comments
206
+ unless Nitro::Template.strip_xml_comments
207
207
  @buffer << "<!--#{c}-->"
208
208
  end
209
209
  end
@@ -270,7 +270,3 @@ class Morphing
270
270
  end
271
271
 
272
272
  end
273
-
274
- # * George Moschovitis <gm@navel.gr>
275
- # * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
276
- # * Chris Farmiloe <chris.farmiloe@farmiloe.com>
@@ -12,7 +12,7 @@ module ScriptCompiler
12
12
  def self.transform(text, compiler)
13
13
  begin
14
14
  client = constant("#{compiler.controller}::Client")
15
- rescue Object
15
+ rescue NameError => ex
16
16
  client = nil
17
17
  end
18
18
 
@@ -50,7 +50,7 @@ module ScriptCompiler
50
50
  #{function_code}
51
51
  }
52
52
  }
53
- rescue => ex
53
+ rescue Object => ex
54
54
  Logger.debug ex.inspect if $DBG
55
55
  end
56
56
  end
@@ -113,5 +113,3 @@ module ScriptCompiler
113
113
  end
114
114
 
115
115
  end
116
-
117
- # * George Moschovitis <gm@navel.gr>
@@ -17,5 +17,3 @@ class Squeeze
17
17
  end
18
18
 
19
19
  end
20
-
21
- # * George Moschovitis <gm@navel.gr>
@@ -58,5 +58,3 @@ class XSLTransform
58
58
  end
59
59
 
60
60
  end
61
-
62
- # * George Moschovitis <gm@navel.gr>
@@ -3,6 +3,7 @@ require 'forwardable'
3
3
  require 'facet/kernel/assign_with'
4
4
 
5
5
  require 'glue/cache/memory'
6
+ require 'glue/attributeutils'
6
7
 
7
8
  require 'nitro/cgi'
8
9
  require 'nitro/cgi/request'
@@ -112,6 +113,12 @@ class Context
112
113
  @out
113
114
  end
114
115
 
116
+ # Access the server
117
+
118
+ def server
119
+ @dispatcher.server
120
+ end
121
+
115
122
  # Lazy lookup of the session to avoid costly cookie
116
123
  # lookup when not needed.
117
124
 
@@ -126,7 +133,7 @@ class Context
126
133
  return Global
127
134
  end
128
135
  alias_method :application, :global
129
-
136
+ =begin
130
137
  # Lookup the controller for this request.
131
138
  #--
132
139
  # FIXME: improve this! BUGGY
@@ -135,7 +142,7 @@ class Context
135
142
  def controller
136
143
  @dispatcher.controllers[@base || '/']
137
144
  end
138
-
145
+ =end
139
146
  # Automagically populate an object from request parameters.
140
147
  # This is a truly dangerous method.
141
148
  #
@@ -153,7 +160,7 @@ class Context
153
160
  # User.new.assign_with(request)
154
161
 
155
162
  def fill(obj, options = {})
156
- Property.populate_object(obj, @params, options)
163
+ AttributeUtils.populate_object(obj, @params, options)
157
164
  end
158
165
  alias_method :populate, :fill
159
166
  alias_method :assign, :fill
@@ -181,5 +188,3 @@ class Context
181
188
  end
182
189
 
183
190
  end
184
-
185
- # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,18 @@
1
+ require 'nitro/element'
2
+ require 'nitro/helper/xhtml'
3
+
4
+ module Nitro
5
+
6
+ # A specialized kind of element used for implementing UI
7
+ # controls.
8
+ #--
9
+ # TODO: add support for the singleton pattern to avoid excessive
10
+ # memory usage.
11
+ #++
12
+
13
+ class Control < Element
14
+ # THINK: maybe include this in element too?
15
+ include Nitro::XhtmlHelper
16
+ end
17
+
18
+ end
@@ -0,0 +1,88 @@
1
+ require 'nitro/control'
2
+
3
+ module Nitro
4
+
5
+ # The base class for controls used to inspect object
6
+ # attributes.
7
+ #--
8
+ # TODO: find a better name.
9
+ #++
10
+
11
+ class AttributeControl < Control
12
+
13
+ # The attribute that this control renders.
14
+
15
+ attr_accessor :attribute
16
+
17
+ # The annotations used for rendering
18
+
19
+ attr_accessor :anno
20
+
21
+ # The value
22
+
23
+ attr_accessor :value
24
+ alias values value
25
+
26
+ # === Input
27
+ #
28
+ # * object = the object to inspect
29
+ # * a = the attribute to inspect
30
+ # * options = additional options
31
+
32
+ def initialize(object, a, options)
33
+ @object = object
34
+ @attribute = a
35
+ @anno = @object.class.ann(@attribute)
36
+ @objann = @object.annotation[@attribute] || @object.annotation
37
+ @value = @object.send(@attribute)
38
+ @options = options
39
+ end
40
+
41
+ private
42
+
43
+ # Emit the label for this control.
44
+ # The label is skipped if the control is created with the
45
+ # option :no_label set to true.
46
+
47
+ def emit_label
48
+ return '' if @options[:no_label]
49
+ title = @anno[:title] || @options[:label] || @attribute.to_s.humanize
50
+ %{<label for="#{@attribute}">#{title}</label>}
51
+ end
52
+
53
+ # Emit the css style for this control.
54
+ # This mehtod takes into account the passed options (first)
55
+ # and then the attribute annotations.
56
+
57
+ def emit_style
58
+ unless style = (@options[:style] || @anno[:control_style])
59
+ # unless style = (@objann[:control_style] || @options[:style] || @anno[:control_style])
60
+ if self.class.respond_to? :style
61
+ style = self.class.style
62
+ else
63
+ style = nil
64
+ end
65
+ end
66
+ style ? %{ style="#{style}"} : ''
67
+ end
68
+
69
+ # Add support to your controls for being disabled
70
+ # by including an emit_disabled on form items
71
+ # or testing for is_disabled? on more complex controls.
72
+
73
+ def emit_disabled
74
+ is_disabled? ? %{ disabled="disabled"} : ''
75
+ end
76
+
77
+ #--
78
+ # FIXME
79
+ #++
80
+
81
+ def is_disabled?
82
+ return false if @options[:all]
83
+ @options[:disable_controls] || @anno[:disable_control]
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,19 @@
1
+ require 'nitro/control/attribute'
2
+
3
+ module Nitro
4
+
5
+ # A Control used to edit boolean attributes.
6
+
7
+ class CheckboxControl < AttributeControl
8
+ setting :style, :default => '', :doc => 'The default style'
9
+
10
+ def render
11
+ checked = @value == true ? ' checked="checked"' : ''
12
+ %{
13
+ <input type="checkbox" id="#{@attribute}_ctl" name="#{@attribute}" #{emit_style}#{checked}#{emit_disabled} />&nbsp;#{emit_label}
14
+ }
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,21 @@
1
+ require 'nitro/control/attribute'
2
+
3
+ module Nitro
4
+
5
+ # A Control used to edit datetime attributes.
6
+ #--
7
+ # TODO: implement me!
8
+ #++
9
+
10
+ class DatetimeControl < AttributeControl
11
+ setting :style, :default => '', :doc => 'The default style'
12
+
13
+ def render
14
+ %{
15
+ NOT IMPLEMENTED
16
+ }
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'nitro/control/attribute'
2
+
3
+ module Nitro
4
+
5
+ # Usage note:
6
+ # don't forget to set form :method to :multipart
7
+ # or :method to :post and :enctype to 'multipart/form-data'
8
+
9
+ class FileControl < AttributeControl
10
+ setting :style, :default => 'width: 250px', :doc => 'The default style'
11
+
12
+ def render
13
+ %{
14
+ #{emit_label}
15
+ <input type="file" id="#{@attribute}_ctl" name="#{@attribute}" value="#{@object.send(@attribute)}"#{emit_style}#{emit_disabled} />
16
+ }
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,26 @@
1
+ require 'nitro/control/attribute'
2
+
3
+ module Nitro
4
+
5
+ # Controls a Fixnum attribute.
6
+
7
+ class FixnumControl < AttributeControl
8
+ setting :style, :default => 'width: 100px', :doc => 'The default style'
9
+
10
+ def render
11
+ style = @anno.control_style || self.class.style
12
+ %{
13
+ #{emit_label}
14
+ <input type="text" id="#{@attribute}_ctl" name="#{@attribute}" value="#{value}"#{emit_style}#{emit_disabled} />
15
+ <a href="#" onclick="el=document.getElementById('#{@attribute}_ctl'); el.value=(parseInt(el.value) || 0)+#{step}; return false;">+</a>
16
+ <a href="#" onclick="el=document.getElementById('#{@attribute}_ctl'); el.value=(parseInt(el.value) || 0)-#{step}; return false;">-</a>
17
+ }
18
+ end
19
+
20
+ def step
21
+ 1
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'nitro/control/attribute'
2
+
3
+ module Nitro
4
+
5
+ # Controls a Float attribute.
6
+
7
+ class FloatControl < AttributeControl
8
+ setting :style, :default => 'width: 100px', :doc => 'The default style'
9
+
10
+ def render
11
+ style = @anno.control_style || self.class.style
12
+ %{
13
+ #{emit_label}
14
+ <input type="text" id="#{@attribute}_ctl" name="#{@attribute}" value="#{value}"#{emit_style}#{emit_disabled} />
15
+ <a href="#" onclick="el=document.getElementById('#{@attribute}_ctl'); el.value=(parseInt(el.value) || 0)+#{step}; return false;">+</a>
16
+ <a href="#" onclick="el=document.getElementById('#{@attribute}_ctl'); el.value=(parseInt(el.value) || 0)-#{step}; return false;">-</a>
17
+ }
18
+ end
19
+
20
+ def step
21
+ 0.5
22
+ end
23
+
24
+ end
25
+
26
+ end