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.
- data/.gitignore +3 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +18 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/app/controllers/foos_controller.rb +83 -0
- data/app/helpers/application_helper.rb +1 -0
- data/app/models/foo.rb +2 -0
- data/app/views/foos/_form.html.erb +20 -0
- data/app/views/foos/edit.html.erb +6 -0
- data/app/views/foos/index.html.erb +27 -0
- data/app/views/foos/new.html.erb +5 -0
- data/app/views/foos/show.html.erb +20 -0
- data/config.ru +1 -1
- data/config/application.rb +5 -1
- data/config/environment.rb +1 -1
- data/config/environments/development.rb +1 -1
- data/config/environments/test.rb +1 -1
- data/config/initializers/secret_token.rb +1 -1
- data/config/initializers/session_store.rb +1 -1
- data/config/routes.rb +5 -2
- data/db/migrate/20100801224509_create_foos.rb +16 -0
- data/db/mir_ext_development.sqlite3 +0 -0
- data/db/mir_ext_test.sqlite3 +0 -0
- data/db/schema.rb +11 -1
- data/lib/core_ext/core_ext.rb +1 -2
- data/lib/mir_extensions.rb +386 -2
- data/lib/mir_form_builder.rb +166 -0
- data/mir_extensions.gemspec +29 -7
- data/public/stylesheets/scaffold.css +56 -0
- data/spec/controllers/foos_controller_spec.rb +125 -0
- data/spec/routing/foos_routing_spec.rb +35 -0
- data/spec/support/integration_example_group.rb +35 -0
- data/spec/views/foos/edit.html.erb_spec.rb +61 -0
- data/spec/views/foos/index.html.erb_spec.rb +25 -0
- data/spec/views/foos/new.html.erb_spec.rb +22 -0
- data/spec/views/foos/show.html.erb_spec.rb +18 -0
- metadata +29 -7
- data/lib/core_ext/helper_extensions.rb +0 -383
- data/log/development.log +0 -151
- data/log/test.log +0 -27
- data/public/index.html +0 -262
data/.gitignore
CHANGED
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
|
data/Gemfile.lock
CHANGED
@@ -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.
|
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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
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
|
data/app/models/foo.rb
ADDED
@@ -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,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,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
data/config/application.rb
CHANGED
@@ -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
|
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
|
+
|
data/config/environment.rb
CHANGED
data/config/environments/test.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
data/config/routes.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
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
|
-
|
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
|
data/db/mir_ext_test.sqlite3
CHANGED
Binary file
|
data/db/schema.rb
CHANGED
@@ -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 =>
|
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"
|
data/lib/core_ext/core_ext.rb
CHANGED
@@ -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
|
-
|
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)}"} }
|
data/lib/mir_extensions.rb
CHANGED
@@ -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
|