mir_extensions 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +2 -1
  3. data/Gemfile.lock +18 -2
  4. data/Rakefile +1 -1
  5. data/VERSION +1 -1
  6. data/app/controllers/foos_controller.rb +83 -0
  7. data/app/helpers/application_helper.rb +1 -0
  8. data/app/models/foo.rb +2 -0
  9. data/app/views/foos/_form.html.erb +20 -0
  10. data/app/views/foos/edit.html.erb +6 -0
  11. data/app/views/foos/index.html.erb +27 -0
  12. data/app/views/foos/new.html.erb +5 -0
  13. data/app/views/foos/show.html.erb +20 -0
  14. data/config.ru +1 -1
  15. data/config/application.rb +5 -1
  16. data/config/environment.rb +1 -1
  17. data/config/environments/development.rb +1 -1
  18. data/config/environments/test.rb +1 -1
  19. data/config/initializers/secret_token.rb +1 -1
  20. data/config/initializers/session_store.rb +1 -1
  21. data/config/routes.rb +5 -2
  22. data/db/migrate/20100801224509_create_foos.rb +16 -0
  23. data/db/mir_ext_development.sqlite3 +0 -0
  24. data/db/mir_ext_test.sqlite3 +0 -0
  25. data/db/schema.rb +11 -1
  26. data/lib/core_ext/core_ext.rb +1 -2
  27. data/lib/mir_extensions.rb +386 -2
  28. data/lib/mir_form_builder.rb +166 -0
  29. data/mir_extensions.gemspec +29 -7
  30. data/public/stylesheets/scaffold.css +56 -0
  31. data/spec/controllers/foos_controller_spec.rb +125 -0
  32. data/spec/routing/foos_routing_spec.rb +35 -0
  33. data/spec/support/integration_example_group.rb +35 -0
  34. data/spec/views/foos/edit.html.erb_spec.rb +61 -0
  35. data/spec/views/foos/index.html.erb_spec.rb +25 -0
  36. data/spec/views/foos/new.html.erb_spec.rb +22 -0
  37. data/spec/views/foos/show.html.erb_spec.rb +18 -0
  38. metadata +29 -7
  39. data/lib/core_ext/helper_extensions.rb +0 -383
  40. data/log/development.log +0 -151
  41. data/log/test.log +0 -27
  42. data/public/index.html +0 -262
data/.gitignore CHANGED
@@ -17,5 +17,8 @@ tmtags
17
17
  coverage
18
18
  rdoc
19
19
  pkg
20
+ log
21
+ tmp
22
+ test
20
23
 
21
24
  ## PROJECT::SPECIFIC
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ gem 'rails', '3.0.0.rc'
6
6
  # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
7
 
8
8
  gem 'friendly_id'
9
- gem 'mir_extensions'
9
+ gem 'mir_extensions', '>= 0.3.0'
10
10
  gem 'sqlite3-ruby', :require => 'sqlite3'
11
11
  gem 'jeweler'
12
12
  gem 'gemcutter'
@@ -38,4 +38,5 @@ group :test do
38
38
  gem 'rspec-rails', '>= 2.0.0.beta.10'
39
39
  gem "machinist", '>= 2.0.0.beta1'
40
40
  gem "mocha"
41
+ gem "capybara", ">= 0.3.9"
41
42
  end
@@ -32,10 +32,20 @@ GEM
32
32
  activesupport (>= 3.0.0.beta)
33
33
  babosa (0.1.0)
34
34
  builder (2.1.2)
35
+ capybara (0.3.9)
36
+ culerity (>= 0.2.4)
37
+ mime-types (>= 1.16)
38
+ nokogiri (>= 1.3.3)
39
+ rack (>= 1.0.0)
40
+ rack-test (>= 0.5.4)
41
+ selenium-webdriver (>= 0.0.3)
42
+ culerity (0.2.10)
35
43
  diff-lcs (1.1.2)
36
44
  erubis (2.6.6)
37
45
  abstract (>= 1.0.0)
38
46
  faker (0.3.1)
47
+ ffi (0.6.3)
48
+ rake (>= 0.8.7)
39
49
  friendly_id (3.1.1.1)
40
50
  babosa (>= 0.1.0)
41
51
  gemcutter (0.6.1)
@@ -52,7 +62,7 @@ GEM
52
62
  mime-types
53
63
  treetop (>= 1.4.5)
54
64
  mime-types (1.16)
55
- mir_extensions (0.1.0)
65
+ mir_extensions (0.3.0)
56
66
  mocha (0.9.8)
