aurita-gui 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|