merb-ui 0.1

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