57
67
  rake
58
68
  nokogiri (1.4.3.1)
@@ -89,6 +99,11 @@ GEM
89
99
  webrat (>= 0.7.2.beta.1)
90
100
  rubyforge (2.0.4)
91
101
  json_pure (>= 1.1.7)
102
+ rubyzip (0.9.4)
103
+ selenium-webdriver (0.0.27)
104
+ ffi (>= 0.6.1)
105
+ json_pure
106
+ rubyzip
92
107
  sqlite3-ruby (1.3.1)
93
108
  thor (0.14.0)
94
109
  treetop (1.4.8)
@@ -103,12 +118,13 @@ PLATFORMS
103
118
  ruby
104
119
 
105
120
  DEPENDENCIES
121
+ capybara (>= 0.3.9)
106
122
  faker
107
123
  friendly_id
108
124
  gemcutter
109
125
  jeweler
110
126
  machinist (>= 2.0.0.beta1)
111
- mir_extensions
127
+ mir_extensions (>= 0.3.0)
112
128
  mocha
113
129
  rails (= 3.0.0.rc)
114
130
  rspec (>= 2.0.0.beta.19)
data/Rakefile CHANGED
@@ -47,4 +47,4 @@ Rake::RDocTask.new do |rdoc|
47
47
  end
48
48
 
49
49
  require File.expand_path('../config/application', __FILE__)
50
- MirExtensions::Application.load_tasks
50
+ MirExtensionsContainer::Application.load_tasks
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 1.0.0
@@ -0,0 +1,83 @@
1
+ class FoosController < ApplicationController
2
+ # GET /foos
3
+ # GET /foos.xml
4
+ def index
5
+ @foos = Foo.all
6
+
7
+ respond_to do |format|
8
+ format.html # index.html.erb
9
+ format.xml { render :xml => @foos }
10
+ end
11
+ end
12
+
13
+ # GET /foos/1
14
+ # GET /foos/1.xml
15
+ def show
16
+ @foo = Foo.find(params[:id])
17
+
18
+ respond_to do |format|
19
+ format.html # show.html.erb
20
+ format.xml { render :xml => @foo }
21
+ end
22
+ end
23
+
24
+ # GET /foos/new
25
+ # GET /foos/new.xml
26
+ def new
27
+ @foo = Foo.new
28
+
29
+ respond_to do |format|
30
+ format.html # new.html.erb
31
+ format.xml { render :xml => @foo }
32
+ end
33
+ end
34
+
35
+ # GET /foos/1/edit
36
+ def edit
37
+ @foo = Foo.find(params[:id])
38
+ end
39
+
40
+ # POST /foos
41
+ # POST /foos.xml
42
+ def create
43
+ @foo = Foo.new(params[:foo])
44
+
45
+ respond_to do |format|
46
+ if @foo.save
47
+ format.html { redirect_to(@foo, :notice => 'Foo was successfully created.') }
48
+ format.xml { render :xml => @foo, :status => :created, :location => @foo }
49
+ else
50
+ format.html { render :action => "new" }
51
+ format.xml { render :xml => @foo.errors, :status => :unprocessable_entity }
52
+ end
53
+ end
54
+ end
55
+
56
+ # PUT /foos/1
57
+ # PUT /foos/1.xml
58
+ def update
59
+ @foo = Foo.find(params[:id])
60
+
61
+ respond_to do |format|
62
+ if @foo.update_attributes(params[:foo])
63
+ format.html { redirect_to(@foo, :notice => 'Foo was successfully updated.') }
64
+ format.xml { head :ok }
65
+ else
66
+ format.html { render :action => "edit" }
67
+ format.xml { render :xml => @foo.errors, :status => :unprocessable_entity }
68
+ end
69
+ end
70
+ end
71
+
72
+ # DELETE /foos/1
73
+ # DELETE /foos/1.xml
74
+ def destroy
75
+ @foo = Foo.find(params[:id])
76
+ @foo.destroy
77
+
78
+ respond_to do |format|
79
+ format.html { redirect_to(foos_url) }
80
+ format.xml { head :ok }
81
+ end
82
+ end
83
+ end
@@ -1,2 +1,3 @@
1
1
  module ApplicationHelper
2
2
  end
