merb-ui 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Jamie Hoover
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,77 @@
1
+ Installation:
2
+
3
+ 1.) Install merb-ui gem.
4
+ git clone git://github.com/uipoet/merb-ui.git
5
+ cd merb-ui
6
+ sudo rake install
7
+
8
+ 2.) Navigate to your merb application.
9
+ cd ~/your_merb_app/
10
+
11
+ 3.) Copy assets to your merb application.
12
+ rake slices:merb_ui:copy_assets
13
+
14
+ 4.) Add to your dependencies file.
15
+ vim config/dependencies.rb
16
+ a
17
+
18
+ dependency 'merb-ui'
19
+
20
+ esc : wq
21
+
22
+ 5.) Add options to your init file in the before_app_loads callback.
23
+ vim config/init.rb
24
+ a
25
+
26
+ Merb::BootLoader.before_app_loads do
27
+ Merb::Slices::config[:merb_ui][:owner] = 'Your Name' #Owner in the Copyright.
28
+ Merb::Slices::config[:merb_ui][:year] = 2000 #Year in the Copyright.
29
+ end
30
+
31
+ esc : wq
32
+
33
+ 6.) Add to your router file.
34
+ vim config/router.rb
35
+ a
36
+
37
+ slice(:merb_ui)
38
+
39
+ esc : wq
40
+
41
+ 7.) Add to your application layout file.
42
+ vim app/views/layout/application.html.erb
43
+ a
44
+
45
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
46
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
47
+ <head>
48
+ <title>Your Merb Application</title>
49
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
50
+ <%= mui_head %>
51
+ </head>
52
+ <body>
53
+ <%= mui_body do %>
54
+ <%= mui_bar(:tab_width => '6em') do %>
55
+ <%= mui_tab(:title => merb_words_title, :controller => 'merb_words/pages', :url => url(:merb_words_index)) %><%= mui_tab(:title => merb_photos_title, :controller => 'merb_photos/photos', :url => url(:merb_photos_index)) %><%= mui_tab(:title => 'Projects', :controller => 'projects', :url => url(:projects)) %>
56
+ <% end =%>
57
+ <% end =%>
58
+ </body>
59
+ </html>
60
+
61
+ esc : wq
62
+
63
+
64
+ ------------------------------------------------------------------------------
65
+
66
+ Advanced:
67
+
68
+ # List all available tasks:
69
+ rake -T slices:merb_ui
70
+
71
+ # Put your application-level overrides in:
72
+ host-app/slices/merb-ui/
73
+
74
+ # Templates are located in this order:
75
+ 1. host-app/slices/merb-ui/app/views/*
76
+ 2. gems/merb-ui/app/views/*
77
+ 3. host-app/app/views/*
data/Rakefile ADDED
@@ -0,0 +1,71 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ require 'merb-core'
5
+ require 'merb-core/tasks/merb'
6
+
7
+ GEM_NAME = "merb-ui"
8
+ AUTHOR = "uipoet"
9
+ EMAIL = "dont.tase@me.com"
10
+ HOMEPAGE = "http://uipoet.com/"
11
+ SUMMARY = "User interface components for Merb."
12
+ GEM_VERSION = "0.1"
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.rubyforge_project = "mui"
16
+ s.name = GEM_NAME
17
+ s.version = GEM_VERSION
18
+ s.platform = Gem::Platform::RUBY
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = ["README", "LICENSE"]
21
+ s.summary = SUMMARY
22
+ s.description = s.summary
23
+ s.author = AUTHOR
24
+ s.email = EMAIL
25
+ s.homepage = HOMEPAGE
26
+ s.add_dependency('merb-slices', '~> 1.0.0')
27
+ s.add_dependency('merb-helpers', '~> 1.0.0')
28
+ s.require_path = 'lib'
29
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{lib,app,public}/**/*")
30
+ end
31
+
32
+ Rake::GemPackageTask.new(spec) do |pkg|
33
+ pkg.gem_spec = spec
34
+ end
35
+
36
+ desc "Install the gem"
37
+ task :install do
38
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
39
+ end
40
+
41
+ desc "Uninstall the gem"
42
+ task :uninstall do
43
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
44
+ end
45
+
46
+ desc "Release the gem to rubyforge"
47
+ task :release do
48
+ require 'rubyforge'
49
+ require 'rake/contrib/rubyforgepublisher'
50
+ sh %{rake package}
51
+ packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{GEM_NAME}-#{GEM_VERSION}.#{ext}" }
52
+ begin
53
+ sh %{rubyforge login}
54
+ sh %{rubyforge add_release #{AUTHOR} #{GEM_NAME} #{GEM_VERSION} #{packages.join(' ')}}
55
+ sh %{rubyforge add_file #{AUTHOR} #{GEM_NAME} #{GEM_VERSION} #{packages.join(' ')}}
56
+ rescue Exception => e
57
+ puts "Release failed: #{e.message}"
58
+ end
59
+ end
60
+
61
+ desc "Create a gemspec file"
62
+ task :gemspec do
63
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
64
+ file.puts spec.to_ruby
65
+ end
66
+ end
67
+
68
+ require 'spec/rake/spectask'
69
+ require 'merb-core/test/tasks/spectasks'
70
+ desc 'Default: run spec examples'
71
+ task :default => 'spec'
@@ -0,0 +1,5 @@
1
+ class MerbUi::Application < Merb::Controller
2
+
3
+ controller_for_slice
4
+
5
+ end
@@ -0,0 +1,24 @@
1
+ class MerbUi::Styles < MerbUi::Application
2
+
3
+ only_provides :css
4
+
5
+ def index
6
+ if mui_browser == 'gecko'
7
+ @browser = selector('*::-moz-focus-inner') do
8
+ property('border', :value => 'none')
9
+ property('padding', :value => 0)
10
+ end
11
+ elsif mui_browser == 'msie'
12
+ @browser = selector('*.mui_button') do
13
+ property('overflow', :value => 'visible')
14
+ property('width', :value => 'auto')
15
+ end
16
+ end
17
+ render :layout => false
18
+ end
19
+
20
+ Merb::BootLoader.after_app_loads do
21
+ Merb.add_mime_type(:css, :to_css, %w[text/css])
22
+ end
23
+
24
+ end
@@ -0,0 +1,60 @@
1
+ module Merb::MerbUi::ApplicationHelper
2
+
3
+ # @param *segments<Array[#to_s]> Path segments to append.
4
+ #
5
+ # @return <String>
6
+ # A path relative to the public directory, with added segments.
7
+ def image_path(*segments)
8
+ public_path_for(:image, *segments)
9
+ end
10
+
11
+ # @param *segments<Array[#to_s]> Path segments to append.
12
+ #
13
+ # @return <String>
14
+ # A path relative to the public directory, with added segments.
15
+ def javascript_path(*segments)
16
+ public_path_for(:javascript, *segments)
17
+ end
18
+
19
+ # @param *segments<Array[#to_s]> Path segments to append.
20
+ #
21
+ # @return <String>
22
+ # A path relative to the public directory, with added segments.
23
+ def stylesheet_path(*segments)
24
+ public_path_for(:stylesheet, *segments)
25
+ end
26
+
27
+ # Construct a path relative to the public directory
28
+ #
29
+ # @param <Symbol> The type of component.
30
+ # @param *segments<Array[#to_s]> Path segments to append.
31
+ #
32
+ # @return <String>
33
+ # A path relative to the public directory, with added segments.
34
+ def public_path_for(type, *segments)
35
+ ::MerbUi.public_path_for(type, *segments)
36
+ end
37
+
38
+ # Construct an app-level path.
39
+ #
40
+ # @param <Symbol> The type of component.
41
+ # @param *segments<Array[#to_s]> Path segments to append.
42
+ #
43
+ # @return <String>
44
+ # A path within the host application, with added segments.
45
+ def app_path_for(type, *segments)
46
+ ::MerbUi.app_path_for(type, *segments)
47
+ end
48
+
49
+ # Construct a slice-level path.
50
+ #
51
+ # @param <Symbol> The type of component.
52
+ # @param *segments<Array[#to_s]> Path segments to append.
53
+ #
54
+ # @return <String>
55
+ # A path within the slice source (Gem), with added segments.
56
+ def slice_path_for(type, *segments)
57
+ ::MerbUi.slice_path_for(type, *segments)
58
+ end
59
+
60
+ end
@@ -0,0 +1,318 @@
1
+ module Merb::GlobalHelpers
2
+
3
+ def mui_bar(options = {}, &block)
4
+ @@mui_bar_tab_width = options[:tab_width] if options[:tab_width]
5
+ tag(:div, capture(&block), :class => 'mui_bar')
6
+ end
7
+
8
+ def mui_block(options = {}, &block)
9
+ attributes = {}
10
+ attributes[:align] = options[:align] if options[:align]
11
+ attributes[:class] = 'mui_block'
12
+ if type = options[:type]
13
+ if type == 'inline'
14
+ tag_type = :span
15
+ else
16
+ tag_type = :div
17
+ attributes[:class] << %{ mui_block_#{type}}
18
+ end
19
+ else
20
+ tag_type = :div
21
+ end
22
+ if options[:height] || options[:width]
23
+ attributes[:style] = ''
24
+ attributes[:style] << %{height:#{options[:height]};} if options[:height]
25
+ attributes[:style] << %{width:#{options[:width]};} if options[:width]
26
+ end
27
+ content = ''
28
+ content << mui_title(:title => options[:title], :title_size => options[:title_size]) if options[:title]
29
+ content << capture(&block) if block_given?
30
+ tag(tag_type, content, attributes)
31
+ end
32
+
33
+ def mui_body(options = {}, &block)
34
+ attributes={}
35
+ attributes[:class] = 'mui_desktop'
36
+ attributes[:class] << ' mui_gallery' if controller_name == 'merb_photos/photos'
37
+ output = ''
38
+ if message = session[:mui_message]
39
+ message_content = mui_button(:title => '&#215;', :message => 'close')
40
+ message_content << message[:title] if message[:title]
41
+ message_content << message[:body] if message[:body]
42
+ output << tag(:div, message_content, :class => %{mui_message mui_message_#{message[:tone]}})
43
+ session.delete(:mui_message)
44
+ end
45
+ output << capture(&block)
46
+ copyright_now = Time.now.year
47
+ copyright_then = MerbUi[:year] || copyright_now
48
+ if copyright_now == copyright_then
49
+ copyright_years = copyright_now
50
+ else
51
+ copyright_years = %{#{copyright_then}-#{copyright_now}}
52
+ end
53
+ copyright_owner = %{ #{MerbUi[:owner]}} if MerbUi[:owner]
54
+ copyright_text = %{Copyright &copy; #{copyright_years}#{copyright_owner}. All rights reserved.}
55
+ copyright = tag(:div, copyright_text, :class => 'mui_copyright')
56
+ output << tag(:div, catch_content(:for_layout) + copyright, attributes)
57
+ output << tag(:div, :class => 'mui_window_target')
58
+ if session[:mui_window]
59
+ output << tag(:script, "windowOpen('#{session[:mui_window]}');", :type => 'text/javascript')
60
+ session.delete(:mui_window)
61
+ end
62
+ output
63
+ end
64
+
65
+ def mui_browser
66
+ browser = request.user_agent
67
+ if browser.include? 'MSIE'
68
+ 'msie'
69
+ elsif browser.include? 'Gecko/'
70
+ 'gecko'
71
+ elsif browser.include? 'AppleWebKit'
72
+ 'webkit'
73
+ else
74
+ 'unknown'
75
+ end
76
+ end
77
+
78
+ def mui_button(options = {}, &block)
79
+ attributes = {}
80
+ attributes[:class] = 'mui_button'
81
+ attributes[:class] << %{ mui_button_tone_#{options[:tone] || 'neutral'}}
82
+ attributes[:class] << ' mui_click'
83
+ attributes[:class] << %{_message_#{options[:message]}} if options[:message]
84
+ attributes[:class] << %{_window_#{options[:window]}} if options[:window]
85
+ attributes[:id] = options[:url] if options[:url]
86
+ attributes[:name] = options[:name] if options[:name]
87
+ attributes[:style] = %{width:#{options[:width]};} if options[:width]
88
+ attributes[:type] = options[:submit] == true ? 'submit' : 'button'
89
+ attributes[:value] = options[:title] if options[:title]
90
+ if block_given?
91
+ if options[:title]
92
+ content = tag(:table, tag(:tr, tag(:td, capture(&block)) + tag(:td, options[:title], :width => '100%')))
93
+ else
94
+ content = capture(&block)
95
+ end
96
+ tag(:button, content, attributes)
97
+ else
98
+ self_closing_tag(:input, attributes)
99
+ end
100
+ end
101
+
102
+ def mui_cell(options = {}, &block)
103
+ return unless block_given?
104
+ @mui_grid[:count] += 1
105
+ attributes = {}
106
+ attributes[:align] = @mui_grid[:align] || options[:align] || nil
107
+ attributes[:nowrap] = 'nowrap' if options[:wrap] == false
108
+ if options[:width]
109
+ attributes[:style] = %{width:#{options[:width]}}
110
+ else
111
+ attributes[:style] = %{width:#{@mui_grid[:width]}} if @mui_grid[:width]
112
+ end
113
+ attributes[:valign] = @mui_grid[:valign] || options[:valign] || 'top'
114
+ html = ''
115
+ if @mui_grid[:count] > @mui_grid[:columns]
116
+ @mui_grid[:count] = 0
117
+ html << close_tag(:tr) + open_tag(:tr)
118
+ end
119
+ html << tag(:td, capture(&block), attributes)
120
+ end
121
+
122
+ def mui_check(name, options = {})
123
+ columns = tag(:td, check_box(name, :class => 'mui_check'))
124
+ columns << tag(:td, tag(:label, options[:title]))
125
+ tag(:table, tag(:tr, columns))
126
+ end
127
+
128
+ def mui_date(name, options = {})
129
+ tag(:div, date_field(name, :label => options[:title]), :class => 'mui_date')
130
+ end
131
+
132
+ def mui_date_span(options = {})
133
+ tag(:span, relative_date_span([options[:created], options[:updated]]), :class => 'mui_date')
134
+ end
135
+
136
+ def mui_delete(options = {})
137
+ attributes = {}
138
+ attributes[:class] = 'mui_button mui_button_tone_negative'
139
+ attributes[:style] = %{width:#{options[:width]};} if options[:width]
140
+ delete_button(options[:url], options[:title], attributes)
141
+ end
142
+
143
+ def mui_divider
144
+ self_closing_tag(:hr, :class => 'mui_divider')
145
+ end
146
+
147
+ def mui_form(name, options = {}, &block)
148
+ form_for(name, options, &block)
149
+ end
150
+
151
+ def mui_grid(options = {}, &block)
152
+ return unless block_given?
153
+ mui_grid_temp = @mui_grid if @mui_grid
154
+ @mui_grid = {}
155
+ @mui_grid[:align] = options[:cell_align]
156
+ @mui_grid[:count] = 0
157
+ @mui_grid[:columns] = options[:columns] || 1
158
+ @mui_grid[:valign] = options[:cell_valign]
159
+ @mui_grid[:width] = options[:cell_width]
160
+ attributes = {}
161
+ attributes[:class] = 'mui_grid'
162
+ attributes[:style] = %{width:#{options[:width]}} if options[:width]
163
+ html = tag(:table, tag(:tr, capture(&block)), attributes)
164
+ @mui_grid = mui_grid_temp if mui_grid_temp
165
+ html
166
+ end
167
+
168
+ def mui_head
169
+ path = '/slices/merb-ui/javascripts/'
170
+ require_css('master', 'mui')
171
+ require_js('jquery', "#{path}ui", "#{path}dimensions", "#{path}keybinder", "#{path}desktop")
172
+ include_required_css + include_required_js + catch_content(:feeds)
173
+ end
174
+
175
+ def mui_hyper_text(name, options = {})
176
+ attributes = {}
177
+ attributes[:class] = 'mui_hyper_text'
178
+ attributes[:class] << ' mui_focus' if options[:focus] == true
179
+ attributes[:label] = options[:title]
180
+ text_area(name, attributes)
181
+ end
182
+
183
+ def mui_image(options={})
184
+ attributes={}
185
+ attributes[:align] = options[:align] if options[:align]
186
+ attributes[:class] = 'mui_image'
187
+ attributes[:class] << ' mui_image_border' if options[:border] == true
188
+ if options[:height] && options[:width]
189
+ attributes[:class] << ' mui_image_rounded' if options[:rounded] == true
190
+ attributes[:src] = '/slices/merb-ui/images/nil.png'
191
+ attributes[:style] = %{background-image: url('#{options[:url]}');}
192
+ attributes[:style] << %{height: #{options[:height]}px;}
193
+ attributes[:style] << %{width: #{options[:width]}px;}
194
+ else
195
+ attributes[:src] = file
196
+ end
197
+ attributes[:class] << ' mui_photo' if options[:photo] == true
198
+ attributes[:class] << ' mui_inline' if options[:inline] == true
199
+ self_closing_tag(:img, attributes)
200
+ end
201
+
202
+ def mui_link(options={}, &block)
203
+ attributes = {}
204
+ attributes[:class] = 'mui_link'
205
+ attributes[:href] = options[:url]
206
+ if block_given?
207
+ content = capture(&block)
208
+ attributes[:title] = options[:title]
209
+ else
210
+ content = options[:title]
211
+ end
212
+ attributes[:style] = %{font-size:#{options[:title_size]};} if options[:title_size]
213
+ tag(:a, content, attributes)
214
+ end
215
+
216
+ def mui_list(parents = [])
217
+ children = ''
218
+ parents.each do |p|
219
+ p.each do |c|
220
+ children << tag(:li, c, :class => 'mui_list_item')
221
+ end
222
+ end
223
+ tag(:ul, children, :class => 'mui_list')
224
+ end
225
+
226
+ def mui_paragraph(options={}, &block)
227
+ tag(:p, (capture(&block) if block_given?), :class => 'mui_paragraph')
228
+ end
229
+
230
+ def mui_password(name, options = {})
231
+ attributes = {}
232
+ attributes[:class] = 'mui_password'
233
+ attributes[:class] << ' mui_focus' if options[:focus] == true
234
+ attributes[:label] = options[:title]
235
+ password_field(name, attributes)
236
+ end
237
+
238
+ def mui_search(options = {})
239
+ attributes = {}
240
+ attributes[:class] = 'mui_search'
241
+ attributes[:name] = :search
242
+ attributes[:style] = %{width:#{options[:width]};} if options[:width]
243
+ attributes[:type] = :text
244
+ attributes[:value] = params[:search]
245
+ box = mui_cell(:valign => 'middle'){self_closing_tag(:input, attributes)}
246
+ button = mui_cell(:align => 'right', :valign => 'middle', :wrap => false){%{#{mui_button(:submit => true, :title => 'Search')}}}
247
+ table = mui_grid(:columns => 2){box + button}
248
+ tag(:form, table, :action => options[:action])
249
+ end
250
+
251
+ def mui_tab(options = {}, &block)
252
+ attributes = {}
253
+ if type = options[:type]
254
+ if type == 'merb_words'
255
+ controller = 'merb_words/pages'
256
+ title = options[:title] || MerbWords[:title] || 'Untitled'
257
+ attributes[:href] = options[:url] || url(:merb_words_index)
258
+ elsif type == 'merb_photos'
259
+ controller = 'merb_photos/photos'
260
+ title = options[:title] || MerbPhotos[:title] || 'Untitled'
261
+ attributes[:href] = options[:url] || url(:merb_photos_index)
262
+ end
263
+ else
264
+ controller = options[:controller] || 'application'
265
+ title = options[:title] || 'Untitled'
266
+ attributes[:href] = options[:url] || '/'
267
+ end
268
+ attributes[:class] = 'mui_tab'
269
+ attributes[:class] << ' mui_selected' if controller == controller_name || options[:selected] == true
270
+ if options[:width]
271
+ attributes[:style] = %{width:#{options[:width]}}
272
+ elsif @@mui_bar_tab_width
273
+ attributes[:style] = %{width:#{@@mui_bar_tab_width}}
274
+ end
275
+ tag(:a, title, attributes)
276
+ end
277
+
278
+ def mui_text(name, options = {})
279
+ attributes = {}
280
+ attributes[:class] = 'mui_text'
281
+ attributes[:class] << ' mui_focus' if options[:focus] == true
282
+ attributes[:label] = options[:title]
283
+ attributes[:maxlength] = options[:length] || 50
284
+ attributes[:style] = %{width:#{options[:width]};} if options[:width]
285
+ text_field(name, attributes)
286
+ end
287
+
288
+ def mui_title(options = {})
289
+ size = options[:title_size] || '1.5em'
290
+ attributes = {}
291
+ attributes[:class] = 'mui_title'
292
+ attributes
293
+ attributes[:style] = %{font-size:#{size}}
294
+ tag(:div, options[:title], attributes)
295
+ end
296
+
297
+ def mui_window(options = {}, &block)
298
+ script = js_include_tag '/slices/merb-ui/javascripts/window'
299
+ bar_content = ''
300
+ bar_content << tag(:td, options[:buttons], :class => 'mui_bar_buttons') if options[:buttons]
301
+ bar_content << tag(:td, options[:title], :class => 'mui_window_title') if options[:title]
302
+ bar_content << tag(:td, mui_button(:title => '&#215;', :window => 'close'), :class => 'mui_window_bar_end')
303
+ bar = tag(:tr, tag(:td, tag(:table, tag(:tr, bar_content), :class => 'mui_window_bar')))
304
+ content = tag(:tr, tag(:td, capture(&block), :class => 'mui_window_content'))
305
+ script + tag(:table, bar + content, :class => 'mui_window')
306
+ end
307
+
308
+ def mui_window_redirect
309
+ url = session[:mui_referer] || '/'
310
+ session.delete(:mui_referer)
311
+ redirect(url)
312
+ end
313
+
314
+ def mui_window_referer
315
+ session[:mui_referer] = request.referer
316
+ end
317
+
318
+ end