aurita-gui 0.3.2 → 0.3.3
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 +10 -0
- data/TODO +12 -0
- data/aurita-gui.gemspec +1 -1
- data/lib/aurita-gui.rb +1 -0
- data/lib/aurita-gui/button.rb +2 -2
- data/lib/aurita-gui/element.rb +29 -17
- data/lib/aurita-gui/form.rb +46 -12
- data/lib/aurita-gui/form/date_field.rb +11 -5
- data/lib/aurita-gui/form/datetime_field.rb +3 -3
- data/lib/aurita-gui/form/template_helper.rb +109 -0
- data/lib/aurita-gui/html.rb +27 -74
- data/lib/aurita-gui/javascript.rb +158 -0
- data/spec/element.rb +9 -0
- data/spec/form.rb +1 -1
- data/spec/html.rb +8 -1
- data/spec/javascript.rb +25 -0
- metadata +5 -3
- data/spec/; +0 -14
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 0.3.3 / 2009-01-24
|
2
|
+
|
3
|
+
* Added form helpers for template rendering.
|
4
|
+
* Extended API by convenience shortcuts:
|
5
|
+
Content for elements can be set markaby-like now:
|
6
|
+
|
7
|
+
HTML.div 'content here' :class => :highlighted
|
8
|
+
|
9
|
+
* Minor bug fixes.
|
10
|
+
|
1
11
|
=== 0.3.1 / 2009-01-15
|
2
12
|
|
3
13
|
* Added specs for Element and HTML.
|
data/TODO
CHANGED
@@ -20,6 +20,18 @@
|
|
20
20
|
|
21
21
|
= DONE =============================================
|
22
22
|
|
23
|
+
- Provide markaby-like syntax, Example:
|
24
|
+
|
25
|
+
HTML.div 'content here' :class => :highlight
|
26
|
+
|
27
|
+
and
|
28
|
+
|
29
|
+
HTML.build {
|
30
|
+
div 'content' {
|
31
|
+
h1 'header'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
23
35
|
- Decorate required fields.
|
24
36
|
Required fields are always rendered.
|
25
37
|
|
data/aurita-gui.gemspec
CHANGED
@@ -14,7 +14,7 @@ as stand-alone library in any context (such as rails).
|
|
14
14
|
As there seems to be a lack of ruby form generators, i decided to release this
|
15
15
|
part of Aurita in a single gem with no dependencies.
|
16
16
|
EOF
|
17
|
-
s.version = '0.3.
|
17
|
+
s.version = '0.3.3'
|
18
18
|
s.author = 'Tobias Fuchs'
|
19
19
|
s.email = 'fuchs@atomnode.net'
|
20
20
|
s.date = Time.now
|
data/lib/aurita-gui.rb
CHANGED
data/lib/aurita-gui/button.rb
CHANGED
@@ -50,7 +50,7 @@ module GUI
|
|
50
50
|
#
|
51
51
|
# b = Submit_Button.new(:class => :css_class) { 'click me' }
|
52
52
|
#
|
53
|
-
class Submit_Button <
|
53
|
+
class Submit_Button < Button
|
54
54
|
def initialize(params, &block)
|
55
55
|
params[:tag] = :input
|
56
56
|
params[:type] = :submit unless params[:type]
|
@@ -70,7 +70,7 @@ module GUI
|
|
70
70
|
#
|
71
71
|
# Note that reset buttons in forms are considered
|
72
72
|
# bad style in terms of usability.
|
73
|
-
class Reset_Button <
|
73
|
+
class Reset_Button < Button
|
74
74
|
def initialize(params, &block)
|
75
75
|
params[:tag] = :input
|
76
76
|
params[:type] = :reset unless params[:type]
|
data/lib/aurita-gui/element.rb
CHANGED
@@ -59,19 +59,28 @@ module GUI
|
|
59
59
|
|
60
60
|
@@element_count = 0
|
61
61
|
|
62
|
-
attr_accessor :attrib, :content, :parent, :
|
62
|
+
attr_accessor :attrib, :content, :parent, :force_closing_tag, :tag
|
63
63
|
|
64
|
-
def initialize(
|
64
|
+
def initialize(*args, &block)
|
65
|
+
|
66
|
+
params = {}
|
67
|
+
case args[0]
|
68
|
+
when Hash
|
69
|
+
params = args[0]
|
70
|
+
else
|
71
|
+
params = args[1]
|
72
|
+
params ||= {}
|
73
|
+
params[:content] = args[0]
|
74
|
+
end
|
65
75
|
|
66
76
|
@@element_count += 1
|
67
77
|
@id = @@element_count
|
68
78
|
@parent = params[:parent]
|
69
79
|
@force_closing_tag = params[:force_closing_tag]
|
80
|
+
|
70
81
|
params[:tag] = :div if params[:tag].nil?
|
71
|
-
@tag
|
72
|
-
|
73
|
-
@force_closing_tag = true
|
74
|
-
end
|
82
|
+
@tag = params[:tag]
|
83
|
+
|
75
84
|
params.delete(:parent)
|
76
85
|
params.delete(:force_closing_tag)
|
77
86
|
|
@@ -104,6 +113,16 @@ module GUI
|
|
104
113
|
def dom_id=(value)
|
105
114
|
@attrib[:id] = value if @attrib
|
106
115
|
end
|
116
|
+
# Alias definition for #dom_id=(value)
|
117
|
+
# Define explicitly so built-in method #id
|
118
|
+
# is not invoked instead
|
119
|
+
def id=(value)
|
120
|
+
@attrib[:id] = value
|
121
|
+
end
|
122
|
+
# Alias definition for #dom_id()
|
123
|
+
def id
|
124
|
+
@attrib[:id]
|
125
|
+
end
|
107
126
|
|
108
127
|
# Render this element to a string and append another
|
109
128
|
# element.
|
@@ -118,7 +137,6 @@ module GUI
|
|
118
137
|
end
|
119
138
|
alias to_a to_ary
|
120
139
|
|
121
|
-
|
122
140
|
# Redirect methods to setting or retreiving tag
|
123
141
|
# attributes.
|
124
142
|
def method_missing(meth, value=nil)
|
@@ -135,16 +153,6 @@ module GUI
|
|
135
153
|
def type=(type)
|
136
154
|
@attrib[:type] = type
|
137
155
|
end
|
138
|
-
# Alias definition for #dom_id=(value)
|
139
|
-
# Define explicitly so built-in method #id
|
140
|
-
# is not invoked instead
|
141
|
-
def id=(value)
|
142
|
-
@attrib[:id] = value
|
143
|
-
end
|
144
|
-
# Alias definition for #dom_id()
|
145
|
-
def id
|
146
|
-
@attrib[:id]
|
147
|
-
end
|
148
156
|
|
149
157
|
# Do not redirect random access operators.
|
150
158
|
def [](index)
|
@@ -186,6 +194,10 @@ module GUI
|
|
186
194
|
}
|
187
195
|
|
188
196
|
out = ''
|
197
|
+
if (!(@force_closing_tag.instance_of?(FalseClass)) &&
|
198
|
+
[ :div, :label, :button, :textarea ].include?(@tag)) then
|
199
|
+
@force_closing_tag = true
|
200
|
+
end
|
189
201
|
if @force_closing_tag || content.to_s != '' then
|
190
202
|
out << "<#{@tag}"
|
191
203
|
out << attrib_string if attrib_string.length > 0
|
data/lib/aurita-gui/form.rb
CHANGED
@@ -72,12 +72,13 @@ module GUI
|
|
72
72
|
else
|
73
73
|
@content = field
|
74
74
|
end
|
75
|
+
field.dom_id = field.name.to_s.gsub('.','_') unless field.dom_id
|
75
76
|
css_classes = field.class.to_s.split('::')[-1].downcase + '_wrap form_field'
|
76
77
|
css_classes << ' required' if field.required?
|
77
78
|
css_classes << ' invalid' if field.invalid?
|
78
79
|
params = { :tag => :li,
|
79
80
|
:content => @content,
|
80
|
-
:id => field.dom_id + '_wrap',
|
81
|
+
:id => field.dom_id.to_s + '_wrap',
|
81
82
|
:class => css_classes }
|
82
83
|
super(params)
|
83
84
|
end
|
@@ -142,14 +143,32 @@ module GUI
|
|
142
143
|
# }
|
143
144
|
# textarea = GUI::Textarea.new(:name => :comment, :label => 'Comment')
|
144
145
|
# form.add(textarea)
|
145
|
-
#
|
146
|
-
# In case you want to override the form action (default: /aurita/dispatch),
|
147
|
-
# use :action_url:
|
148
146
|
#
|
149
|
-
#
|
150
|
-
# or
|
151
|
-
# Form.action_url = '/where/to/send/form'
|
147
|
+
# === Rails
|
152
148
|
#
|
149
|
+
# In Rails, you could use form instances like:
|
150
|
+
#
|
151
|
+
# class ItemController < ActionController::Base
|
152
|
+
# def add
|
153
|
+
# @form = Form.new(:action => 'where/to/send')
|
154
|
+
# @form[:title].required!
|
155
|
+
# end
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# And in view 'item/add':
|
159
|
+
#
|
160
|
+
# <%
|
161
|
+
# @form[:title].value = 'Enter a title here'
|
162
|
+
# @form[:description].disabled! unless @may_edit_description
|
163
|
+
# %>
|
164
|
+
#
|
165
|
+
# <%= @form.string %>
|
166
|
+
#
|
167
|
+
# You can also use form template helpers from
|
168
|
+
# Aurita::GUI::Form_Field_Helpers.
|
169
|
+
# You'd have to define you own form builder class, but that's
|
170
|
+
# quite simple (see comments on module Form_Field_Helpers).
|
171
|
+
# I'll soon provide a Rails-specific form builder, though.
|
153
172
|
#
|
154
173
|
# == Render modes
|
155
174
|
#
|
@@ -173,6 +192,7 @@ module GUI
|
|
173
192
|
# :id => :the_form_id,
|
174
193
|
# :action => :where_to_send)
|
175
194
|
#
|
195
|
+
#
|
176
196
|
# You can either set all attributes in the
|
177
197
|
# constructor call ...
|
178
198
|
#
|
@@ -286,14 +306,11 @@ module GUI
|
|
286
306
|
#
|
287
307
|
class Form < Element
|
288
308
|
|
289
|
-
attr_accessor :
|
309
|
+
attr_accessor :fields, :elements, :element_map, :values, :field_decorator, :content_decorator
|
290
310
|
|
291
311
|
def initialize(params={}, &block)
|
292
|
-
@action = params[:action]
|
293
|
-
@method = params[:method]
|
294
312
|
@fields = params[:fields]
|
295
313
|
@values = params[:values]
|
296
|
-
@method ||= :post
|
297
314
|
@fields ||= []
|
298
315
|
@elements = []
|
299
316
|
@element_map = {}
|
@@ -307,8 +324,12 @@ module GUI
|
|
307
324
|
end
|
308
325
|
params.delete(:fields)
|
309
326
|
params.delete(:values)
|
327
|
+
params.delete(:title)
|
328
|
+
params[:method] = 'POST' unless params[:method]
|
329
|
+
params[:enctype] = 'multipart/form-data' unless params[:enctype]
|
310
330
|
params[:tag] = 'form'
|
311
331
|
params[:content] = content()
|
332
|
+
params[:action] = @action
|
312
333
|
super(params)
|
313
334
|
end
|
314
335
|
|
@@ -331,7 +352,7 @@ module GUI
|
|
331
352
|
def []=(index, form_field)
|
332
353
|
@content = false # Invalidate
|
333
354
|
if !index.kind_of? Numeric
|
334
|
-
@element_map[index
|
355
|
+
@element_map[index.to_s] = form_field
|
335
356
|
@elements.collect { |e|
|
336
357
|
e = form_field if e.name.to_s == index.to_s
|
337
358
|
}
|
@@ -477,6 +498,19 @@ module GUI
|
|
477
498
|
HTML.form(@attrib) { content() }
|
478
499
|
end
|
479
500
|
|
501
|
+
# Returns opening tag of this form instance.
|
502
|
+
# Useful for template helper methods.
|
503
|
+
# Example:
|
504
|
+
#
|
505
|
+
# form = Form.new(:action => 'where/to/send')
|
506
|
+
# puts form.header_string
|
507
|
+
# -->
|
508
|
+
# '<form action="where/to/send" enctype="multipart/form-data" method="POST">'
|
509
|
+
#
|
510
|
+
def header_string
|
511
|
+
HTML.form(@attrib).string.gsub('</form>','')
|
512
|
+
end
|
513
|
+
|
480
514
|
# Render this form to a string
|
481
515
|
def string
|
482
516
|
element().to_s
|
@@ -12,7 +12,11 @@ module GUI
|
|
12
12
|
@date_format = params[:date_format]
|
13
13
|
@date_format ||= 'mdy'
|
14
14
|
@year_range = params[:year_range]
|
15
|
+
@year_range ||= (2009..2020)
|
15
16
|
|
17
|
+
if params[:value] then set_date(params[:value]) end
|
18
|
+
|
19
|
+
params.delete(:value)
|
16
20
|
params.delete(:date_format)
|
17
21
|
params.delete(:date)
|
18
22
|
params.delete(:day)
|
@@ -24,7 +28,7 @@ module GUI
|
|
24
28
|
|
25
29
|
def year_element
|
26
30
|
if !@year_element then
|
27
|
-
@year_element = Select_Field.new(:name => @attrib[:name] + '_year',
|
31
|
+
@year_element = Select_Field.new(:name => @attrib[:name].to_s + '_year',
|
28
32
|
:class => :year_select,
|
29
33
|
:value => @year, :options => @year_range)
|
30
34
|
end
|
@@ -32,7 +36,7 @@ module GUI
|
|
32
36
|
end
|
33
37
|
def month_element
|
34
38
|
if !@month_element then
|
35
|
-
@month_element = Select_Field.new(:name => @attrib[:name] + '_month',
|
39
|
+
@month_element = Select_Field.new(:name => @attrib[:name].to_s + '_month',
|
36
40
|
:class => :month_select,
|
37
41
|
:value => @month, :options => (1..12))
|
38
42
|
end
|
@@ -40,7 +44,7 @@ module GUI
|
|
40
44
|
end
|
41
45
|
def day_element
|
42
46
|
if !@day_element then
|
43
|
-
@day_element = Select_Field.new(:name => @attrib[:name] + '_day',
|
47
|
+
@day_element = Select_Field.new(:name => @attrib[:name].to_s + '_day',
|
44
48
|
:class => :day_select,
|
45
49
|
:value => @day, :options => (1..31))
|
46
50
|
end
|
@@ -68,7 +72,7 @@ module GUI
|
|
68
72
|
case date
|
69
73
|
when Hash then
|
70
74
|
@value = date
|
71
|
-
when
|
75
|
+
when ::DateTime then
|
72
76
|
@value = { :year => date.year,
|
73
77
|
:month => date.month,
|
74
78
|
:day => date.day }
|
@@ -77,13 +81,15 @@ module GUI
|
|
77
81
|
:month => date.month,
|
78
82
|
:day => date.day }
|
79
83
|
when String then
|
80
|
-
date =
|
84
|
+
date = (::DateTime).strptime(date, "%Y%m%d")
|
81
85
|
@value = { :year => date.year,
|
82
86
|
:month => date.month,
|
83
87
|
:day => date.day }
|
84
88
|
else
|
85
89
|
end
|
90
|
+
@year, @month, @day = @value[:year], @value[:month], @value[:day]
|
86
91
|
end
|
92
|
+
alias set_date value=
|
87
93
|
|
88
94
|
def value
|
89
95
|
{ :day => @day, :month => @month, :year => @year }
|
@@ -21,7 +21,7 @@ module GUI
|
|
21
21
|
|
22
22
|
def hour_element
|
23
23
|
if !@hour_element then
|
24
|
-
@hour_element = Select_Field.new(:name => @attrib[:name] + '_hour',
|
24
|
+
@hour_element = Select_Field.new(:name => @attrib[:name].to_s + '_hour',
|
25
25
|
:class => :hour_select,
|
26
26
|
:value => @hour, :options => (0..23))
|
27
27
|
end
|
@@ -29,7 +29,7 @@ module GUI
|
|
29
29
|
end
|
30
30
|
def minute_element
|
31
31
|
if !@minute_element then
|
32
|
-
@minute_element = Select_Field.new(:name => @attrib[:name] + '_minute',
|
32
|
+
@minute_element = Select_Field.new(:name => @attrib[:name].to_s + '_minute',
|
33
33
|
:class => :minute_select,
|
34
34
|
:value => @minute, :options => (0..59))
|
35
35
|
end
|
@@ -37,7 +37,7 @@ module GUI
|
|
37
37
|
end
|
38
38
|
def second_element
|
39
39
|
if !@second_element then
|
40
|
-
@second_element = Select_Field.new(:name => @attrib[:name] + '_second',
|
40
|
+
@second_element = Select_Field.new(:name => @attrib[:name].to_s + '_second',
|
41
41
|
:class => :second_select,
|
42
42
|
:value => @second, :options => (0..59))
|
43
43
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
|
2
|
+
require('aurita-gui/form')
|
3
|
+
|
4
|
+
module Aurita
|
5
|
+
module GUI
|
6
|
+
|
7
|
+
# Provides wrapper methods for every
|
8
|
+
# form field type.
|
9
|
+
# Include this module in your template
|
10
|
+
# helper class.
|
11
|
+
#
|
12
|
+
# Form_Helper methods each return a string
|
13
|
+
# for a respective Form_Field element.
|
14
|
+
# Rendering respects the form instances'
|
15
|
+
# @field_decorator, but not @content_decorator,
|
16
|
+
# so you have to wrap form contents manually
|
17
|
+
# in your helper method.
|
18
|
+
#
|
19
|
+
# Example: (what your template helper could look like)
|
20
|
+
#
|
21
|
+
# module Form_Helper_Class_Methods
|
22
|
+
# def form_for(params, &block)
|
23
|
+
# form = Form.new(params, &block)
|
24
|
+
# render form.header_string # <form ...> tag is prepared by form instance
|
25
|
+
# render '<ul class="form_fields">' # begin content wrap
|
26
|
+
# yield(form)
|
27
|
+
# render '</ul>' # end content wrap
|
28
|
+
# render '</form>' # Closing tag for a form should always be </form>
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# Usage, e.g. in ERB templates:
|
33
|
+
#
|
34
|
+
# <% form_for(:action => '/where/to/send') do |f| %>
|
35
|
+
# <%= f.text(:name => :title) { 'Value for this field' } %>
|
36
|
+
# <%= f.select(:name => :color, :options => [ :blue, :red, :green ], :value => :red)
|
37
|
+
# <% end %>
|
38
|
+
#
|
39
|
+
# Form_Helper automatically extends Aurita::GUI::Form
|
40
|
+
# when included.
|
41
|
+
#
|
42
|
+
module Form_Field_Helper
|
43
|
+
|
44
|
+
def text(params, &block)
|
45
|
+
params[:type] = :text
|
46
|
+
@field_decorator.new(Input_Field.new(params, &block)).string
|
47
|
+
end
|
48
|
+
|
49
|
+
def boolean(params, &block)
|
50
|
+
@field_decorator.new(Boolean_Field.new(params, &block)).string
|
51
|
+
end
|
52
|
+
|
53
|
+
def password(params, &block)
|
54
|
+
params[:type] = :password
|
55
|
+
@field_decorator.new(Password_Field.new(params, &block)).string
|
56
|
+
end
|
57
|
+
|
58
|
+
def select(params, &block)
|
59
|
+
@field_decorator.new(Select_Field.new(params, &block)).string
|
60
|
+
end
|
61
|
+
|
62
|
+
def radio(params, &block)
|
63
|
+
@field_decorator.new(Radio_Field.new(params, &block)).string
|
64
|
+
end
|
65
|
+
|
66
|
+
def checkbox(params, &block)
|
67
|
+
@field_decorator.new(Checkbox_Field.new(params, &block)).string
|
68
|
+
end
|
69
|
+
|
70
|
+
def textarea(params, &block)
|
71
|
+
@field_decorator.new(Textarea_Field.new(params, &block)).string
|
72
|
+
end
|
73
|
+
|
74
|
+
def hidden(params, &block)
|
75
|
+
@field_decorator.new(Hidden_Field.new(params, &block)).string
|
76
|
+
end
|
77
|
+
|
78
|
+
def file(params, &block)
|
79
|
+
@field_decorator.new(File_Field.new(params, &block)).string
|
80
|
+
end
|
81
|
+
|
82
|
+
def fieldset(params, &block)
|
83
|
+
@field_decorator.new(Fieldset.new(params, &block)).string
|
84
|
+
end
|
85
|
+
|
86
|
+
def date(params, &block)
|
87
|
+
@field_decorator.new(Date_Field.new(params, &block)).string
|
88
|
+
end
|
89
|
+
|
90
|
+
def datetime(params, &block)
|
91
|
+
@field_decorator.new(Datetime_Field.new(params, &block)).string
|
92
|
+
end
|
93
|
+
|
94
|
+
def custom(params, &block)
|
95
|
+
klass = params[:element]
|
96
|
+
params.delete(:element)
|
97
|
+
@field_decorator.new(klass.new(params, &block)).string
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
# Extend class Aurita::GUI::Form by helper
|
103
|
+
# methods.
|
104
|
+
class Form
|
105
|
+
include Form_Field_Helper
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/lib/aurita-gui/html.rb
CHANGED
@@ -66,6 +66,20 @@ module GUI
|
|
66
66
|
#
|
67
67
|
# HTML.a(:href => 'http://domain.com', :content => 'click me')
|
68
68
|
#
|
69
|
+
# Or as first argument:
|
70
|
+
#
|
71
|
+
# HTML.a('click me', :href => 'http://domain.com')
|
72
|
+
#
|
73
|
+
# So the following statements are equivalent:
|
74
|
+
#
|
75
|
+
# e = HTML.div 'hello', :class => 'highlight'
|
76
|
+
# e = HTML.div(:class => :highlight) { 'hello' }
|
77
|
+
# e = HTML.div(:class => :highlight, :content => 'hello')
|
78
|
+
#
|
79
|
+
# In all cases, e.to_s renders:
|
80
|
+
#
|
81
|
+
# <div class="highlight">hello</div>
|
82
|
+
#
|
69
83
|
# == Further Examples
|
70
84
|
#
|
71
85
|
# There are some few usage principles that are
|
@@ -217,12 +231,12 @@ module GUI
|
|
217
231
|
Element.new(:tag => :br)
|
218
232
|
end
|
219
233
|
|
220
|
-
def self.render(meth_name,
|
221
|
-
raise ::Exception.new('Missing attributes for HTML.' << meth_name.inspect) unless
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
234
|
+
def self.render(meth_name, *args, &block)
|
235
|
+
raise ::Exception.new('Missing attributes for HTML.' << meth_name.inspect) unless args
|
236
|
+
|
237
|
+
e = Element.new(*args, &block)
|
238
|
+
e.tag = meth_name
|
239
|
+
e
|
226
240
|
end
|
227
241
|
|
228
242
|
def self.build(&block)
|
@@ -231,19 +245,19 @@ module GUI
|
|
231
245
|
end
|
232
246
|
|
233
247
|
|
234
|
-
def self.a(
|
235
|
-
render(:a,
|
248
|
+
def self.a(*attribs, &block)
|
249
|
+
render(:a, *attribs, &block)
|
236
250
|
end
|
237
251
|
|
238
252
|
# p is defined in Kernel, so we have to
|
239
253
|
# redirect it manually (method_missing won't be
|
240
254
|
# triggered for it)
|
241
|
-
def self.p(
|
242
|
-
render(:p,
|
255
|
+
def self.p(*attribs, &block)
|
256
|
+
render(:p, *attribs, &block)
|
243
257
|
end
|
244
258
|
|
245
|
-
def self.method_missing(meth_name,
|
246
|
-
render(meth_name,
|
259
|
+
def self.method_missing(meth_name, *attribs, &block)
|
260
|
+
render(meth_name, *attribs, &block)
|
247
261
|
end
|
248
262
|
|
249
263
|
=begin
|
@@ -259,68 +273,7 @@ EOC
|
|
259
273
|
=end
|
260
274
|
|
261
275
|
end # class
|
262
|
-
|
263
|
-
# A minimalistic generator for javascript calls.
|
264
|
-
# Usage:
|
265
|
-
#
|
266
|
-
# my_element.onclick = Javascript.new("alert('an alert message');")
|
267
|
-
#
|
268
|
-
# or just:
|
269
|
-
#
|
270
|
-
# my_element.onclick = Javascript.my_function('foo', 2, 'bar')
|
271
|
-
# --> my_function('foo', 2, 'bar');
|
272
|
-
#
|
273
|
-
# For namespaces:
|
274
|
-
#
|
275
|
-
# my_element.onclick = Javascript[:Foo].my_function(1,2)
|
276
|
-
# --> Foo.my_function('foo', 2, 'bar');
|
277
|
-
#
|
278
|
-
# Method #string renders the code passed in constructir,
|
279
|
-
# enclosed in <script> tags:
|
280
|
-
#
|
281
|
-
# Javascript.new("alert('message');").string
|
282
|
-
# -->
|
283
|
-
# <script language="Javascript" type="text/javascript">
|
284
|
-
# alert('message');
|
285
|
-
# </script>
|
286
|
-
#
|
287
|
-
class Javascript
|
288
|
-
|
289
|
-
def initialize(script)
|
290
|
-
@script = script
|
291
|
-
end
|
292
|
-
|
293
|
-
# Renders script to a <script> block.
|
294
|
-
def code_block
|
295
|
-
'<script language="Javascript" type="text/javascript">' << "\n" <<
|
296
|
-
@script + "\n" <<
|
297
|
-
'</script>'
|
298
|
-
end
|
299
|
-
|
300
|
-
def string
|
301
|
-
@script
|
302
|
-
end
|
303
|
-
alias to_s string
|
304
|
-
|
305
|
-
def self.[](namespace)
|
306
|
-
return self.new(namespace.to_s + '.')
|
307
|
-
end
|
308
|
-
|
309
|
-
def self.method_missing(meth, *args)
|
310
|
-
args = args.collect { |arg|
|
311
|
-
if arg.instance_of? String then
|
312
|
-
'\'' << arg << '\''
|
313
|
-
else
|
314
|
-
arg
|
315
|
-
end
|
316
|
-
}
|
317
|
-
args_string = args.join(',')
|
318
|
-
meth.to_s << '(' << args_string + ');'
|
319
|
-
end
|
320
|
-
|
321
|
-
end # class
|
322
|
-
|
323
|
-
|
276
|
+
|
324
277
|
end # module
|
325
278
|
end # module
|
326
279
|
|
@@ -0,0 +1,158 @@
|
|
1
|
+
|
2
|
+
module Aurita
|
3
|
+
module GUI
|
4
|
+
|
5
|
+
# A minimalistic generator for javascript calls.
|
6
|
+
#
|
7
|
+
# Javascript is a simple string factory so you can
|
8
|
+
# write pieces of javascript code in ruby instead of
|
9
|
+
# using plain old strings.
|
10
|
+
# This does not introduce functionality, it just
|
11
|
+
# eases the rendering of ruby objects to javascript:
|
12
|
+
# Aurita::GUI::Javascript renders method parameters
|
13
|
+
# to their respective meaning in javascript, and also
|
14
|
+
# understands namespaces, variables, and object
|
15
|
+
# notation.
|
16
|
+
#
|
17
|
+
# Sometimes i needed somethind like this in ERB
|
18
|
+
# templates:
|
19
|
+
#
|
20
|
+
# <%= button(:class => :cancel, :onclick => "Aurita.cancel_form('#{form.dom_id}"')) %>
|
21
|
+
#
|
22
|
+
# Now i can do the same in pure ruby:
|
23
|
+
#
|
24
|
+
# <%= button(:class => :cancel, :onclick => js.Aurita.cancel_form(form.dom_id)) %>
|
25
|
+
#
|
26
|
+
# Just by defining a helper method in 5 lines of
|
27
|
+
# code (see below, section Template helper example).
|
28
|
+
#
|
29
|
+
# == Usage with block:
|
30
|
+
#
|
31
|
+
# Javascript.build { |j|
|
32
|
+
# j.Some.Namespace.do_stuff()
|
33
|
+
# j.bla(123, { :gna => 23, :blu => '42' })
|
34
|
+
# j.alert("escape 'this' string")
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
# -->
|
38
|
+
# Some.Namespace.do_stuff(); bla(123,{gna: 23, blu: '42' }); alert('escape \'this\' string');
|
39
|
+
#
|
40
|
+
# == Calling class methods
|
41
|
+
#
|
42
|
+
# For a single call of a javascipt method, you can also use:
|
43
|
+
#
|
44
|
+
# my_element.onclick = Javascript.alert('an alert message')
|
45
|
+
# --> alert('an alert message');
|
46
|
+
#
|
47
|
+
# This also provides method chaining. Uppercase
|
48
|
+
# methods are interpreted as namespaces.
|
49
|
+
#
|
50
|
+
# my_element.onclick = Javascript.Some.Namespace.my_function('foo', 2, 'bar')
|
51
|
+
# --> <div onclick="Some_Namespace.my_function('foo', 2, 'bar'); "> ... </div>
|
52
|
+
#
|
53
|
+
# == Template helper example
|
54
|
+
#
|
55
|
+
# In Aurita, there's a simple helper, defined as
|
56
|
+
#
|
57
|
+
# def js(&block)
|
58
|
+
# if block_given? then
|
59
|
+
# Javascript.build(&block)
|
60
|
+
# else
|
61
|
+
# Javascript
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# It works like that:
|
66
|
+
#
|
67
|
+
# input = Input_Field.new(:onchange => js.Aurita.notify_change_of(:this))
|
68
|
+
# --> <input onchange="Aurita.notify_change_of(this); " />
|
69
|
+
# or
|
70
|
+
# input.onfocus = js.Aurita.notify_focus_on(:this)
|
71
|
+
# --> <input onchange="Aurita.notify_change_of(this); "
|
72
|
+
# onfocus="Aurita.notify_focus_of(this); " />
|
73
|
+
#
|
74
|
+
# == Render to <script> tag
|
75
|
+
#
|
76
|
+
# Method #to_tag renders the code enclosed in <script> tags:
|
77
|
+
#
|
78
|
+
# Javascript.new("alert('message');").to_tag
|
79
|
+
# -->
|
80
|
+
# <script language="Javascript" type="text/javascript">
|
81
|
+
# alert('message');
|
82
|
+
# </script>
|
83
|
+
#
|
84
|
+
class Javascript
|
85
|
+
|
86
|
+
def initialize(script='')
|
87
|
+
@script = script
|
88
|
+
@scripy ||= ''
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.build(&block)
|
92
|
+
if block.arity > 0 then
|
93
|
+
yield(Javascript.new)
|
94
|
+
else
|
95
|
+
self.class_eval(&block)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Renders script to a <script> block.
|
100
|
+
def to_tag
|
101
|
+
'<script language="Javascript" type="text/javascript">' << "\n" <<
|
102
|
+
@script + "\n" <<
|
103
|
+
'</script>'
|
104
|
+
end
|
105
|
+
|
106
|
+
def string
|
107
|
+
@script
|
108
|
+
end
|
109
|
+
alias to_s string
|
110
|
+
|
111
|
+
def self.[](namespace)
|
112
|
+
return self.new(namespace.to_s + '.')
|
113
|
+
end
|
114
|
+
|
115
|
+
def method_missing(meth, *args)
|
116
|
+
args = args.collect { |arg|
|
117
|
+
arg = to_js(arg)
|
118
|
+
}
|
119
|
+
args_string = args.join(',') if args.size > 0
|
120
|
+
meth = meth.to_s
|
121
|
+
# Uppercase method => method call
|
122
|
+
meth << '(' << args_string.to_s << '); ' if meth[0] > 96
|
123
|
+
# Uppercase method => Namespace
|
124
|
+
meth << '.' if meth[0] < 97
|
125
|
+
@script << meth
|
126
|
+
return self
|
127
|
+
end
|
128
|
+
alias render method_missing
|
129
|
+
def self.method_missing(meth, *args)
|
130
|
+
return self.new().__send__(meth, *args)
|
131
|
+
end
|
132
|
+
|
133
|
+
protected
|
134
|
+
|
135
|
+
def to_js(arg)
|
136
|
+
case arg
|
137
|
+
when String:
|
138
|
+
arg.gsub!("'","\\\\'")
|
139
|
+
"'#{arg}'"
|
140
|
+
when Hash:
|
141
|
+
obj = []
|
142
|
+
arg.each_pair { |k,v|
|
143
|
+
v = to_js(v)
|
144
|
+
obj << "#{k}: #{v}"
|
145
|
+
}
|
146
|
+
"{#{obj.join(', ')}}"
|
147
|
+
when Symbol
|
148
|
+
arg.to_s
|
149
|
+
else
|
150
|
+
arg
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end # class
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
data/spec/element.rb
CHANGED
@@ -16,6 +16,15 @@ describe Aurita::GUI::Element, "basic rendering" do
|
|
16
16
|
e.tag.should == :tagname
|
17
17
|
end
|
18
18
|
|
19
|
+
it "should provide a shortcut for content as first constructor argument" do
|
20
|
+
e = Element.new('I am the content')
|
21
|
+
e.string.should == '<div>I am the content</div>'
|
22
|
+
e = Element.new('I am the content', :tag => :p)
|
23
|
+
e.string.should == '<p>I am the content</p>'
|
24
|
+
e.class = 'highlight'
|
25
|
+
e.string.should == '<p class="highlight">I am the content</p>'
|
26
|
+
end
|
27
|
+
|
19
28
|
it "should have :div as default attribute" do
|
20
29
|
e = Element.new()
|
21
30
|
e.tag.should == :div
|
data/spec/form.rb
CHANGED
@@ -22,7 +22,7 @@ describe Aurita::GUI::Form, "basic rendering" do
|
|
22
22
|
|
23
23
|
it "should wrap form fields as list elements (<li>...</li>)" do
|
24
24
|
@form.add(@text_field)
|
25
|
-
@form.to_s.should == '<form><ul class="form_fields"><li class="input_field_wrap form_field" id="textfield_wrap"><input type="text" name="textfield" id="textfield" /></li></ul></form>'
|
25
|
+
@form.to_s.should == '<form method="POST" enctype="multipart/form-data"><ul class="form_fields"><li class="input_field_wrap form_field" id="textfield_wrap"><input type="text" name="textfield" id="textfield" /></li></ul></form>'
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
data/spec/html.rb
CHANGED
@@ -8,7 +8,7 @@ describe Aurita::GUI::HTML, "basic rendering" do
|
|
8
8
|
before do
|
9
9
|
@e = HTML.build {
|
10
10
|
div(:class => :outer) {
|
11
|
-
h2(:id => :header)
|
11
|
+
h2('Header', :id => :header) +
|
12
12
|
p(:id => :content) { 'Content' }
|
13
13
|
}
|
14
14
|
}
|
@@ -23,6 +23,13 @@ describe Aurita::GUI::HTML, "basic rendering" do
|
|
23
23
|
HTML.p { 'string' }.to_s.should == '<p>string</p>'
|
24
24
|
end
|
25
25
|
|
26
|
+
it "should also accept the first constructor argument as content" do
|
27
|
+
e = HTML.p 'I am the content'
|
28
|
+
e.to_s.should == Element.new(:tag => :p) { 'I am the content' }.to_s
|
29
|
+
e = HTML.div 'foo', :class => 'highlight'
|
30
|
+
e.to_s.should == '<div class="highlight">foo</div>'
|
31
|
+
end
|
32
|
+
|
26
33
|
it "should provide a build mechanism that delegates class methods" do
|
27
34
|
@e.to_s = '<div class="outer"><h2 id="header">Header</h2><p id="content">Content</p></div>'
|
28
35
|
end
|
data/spec/javascript.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
require('rubygems')
|
3
|
+
require('aurita-gui/javascript')
|
4
|
+
|
5
|
+
include Aurita::GUI
|
6
|
+
|
7
|
+
describe Aurita::GUI::Javascript, "basic rendering" do
|
8
|
+
before do
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should provide a nice DSL" do
|
12
|
+
js = Javascript.build { |j|
|
13
|
+
j.Some.Namespace.do_stuff()
|
14
|
+
j.bla(123, { :gna => 23, :blu => '42' })
|
15
|
+
j.alert("escape 'this' string")
|
16
|
+
}
|
17
|
+
js.to_s.should == "Some.Namespace.do_stuff(); bla(123,{gna: 23, blu: '42'}); alert('escape \\'this\\' string'); "
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should render on class method calls" do
|
21
|
+
Javascript.Some.Namespace.do_stuff(23, 'wombat').to_s.should == "Some.Namespace.do_stuff(23,'wombat'); "
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aurita-gui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Fuchs
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-25 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- LICENSE
|
36
36
|
- lib/aurita-gui
|
37
37
|
- lib/aurita-gui.rb
|
38
|
+
- lib/aurita-gui/javascript.rb
|
38
39
|
- lib/aurita-gui/button.rb
|
39
40
|
- lib/aurita-gui/form.rb
|
40
41
|
- lib/aurita-gui/html.rb
|
@@ -55,9 +56,10 @@ files:
|
|
55
56
|
- lib/aurita-gui/form/radio_field.rb
|
56
57
|
- lib/aurita-gui/form/hidden_field.rb
|
57
58
|
- lib/aurita-gui/form/text_field.rb
|
59
|
+
- lib/aurita-gui/form/template_helper.rb
|
58
60
|
- lib/aurita-gui/form/input_field.rb
|
59
61
|
- lib/aurita-gui/form/date_field.rb
|
60
|
-
- spec
|
62
|
+
- spec/javascript.rb
|
61
63
|
- spec/form.rb
|
62
64
|
- spec/html.rb
|
63
65
|
- spec/element.rb
|