3
+
@@ -0,0 +1,2 @@
1
+ class Foo < ActiveRecord::Base
2
+ end
@@ -0,0 +1,20 @@
1
+ <%= form_for(@foo) do |f| %>
2
+ <% if @foo.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(@foo.errors.count, "error") %> prohibited this foo from being saved:</h2>
5
+
6
+ <ul>
7
+ <% @foo.errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <%= f.text_field :name %>
15
+ <%= f.check_box :active, :label => 'Status', :inline_label => 'Active' %>
16
+ <%= f.select :style, [select_prompt, "foo", "bar"], :label => 'Select a Style' %>
17
+ <%= f.date_select :due_date, :order => [:month, :day, :year] -%>
18
+ <%= f.submit %>
19
+
20
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing foo</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', @foo %> |
6
+ <%= link_to 'Back', foos_path %>
@@ -0,0 +1,27 @@
1
+ <h1>Listing foos</h1>
2
+
3
+ <table>
4
+ <tr>
5
+ <th>Name</th>
6
+ <th>Active</th>
7
+ <th>Style</th>
8
+ <th></th>
9
+ <th></th>
10
+ <th></th>
11
+ </tr>
12
+
13
+ <% @foos.each do |foo| %>
14
+ <tr>
15
+ <td><%= foo.name %></td>
16
+ <td><%= foo.active %></td>
17
+ <td><%= foo.style %></td>
18
+ <td><%= link_to 'Show', foo %></td>
19
+ <td><%= link_to 'Edit', edit_foo_path(foo) %></td>
20
+ <td><%= link_to 'Destroy', foo, :confirm => 'Are you sure?', :method => :delete %></td>
21
+ </tr>
22
+ <% end %>
23
+ </table>
24
+
25
+ <br />
26
+
27
+ <%= link_to 'New Foo', new_foo_path %>
@@ -0,0 +1,5 @@
1
+ <h1>New foo</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', foos_path %>
@@ -0,0 +1,20 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <b>Name:</b>
5
+ <%= @foo.name %>
6
+ </p>
7
+
8
+ <p>
9
+ <b>Active:</b>
10
+ <%= @foo.active %>
11
+ </p>
12
+
13
+ <p>
14
+ <b>Style:</b>
15
+ <%= @foo.style %>
16
+ </p>
17
+
18
+
19
+ <%= link_to 'Edit', edit_foo_path(@foo) %> |
20
+ <%= link_to 'Back', foos_path %>
data/config.ru CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is used by Rack-based servers to start the application.
2
2
 
3
3
  require ::File.expand_path('../config/environment', __FILE__)
4
- run MirExtensions::Application
4
+ run MirExtensionsContainer::Application
@@ -1,12 +1,13 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
3
  require 'rails/all'
4
+ require 'lib/mir_form_builder'
4
5
 
5
6
  # If you have a Gemfile, require the gems listed there, including any gems
6
7
  # you've limited to :test, :development, or :production.
7
8
  Bundler.require(:default, Rails.env) if defined?(Bundler)
8
9
 
9
- module MirExtensions
10
+ module MirExtensionsContainer
10
11
  class Application < Rails::Application
11
12
  # Settings in config/environments/* take precedence over those specified here.
12
13
  # Application configuration should go into files in config/initializers
@@ -39,9 +40,12 @@ module MirExtensions
39
40
  # Configure sensitive parameters which will be filtered from the log file.
40
41
  config.filter_parameters += [:password]
41
42
 
43
+ config.action_view.default_form_builder = MirExtensions::MirFormBuilder
44
+
42
45
  config.generators do |g|
43
46
  g.test_framework :rspec
44
47
  end
45
48
 
46
49
  end
47
50
  end
51
+
@@ -2,4 +2,4 @@
2
2
  require File.expand_path('../application', __FILE__)
3
3
 
4
4
  # Initialize the rails application
5
- MirExtensions::Application.initialize!
5
+ MirExtensionsContainer::Application.initialize!
@@ -1,4 +1,4 @@
1
- MirExtensions::Application.configure do
1
+ MirExtensionsContainer::Application.configure do
2
2
  # Settings specified here will take precedence over those in config/environment.rb
3
3
 
4
4
  # In the development environment your application's code is reloaded on
@@ -1,4 +1,4 @@
1
- MirExtensions::Application.configure do
1
+ MirExtensionsContainer::Application.configure do
2
2
  # Settings specified here will take precedence over those in config/environment.rb
3
3
 
4
4
  # The test environment is used exclusively to run your application's
@@ -4,4 +4,4 @@
4
4
  # If you change this key, all old signed cookies will become invalid!
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
- MirExtensions::Application.config.secret_token = 'df016d1dd6851037860d1dc3e9abfc4c3b1c99169dfdd03a19c00d243f8d3507fd0b17376371a8bd472797b093afd885a5dd9e5bc10c36475c432ea212437ecc'
7
+ MirExtensionsContainer::Application.config.secret_token = 'df016d1dd6851037860d1dc3e9abfc4c3b1c99169dfdd03a19c00d243f8d3507fd0b17376371a8bd472797b093afd885a5dd9e5bc10c36475c432ea212437ecc'
@@ -1,6 +1,6 @@
1
1
  # Be sure to restart your server when you modify this file.
2
2
 
3
- MirExtensions::Application.config.session_store :cookie_store, :key => '_MirExtensions_session'
3
+ MirExtensionsContainer::Application.config.session_store :cookie_store, :key => '_MirExtensions_session'
4
4
 
5
5
  # Use the database for sessions instead of the cookie-based default,
6
6
  # which shouldn't be used to store highly confidential information
@@ -1,4 +1,7 @@
1
- MirExtensions::Application.routes.draw do
1
+ MirExtensionsContainer::Application.routes.draw do
2
+
3
+ resources :foos
4
+
2
5
  # The priority is based upon order of creation:
3
6
  # first created -> highest priority.
4
7
 
@@ -48,7 +51,7 @@ MirExtensions::Application.routes.draw do
48
51
 
49
52
  # You can have the root of your site routed with "root"
50
53
  # just remember to delete public/index.html.
51
- # root :to => "welcome#index"
54
+ root :to => "foos#index"
52
55
 
53
56
  # See how all your routes lay out with "rake routes"
54
57
 
@@ -0,0 +1,16 @@
1
+ class CreateFoos < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :foos do |t|
4
+ t.string :name
5
+ t.boolean :active
6
+ t.string :style
7
+ t.datetime :due_date
8
+ t.string :country
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :foos
15
+ end
16
+ end
Binary file
@@ -10,7 +10,17 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 0) do
13
+ ActiveRecord::Schema.define(:version => 20100801224509) do
14
+
15
+ create_table "foos", :force => true do |t|
16
+ t.string "name"
17
+ t.boolean "active"
18
+ t.string "style"
19
+ t.datetime "due_date"
20
+ t.string "country"
21
+ t.datetime "created_at"
22
+ t.datetime "updated_at"
23
+ end
14
24
 
15
25
  create_table "primaries", :force => true do |t|
16
26
  t.string "name"
@@ -250,8 +250,7 @@ class ActiveRecord::Base
250
250
 
251
251
  #FIXME Extending AR in this way will stop working under Rails 2.3.2 for some reason.
252
252
 
253
- # scope :order_by, lambda{ |col, dir| {:order => (col.blank?) ? ( (dir.blank?) ? 'id' : dir ) : "#{col} #{dir}"} }
254
- # scope :limit, lambda { |num| { :limit => num } }
253
+ scope :order_by, lambda{ |col, dir| {:order => (col.blank?) ? ( (dir.blank?) ? 'id' : dir ) : "#{col} #{dir}"} }
255
254
 
256
255
  # TODO: call the column_names class method on the subclass
257
256
  # named_scope :sort_by, lambda{ |col, dir| {:order => (col.blank?) ? ( (dir.blank?) ? (Client.column_names.include?('name') ? 'name' : 'id') : h(dir) ) : "#{h(col)} #{h(dir)}"} }
@@ -1,9 +1,9 @@
1
1
  require 'singleton'
2
- require File.expand_path(File.dirname(__FILE__) + '/core_ext/core_ext')
3
2
  require 'friendly_id'
3
+ require 'core_ext/core_ext'
4
4
 
5
5
  module MirExtensions
6
-
6
+
7
7
  # Constants ======================================================================================
8
8
 
9
9
  MONTHS = {0 => "JAN", 1 => "FEB", 2 => "MAR", 3 => "APR", 4 => "MAY", 5 => "JUN", 6 => "JUL", 7 => "AUG", 8 => "SEP", 9 => "OCT", 10 => "NOV", 11 => "DEC"}
@@ -33,5 +33,389 @@ module MirExtensions
33
33
  def self.state_name_for(abbreviation)
34
34
  STATE_CODES.invert[abbreviation]
35
35
  end
36
+
37
+ module HelperExtensions
38
+
39
+ def action?( expression )
40
+ !! ( expression.class == Regexp ? controller.action_name =~ expression : controller.action_name == expression )
41
+ end
42
+
43
+ # Formats an array with HTML line breaks, or the specified delimiter.
44
+ def array_to_lines(array, delimiter = '<br />')
45
+ array.blank? ? nil : array * delimiter
46
+ end
47
+
48
+ def checkmark
49
+ %{<div class="checkmark"></div>}.html_safe
50
+ end
51
+
52
+ def controller?( expression )
53
+ !! ( expression.class == Regexp ? controller.controller_name =~ expression : controller.controller_name == expression )
54
+ end
55
+
56
+ # Display CRUD icons or links, according to setting in use_crud_icons method.
57
+ #
58
+ # In application_helper.rb:
59
+ #
60
+ # def use_crud_icons
61
+ # true
62
+ # end
63
+ #
64
+ # Then use in index views like this:
65
+ #
66
+ # <td class="crud_links"><%= crud_links(my_model, 'my_model', [:show, :edit, :delete]) -%></td>
67
+ #
68
+ def crud_links(model, instance_name, actions, args={})
69
+ _html = ""
70
+ _options = args.keys.empty? ? '' : ", #{args.map{|k,v| ":#{k} => #{v}"}}"
71
+
72
+ if use_crud_icons
73
+ if actions.include?(:show)
74
+ _html << eval("link_to image_tag('/images/icons/view.png', :class => 'crud_icon'), model, :title => 'View'#{_options}")
75
+ end
76
+ if actions.include?(:edit)
77
+ _html << eval("link_to image_tag('/images/icons/edit.png', :class => 'crud_icon'), edit_#{instance_name}_path(model), :title => 'Edit'#{_options}")
78
+ end
79
+ if actions.include?(:delete)
80
+ _html << eval("link_to image_tag('/images/icons/delete.png', :class => 'crud_icon'), model, :confirm => 'Are you sure? This action cannot be undone.', :method => :delete, :title => 'Delete'#{_options}")
81
+ end
82
+ else
83
+ if actions.include?(:show)
84
+ _html << eval("link_to 'View', model, :title => 'View', :class => 'crud_link'#{_options}")
85
+ end
86
+ if actions.include?(:edit)
87
+ _html << eval("link_to 'Edit', edit_#{instance_name}_path(model), :title => 'Edit', :class => 'crud_link'#{_options}")
88
+ end
89
+ if actions.include?(:delete)
90
+ _html << eval("link_to 'Delete', model, :confirm => 'Are you sure? This action cannot be undone.', :method => :delete, :title => 'Delete', :class => 'crud_link'#{_options}")
91
+ end
92
+ end
93
+ _html
94
+ end
95
+
96
+ # Display CRUD icons or links, according to setting in use_crud_icons method.
97
+ # This method works with nested resources.
98
+ # Use in index views like this:
99
+ #
100
+ # <td class="crud_links"><%= crud_links_for_nested_resource(@my_model, my_nested_model, 'my_model', 'my_nested_model', [:show, :edit, :delete]) -%></td>
101
+ #
102
+ def crud_links_for_nested_resource(model, nested_model, model_instance_name, nested_model_instance_name, actions, args={})
103
+ _html = ""
104
+ if use_crud_icons
105
+ if actions.include?(:show)
106
+ _html << eval("link_to image_tag('/images/icons/view.png', :class => 'crud_icon'), #{model_instance_name}_#{nested_model_instance_name}_path(model, nested_model), :title => 'View'")
107
+ end
108
+
109
+ if actions.include?(:edit)
110
+ _html << eval("link_to image_tag('/images/icons/edit.png', :class => 'crud_icon'), edit_#{model_instance_name}_#{nested_model_instance_name}_path(model, nested_model), :title => 'Edit'")
111
+ end
112
+
113
+ if actions.include?(:delete)
114
+ _html << eval("link_to image_tag('/images/icons/delete.png', :class => 'crud_icon'), #{model_instance_name}_#{nested_model_instance_name}_path(model, nested_model), :method => :delete, :confirm => 'Are you sure? This action cannot be undone.', :title => 'Delete'")
115
+ end
116
+ end
117
+ _html
118
+ end
119
+
120
+ # DRY way to return a legend tag that renders correctly in all browsers. This variation allows
121
+ # for more "stuff" inside the legend tag, e.g. expand/collapse controls, without having to worry
122
+ # about escape sequences.
123
+ #
124
+ # Sample usage:
125
+ #
126
+ # <%- legend_block do -%>
127
+ # <span id="hide_or_show_backlinks" class="show_link" style="background-color: #999999;
128
+ # border: 1px solid #999999;" onclick="javascript:hide_or_show('backlinks');"></span>Backlinks (<%=
129
+ # @google_results.size -%>)
130
+ # <%- end -%>
131
+ #
132
+ def legend_block(&block)
133
+ concat content_tag(:div, capture(&block), :class => "faux_legend")
134
+ end
135
+
136
+ # DRY way to return a legend tag that renders correctly in all browsers
137
+ def legend_tag(text, args={})
138
+ _html = %{<div id="#{args[:id]}" class="faux_legend">#{text}</div>\r}
139
+ _html.gsub!(/ id=""/,'')
140
+ _html.gsub!(/ class=""/,'')
141
+ _html
142
+ end
143
+
144
+ def meta_description(content=nil)
145
+ content_for(:meta_description) { content } unless content.blank?
146
+ end
147
+
148
+ def meta_keywords(content=nil)
149
+ content_for(:meta_keywords) { content } unless content.blank?
150
+ end
151
+
152
+ def models_for_select( models, label = 'name' )
153
+ models.map{ |m| [m[label], m.id] }.sort_by{ |e| e[0] }
154
+ end
155
+
156
+ def options_for_array( a, selected = nil, prompt = select_prompt )
157
+ "<option value=''>#{prompt}</option>" + a.map{ |_e| _flag = _e[0].to_s == selected ? 'selected="1"' : ''; _e.is_a?(Array) ? "<option value=\"#{_e[0]}\" #{_flag}>#{_e[1]}</option>" : "<option>#{_e}</option>" }.to_s
158
+ end
159
+
160
+ # Create a link that is opaque to search engine spiders.
161
+ def obfuscated_link_to(path, image, label, args={})
162
+ _html = %{<form action="#{path}" method="get" class="obfuscated_link">}
163
+ _html << %{ <fieldset><input alt="#{label}" src="#{image}" type="image" /></fieldset>}
164
+ args.each{ |k,v| _html << %{ <div><input id="#{k.to_s}" name="#{k}" type="hidden" value="#{v}" /></div>} }
165
+ _html << %{</form>}
166
+ _html
167
+ end
168
+
169
+ # Wraps the given HTML in Rails' default style to highlight validation errors, if any.
170
+ def required_field_helper( model, element, html )
171
+ if model && ! model.errors.empty? && element.is_required
172
+ return content_tag( :div, html, :class => 'fieldWithErrors' )
173
+ else
174
+ return html
175
+ end
176
+ end
177
+
178
+ def select_prompt
179
+ "Select..."
180
+ end
181
+
182
+ def select_prompt_option
183
+ "<option value=''>#{select_prompt}</option>"
184
+ end
185
+
186
+ # Use on index pages to create dropdown list of filtering criteria.
187
+ # Populate the filter list using a constant in the model corresponding to named scopes.
188
+ #
189
+ # Usage:
190
+ #
191
+ # - item.rb:
192
+ #
193
+ # scope :active, :conditions => { :is_active => true }
194
+ # scope :inactive, :conditions => { :is_active => false }
195
+ #
196
+ # FILTERS = [
197
+ # {:scope => "all", :label => "All"},
198
+ # {:scope => "active", :label => "Active Only"},
199
+ # {:scope => "inactive", :label => "Inactive Only"}
200
+ # ]
201
+ #
202
+ # - items/index.html.erb:
203
+ #
204
+ # <%= select_tag_for_filter("items", @filters, params) -%>
205
+ #
206
+ # - items_controller.rb:
207
+ #
208
+ # def index
209
+ # @filters = Item::FILTERS
210
+ # if params[:show] && params[:show] != "all" && @filters.collect{|f| f[:scope]}.include?(params[:show])
211
+ # @items = eval("@items.#{params[:show]}.order_by(params[:by], params[:dir])")
212
+ # else
213
+ # @items = @items.order_by(params[:by], params[:dir])
214
+ # end
215
+ # ...
216
+ # end
217
+ #
218
+ def select_tag_for_filter(model, nvpairs, params)
219
+ return unless model && nvpairs && ! nvpairs.empty?
220
+ options = { :query => params[:query] }
221
+ _url = url_for(eval("#{model}_url(options)"))
222
+ _html = %{<label for="show">Show:</label><br />}
223
+ _html << %{<select name="show" id="show" onchange="window.location='#{_url}' + '?show=' + this.value">}
224
+ nvpairs.each do |pair|
225
+ _html << %{<option value="#{pair[:scope]}"}
226
+ if params[:show] == pair[:scope] || ((params[:show].nil? || params[:show].empty?) && pair[:scope] == "all")
227
+ _html << %{ selected="selected"}
228
+ end
229
+ _html << %{>#{pair[:label]}}
230
+ _html << %{</option>}
231
+ end
232
+ _html << %{</select>}
233
+ end
234
+
235
+ # Returns a link_to tag with sorting parameters that can be used with ActiveRecord.order_by.
236
+ #
237
+ # To use standard resources, specify the resources as a plural symbol:
238
+ # sort_link(:users, 'email', params)
239
+ #
240
+ # To use resources aliased with :as (in routes.rb), specify the aliased route as a string.
241
+ # sort_link('users_admin', 'email', params)
242
+ #
243
+ # You can override the link's label by adding a labels hash to your params in the controller:
244
+ # params[:labels] = {'user_id' => 'User'}
245
+ def sort_link(model, field, params, html_options={})
246
+ if (field.to_sym == params[:by] || field == params[:by]) && params[:dir] == "ASC"
247
+ classname = "arrow-asc"
248
+ dir = "DESC"
249
+ elsif (field.to_sym == params[:by] || field == params[:by])
250
+ classname = "arrow-desc"
251
+ dir = "ASC"
252
+ else
253
+ dir = "ASC"
254
+ end
255
+
256
+ options = {
257
+ :anchor => html_options[:anchor] || nil,
258
+ :by => field,
259
+ :dir => dir,
260
+ :query => params[:query],
261
+ :show => params[:show]
262
+ }
263
+
264
+ options[:show] = params[:show] unless params[:show].blank? || params[:show] == 'all'
265
+
266
+ html_options = {
267
+ :class => "#{classname} #{html_options[:class]}",
268
+ :style => "color: white; font-weight: #{params[:by] == field ? "bold" : "normal"}; #{html_options[:style]}",
269
+ :title => "Sort by this field"
270
+ }
271
+
272
+ field_name = params[:labels] && params[:labels][field] ? params[:labels][field] : field.titleize
273
+
274
+ _link = model.is_a?(Symbol) ? eval("#{model}_url(options)") : "/#{model}?#{options.to_params}"
275
+ link_to(field_name, _link, html_options)
276
+ end
277
+
278
+ # Tabbed interface helpers =======================================================================
279
+
280
+ # Returns formatted tabs with appropriate JS for activation. Use in conjunction with tab_body.
281
+ #
282
+ # Usage:
283
+ #
284
+ # <%- tabset do -%>
285
+ # <%= tab_tag :id => 'ppc_ads', :label => 'PPC Ads', :state => 'active' %>
286
+ # <%= tab_tag :id => 'budget' %>
287
+ # <%= tab_tag :id => 'geotargeting' %>
288
+ # <%- end -%>
289
+ #
290
+ def tabset(&proc)
291
+ concat %{
292
+ <div class="jump_links">
293
+ <ul>
294
+ }
295
+ yield
296
+ concat %{
297
+ </ul>
298
+ </div>
299
+ <br style="clear: both;" /><br />
300
+ <input type="hidden" id="show_tab" />
301
+ <script type="text/javascript">
302
+ function hide_all_tabs() { $$('.tab_block').invoke('hide'); }
303
+ function activate_tab(tab) {
304
+ $$('.tab_control').each(function(elem){ elem.className = 'tab_control'});
305
+ $('show_' + tab).className = 'tab_control active';
306
+ hide_all_tabs();
307
+ $(tab).toggle();
308
+ $('show_tab').value = tab
309
+ }
310
+ function sticky_tab() { if (location.hash) { activate_tab(location.hash.gsub('#','')); } }
311
+ Event.observe(window, 'load', function() { sticky_tab(); });
312
+ </script>
313
+ }
314
+ end
315
+
316
+ # Returns a tab body corresponding to tabs in a tabset. Make sure that the id of the tab_body
317
+ # matches the id provided to the tab_tag in the tabset block.
318
+ #
319
+ # Usage:
320
+ #
321
+ # <%- tab_body :id => 'ppc_ads', :label => 'PPC Ad Details' do -%>
322
+ # PPC ads form here.
323
+ # <%- end -%>
324
+ #
325
+ # <%- tab_body :id => 'budget' do -%>
326
+ # Budget form here.
327
+ # <%- end -%>
328
+ #
329
+ # <%- tab_body :id => 'geotargeting' do -%>
330
+ # Geotargeting form here.
331
+ # <%- end -%>
332
+ #
333
+ def tab_body(args, &proc)
334
+ concat %{<div id="#{args[:id]}" class="tab_block form_container" style="display: #{args[:display] || 'none'};">}
335
+ concat %{#{legend_tag args[:label] || args[:id].titleize }}
336
+ concat %{<a name="#{args[:id]}"></a><br />}
337
+ yield
338
+ concat %{</div>}
339
+ end
340
+
341
+ # Returns the necessary HTML for a particular tab. Use inside a tabset block.
342
+ # Override the default tab label by specifying a :label parameter.
343
+ # Indicate that the tab should be active by setting its :state to 'active'.
344
+ # (NOTE: You must define a corresponding CSS style for active tabs.)
345
+ #
346
+ # Usage:
347
+ #
348
+ # <%= tab_tag :id => 'ppc_ads', :label => 'PPC Ads', :state => 'active' %>
349
+ #
350
+ def tab_tag(args, *css_class)
351
+ %{<li id="show_#{args[:id]}" class="tab_control #{args[:state]}" onclick="window.location='##{args[:id]}'; activate_tab('#{args[:id]}');">#{args[:label] || args[:id].to_s.titleize}</li>}
352
+ end
353
+
354
+ # ================================================================================================
355
+
356
+ def tag_for_collapsible_row(obj, params)
357
+ _html = ""
358
+ if obj && obj.respond_to?(:parent) && obj.parent
359
+ _html << %{<tr class="#{obj.class.name.downcase}_#{obj.parent.id} #{params[:class]}" style="display: none; #{params[:style]}">}
360
+ else
361
+ _html << %{<tr class="#{params[:class]}" style="#{params[:style]}">}
362
+ end
363
+ _html
364
+ end
365
+
366
+ def tag_for_collapsible_row_control(obj)
367
+ _base_id = "#{obj.class.name.downcase}_#{obj.id}"
368
+ _html = %{<div id="hide_or_show_#{_base_id}" class="show_link" style="background-color: #999999; border: 1px solid #999999;" onclick="javascript:hide_or_show('#{_base_id}');"></div>}
369
+ end
370
+
371
+ # Create a set of tags for displaying a field label with inline help.
372
+ # Field label text is appended with a ? icon, which responds to a click
373
+ # by showing or hiding the provided help text.
374
+ #
375
+ # Sample usage:
376
+ #
377
+ # <%= tag_for_label_with_inline_help 'Relative Frequency', 'rel_frequency', 'Relative frequency of search traffic for this keyword across multiple search engines, as measured by WordTracker.' %>
378
+ #
379
+ # Yields:
380
+ #
381
+ # <label for="rel_frequency">Relative Frequency: <%= image_tag "/images/help_icon.png", :onclick => "$('rel_frequency_help').toggle();", :class => 'inline_icon' %></label><br />
382
+ # <div class="inline_help" id="rel_frequency_help" style="display: none;">
383
+ # <p>Relative frequency of search traffic for this keyword across multiple search engines, as measured by WordTracker.</p>
384
+ # </div>
385
+ def tag_for_label_with_inline_help( label_text, field_id, help_text )
386
+ _html = ""
387
+ _html << %{<label for="#{field_id}">#{label_text}}
388
+ _html << %{<img src="/images/icons/help_icon.png" onclick="$('#{field_id}_help').toggle();" class='inline_icon' />}
389
+ _html << %{</label><br />}
390
+ _html << %{<div class="inline_help" id="#{field_id}_help" style="display: none;">}
391
+ _html << %{<p>#{help_text}</p>}
392
+ _html << %{</div>}
393
+ _html
394
+ end
395
+
396
+ # Create a set of tags for displaying a field label followed by instructions.
397
+ # The instructions are displayed on a new line following the field label.
398
+ #
399
+ # Usage:
400
+ #
401
+ # <%= tag_for_label_with_instructions 'Status', 'is_active', 'Only active widgets will be visible to the public.' %>
402
+ #
403
+ # Yields:
404
+ #
405
+ # <label for="is_active">
406
+ # Status<br />
407
+ # <span class="instructions">Only active widgets will be visible to the public.</span>
408
+ # <label><br />
409
+ def tag_for_label_with_instructions( label_text, field_id, instructions )
410
+ _html = ""
411
+ _html << %{<label for="#{field_id}">#{label_text}}
412
+ _html << %{<span class="instructions">#{instructions}</span>}
413
+ _html << %{</label><br />}
414
+ _html
415
+ end
416
+
417
+ end
36
418
 
37
419
  end
420
+
421
+ ActionView::Base.send :include, MirExtensions::HelperExtensions