├── .ruby-version
├── public
├── javascripts
│ ├── staffers.js
│ ├── jquery.tablesorter.pager.js
│ ├── jquery.tablesorter.min.js
│ ├── donorbanner.js
│ └── jquery.qtip-1.0.0-rc3.min.js
├── favicon.ico
├── images
│ ├── info.png
│ ├── bg_tile.jpg
│ ├── hsd_logo.png
│ ├── main_bg.jpg
│ ├── browsearea.png
│ ├── browsetitle.png
│ ├── cornerpiece.png
│ ├── featurebar.png
│ ├── footerbar.png
│ ├── hsd_logo2.png
│ ├── hsd_star_15.png
│ ├── join_button.png
│ ├── newsearch.png
│ ├── personbar.jpg
│ ├── searchtitle.png
│ ├── sfapp_logo.png
│ ├── sort_arrows.png
│ ├── test-image.jpg
│ ├── toggle-off.png
│ ├── toggle-on.png
│ ├── cornerpiece2.png
│ ├── facebook_icon.png
│ ├── resultstitle.png
│ ├── search_button.png
│ ├── sf_mini_logo.png
│ ├── twitter_icon.png
│ ├── download_button.png
│ ├── findingstaffer.png
│ ├── newsearch_button.png
│ ├── searchbar_tile.jpg
│ ├── sf_mini_nav_bg.jpg
│ └── sfapp_bg_header.jpg
└── css
│ ├── donorbanner.css
│ └── style.css
├── vendor
└── cache
│ ├── bson-4.3.0.gem
│ ├── hashie-3.5.7.gem
│ ├── i18n-0.9.5.gem
│ ├── kgio-2.11.2.gem
│ ├── mongo-1.3.1.gem
│ ├── rack-1.6.10.gem
│ ├── tilt-1.4.1.gem
│ ├── wirble-0.1.3.gem
│ ├── bson_ext-1.3.1.gem
│ ├── builder-3.0.4.gem
│ ├── congress-0.3.0.gem
│ ├── faraday-0.9.2.gem
│ ├── geocoder-1.4.9.gem
│ ├── mongoid-2.0.2.gem
│ ├── sinatra-1.2.6.gem
│ ├── stringex-1.2.2.gem
│ ├── tzinfo-0.3.54.gem
│ ├── unicorn-5.4.0.gem
│ ├── multi_json-1.13.1.gem
│ ├── raindrops-0.19.0.gem
│ ├── safe_yaml-1.0.4.gem
│ ├── mongoid_slug-0.7.2.gem
│ ├── activemodel-3.2.22.5.gem
│ ├── activesupport-3.2.22.5.gem
│ ├── concurrent-ruby-1.0.5.gem
│ ├── multipart-post-2.0.0.gem
│ ├── sinatra-content-for-0.2.gem
│ └── faraday_middleware-0.10.1.gem
├── config.ru.example
├── .gitignore
├── CONTRIBUTING.md
├── config
├── config.yml.example
└── environment.rb
├── unicorn.rb.example
├── Gemfile
├── Rakefile
├── data
├── README.md
├── offices.csv
└── load.rake
├── Gemfile.lock
├── fabfile.py
├── views
├── staffer.erb
├── index.erb
├── _search.erb
├── positions.erb
├── office.erb
├── offices.erb
├── layout.erb
└── faq.erb
├── models.rb
├── README.md
├── csv.rb
├── staffers.rb
└── helpers.rb
/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.2.3
2 |
--------------------------------------------------------------------------------
/public/javascripts/staffers.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/images/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/info.png
--------------------------------------------------------------------------------
/public/images/bg_tile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/bg_tile.jpg
--------------------------------------------------------------------------------
/public/images/hsd_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/hsd_logo.png
--------------------------------------------------------------------------------
/public/images/main_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/main_bg.jpg
--------------------------------------------------------------------------------
/public/images/browsearea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/browsearea.png
--------------------------------------------------------------------------------
/public/images/browsetitle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/browsetitle.png
--------------------------------------------------------------------------------
/public/images/cornerpiece.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/cornerpiece.png
--------------------------------------------------------------------------------
/public/images/featurebar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/featurebar.png
--------------------------------------------------------------------------------
/public/images/footerbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/footerbar.png
--------------------------------------------------------------------------------
/public/images/hsd_logo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/hsd_logo2.png
--------------------------------------------------------------------------------
/public/images/hsd_star_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/hsd_star_15.png
--------------------------------------------------------------------------------
/public/images/join_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/join_button.png
--------------------------------------------------------------------------------
/public/images/newsearch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/newsearch.png
--------------------------------------------------------------------------------
/public/images/personbar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/personbar.jpg
--------------------------------------------------------------------------------
/public/images/searchtitle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/searchtitle.png
--------------------------------------------------------------------------------
/public/images/sfapp_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/sfapp_logo.png
--------------------------------------------------------------------------------
/public/images/sort_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/sort_arrows.png
--------------------------------------------------------------------------------
/public/images/test-image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/test-image.jpg
--------------------------------------------------------------------------------
/public/images/toggle-off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/toggle-off.png
--------------------------------------------------------------------------------
/public/images/toggle-on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/toggle-on.png
--------------------------------------------------------------------------------
/vendor/cache/bson-4.3.0.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/bson-4.3.0.gem
--------------------------------------------------------------------------------
/vendor/cache/hashie-3.5.7.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/hashie-3.5.7.gem
--------------------------------------------------------------------------------
/vendor/cache/i18n-0.9.5.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/i18n-0.9.5.gem
--------------------------------------------------------------------------------
/vendor/cache/kgio-2.11.2.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/kgio-2.11.2.gem
--------------------------------------------------------------------------------
/vendor/cache/mongo-1.3.1.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/mongo-1.3.1.gem
--------------------------------------------------------------------------------
/vendor/cache/rack-1.6.10.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/rack-1.6.10.gem
--------------------------------------------------------------------------------
/vendor/cache/tilt-1.4.1.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/tilt-1.4.1.gem
--------------------------------------------------------------------------------
/vendor/cache/wirble-0.1.3.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/wirble-0.1.3.gem
--------------------------------------------------------------------------------
/public/images/cornerpiece2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/cornerpiece2.png
--------------------------------------------------------------------------------
/public/images/facebook_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/facebook_icon.png
--------------------------------------------------------------------------------
/public/images/resultstitle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/resultstitle.png
--------------------------------------------------------------------------------
/public/images/search_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/search_button.png
--------------------------------------------------------------------------------
/public/images/sf_mini_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/sf_mini_logo.png
--------------------------------------------------------------------------------
/public/images/twitter_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/twitter_icon.png
--------------------------------------------------------------------------------
/vendor/cache/bson_ext-1.3.1.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/bson_ext-1.3.1.gem
--------------------------------------------------------------------------------
/vendor/cache/builder-3.0.4.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/builder-3.0.4.gem
--------------------------------------------------------------------------------
/vendor/cache/congress-0.3.0.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/congress-0.3.0.gem
--------------------------------------------------------------------------------
/vendor/cache/faraday-0.9.2.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/faraday-0.9.2.gem
--------------------------------------------------------------------------------
/vendor/cache/geocoder-1.4.9.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/geocoder-1.4.9.gem
--------------------------------------------------------------------------------
/vendor/cache/mongoid-2.0.2.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/mongoid-2.0.2.gem
--------------------------------------------------------------------------------
/vendor/cache/sinatra-1.2.6.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/sinatra-1.2.6.gem
--------------------------------------------------------------------------------
/vendor/cache/stringex-1.2.2.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/stringex-1.2.2.gem
--------------------------------------------------------------------------------
/vendor/cache/tzinfo-0.3.54.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/tzinfo-0.3.54.gem
--------------------------------------------------------------------------------
/vendor/cache/unicorn-5.4.0.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/unicorn-5.4.0.gem
--------------------------------------------------------------------------------
/public/images/download_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/download_button.png
--------------------------------------------------------------------------------
/public/images/findingstaffer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/findingstaffer.png
--------------------------------------------------------------------------------
/public/images/newsearch_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/newsearch_button.png
--------------------------------------------------------------------------------
/public/images/searchbar_tile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/searchbar_tile.jpg
--------------------------------------------------------------------------------
/public/images/sf_mini_nav_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/sf_mini_nav_bg.jpg
--------------------------------------------------------------------------------
/public/images/sfapp_bg_header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/public/images/sfapp_bg_header.jpg
--------------------------------------------------------------------------------
/vendor/cache/multi_json-1.13.1.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/multi_json-1.13.1.gem
--------------------------------------------------------------------------------
/vendor/cache/raindrops-0.19.0.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/raindrops-0.19.0.gem
--------------------------------------------------------------------------------
/vendor/cache/safe_yaml-1.0.4.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/safe_yaml-1.0.4.gem
--------------------------------------------------------------------------------
/vendor/cache/mongoid_slug-0.7.2.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/mongoid_slug-0.7.2.gem
--------------------------------------------------------------------------------
/vendor/cache/activemodel-3.2.22.5.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/activemodel-3.2.22.5.gem
--------------------------------------------------------------------------------
/vendor/cache/activesupport-3.2.22.5.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/activesupport-3.2.22.5.gem
--------------------------------------------------------------------------------
/vendor/cache/concurrent-ruby-1.0.5.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/concurrent-ruby-1.0.5.gem
--------------------------------------------------------------------------------
/vendor/cache/multipart-post-2.0.0.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/multipart-post-2.0.0.gem
--------------------------------------------------------------------------------
/vendor/cache/sinatra-content-for-0.2.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/sinatra-content-for-0.2.gem
--------------------------------------------------------------------------------
/vendor/cache/faraday_middleware-0.10.1.gem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/propublica/staffers/HEAD/vendor/cache/faraday_middleware-0.10.1.gem
--------------------------------------------------------------------------------
/config.ru.example:
--------------------------------------------------------------------------------
1 | ENV['RACK_ENV'] = "development"
2 |
3 | require 'rubygems'
4 | require 'bundler/setup'
5 |
6 | require './staffers'
7 | run Sinatra::Application
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /config/config.yml
2 | /data/csv
3 | /config.ru
4 |
5 | /vendor/gems
6 |
7 | .DS_Store
8 | *.pyc
9 | *.swp
10 | *.txt
11 | *.pid
12 |
13 | /unicorn.rb
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ### Contributing
2 |
3 | By submitting a pull request to this repository, you're agreeing to license your contribution under this project's [LICENSE](LICENSE).
--------------------------------------------------------------------------------
/config/config.yml.example:
--------------------------------------------------------------------------------
1 | sunlight_api_key: # fill in
2 |
3 | mongoid:
4 | host: localhost
5 | database: staffers
6 | raise_not_found_error: false
7 | logger: # leaving blank suppresses logging, to enable delete this line
--------------------------------------------------------------------------------
/unicorn.rb.example:
--------------------------------------------------------------------------------
1 | worker_processes 1 # this should be >= nr_cpus
2 | pid "/path/to/unicorn.pid"
3 |
4 | working_directory "/path/to/staffers"
5 |
6 | # in production, direct all logs to /dev/null
7 | # (this happens by default on daemonization anyway)
8 | stdout_path "/dev/null"
9 | stderr_path "/dev/null"
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'congress'
4 |
5 | gem 'sinatra', '1.2.6'
6 | gem 'sinatra-content-for', '0.2'
7 |
8 | gem 'safe_yaml'
9 |
10 | gem "mongo", "1.3.1"
11 | gem "mongoid", '2.0.2'
12 | gem "mongoid_slug", '0.7.2'
13 | gem 'bson_ext', '1.3.1'
14 |
15 | group :development do
16 | gem 'wirble'
17 | gem 'unicorn'
18 | end
19 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | desc 'Loads environment'
2 | task :environment do
3 | require 'rubygems'
4 | require 'bundler/setup'
5 | require './config/environment'
6 | end
7 |
8 | load 'data/load.rake'
9 |
10 | task create_indexes: :environment do
11 | [Quarter, Staffer, Title, Office, Position].each do |klass|
12 | klass.create_indexes
13 | puts "Created indexes for #{klass}."
14 | end
15 | end
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | require 'sinatra'
2 | require 'mongoid'
3 | require 'mongoid/slug'
4 | require 'safe_yaml'
5 |
6 | def config
7 | @config ||= YAML.safe_load_file File.join(File.dirname(__FILE__), "config.yml")
8 | end
9 |
10 | configure do
11 | Mongoid.configure {|c| c.from_hash config['mongoid']}
12 | SafeYAML::OPTIONS[:default_mode] = :safe
13 | end
14 |
15 | require './models'
--------------------------------------------------------------------------------
/data/README.md:
--------------------------------------------------------------------------------
1 | This directory expects four CSV files:
2 |
3 | * `staffers.csv` - Unique staffer names as they appear in the original disbursement data, and any standardizations or corrections to those titles.
4 | * `titles.csv` - Unique titles as they appear in the original disbursement data, and any standardizations or corrections to those titles.
5 | * `offices.csv` - Unique office names as they appear in the original disbursement data, and any standardizations or corrections to those titles. Expanded details for each office (committee ID, building, room, telephone number) are added by hand.
6 | * `positions.csv` - The "join table" that links staffer names, title names, and office names together as a "position" for each quarter.
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | activemodel (3.2.22.5)
5 | activesupport (= 3.2.22.5)
6 | builder (~> 3.0.0)
7 | activesupport (3.2.22.5)
8 | i18n (~> 0.6, >= 0.6.4)
9 | multi_json (~> 1.0)
10 | bson (4.3.0)
11 | bson_ext (1.3.1)
12 | builder (3.0.4)
13 | concurrent-ruby (1.0.5)
14 | congress (0.3.0)
15 | faraday (~> 0.9.0)
16 | faraday_middleware (~> 0.10.0)
17 | geocoder (~> 1.2)
18 | hashie (~> 3.0)
19 | faraday (0.9.2)
20 | multipart-post (>= 1.2, < 3)
21 | faraday_middleware (0.10.1)
22 | faraday (>= 0.7.4, < 1.0)
23 | geocoder (1.4.9)
24 | hashie (3.5.7)
25 | i18n (0.9.5)
26 | concurrent-ruby (~> 1.0)
27 | kgio (2.11.2)
28 | mongo (1.3.1)
29 | bson (>= 1.3.1)
30 | mongoid (2.0.2)
31 | activemodel (~> 3.0)
32 | mongo (~> 1.3)
33 | tzinfo (~> 0.3.22)
34 | mongoid_slug (0.7.2)
35 | mongoid (~> 2.0.0)
36 | stringex (~> 1.2.0)
37 | multi_json (1.13.1)
38 | multipart-post (2.0.0)
39 | rack (1.6.10)
40 | raindrops (0.19.0)
41 | safe_yaml (1.0.4)
42 | sinatra (1.2.6)
43 | rack (~> 1.1)
44 | tilt (>= 1.2.2, < 2.0)
45 | sinatra-content-for (0.2)
46 | sinatra
47 | stringex (1.2.2)
48 | tilt (1.4.1)
49 | tzinfo (0.3.54)
50 | unicorn (5.4.0)
51 | kgio (~> 2.6)
52 | raindrops (~> 0.7)
53 | wirble (0.1.3)
54 |
55 | PLATFORMS
56 | ruby
57 |
58 | DEPENDENCIES
59 | bson_ext (= 1.3.1)
60 | congress
61 | mongo (= 1.3.1)
62 | mongoid (= 2.0.2)
63 | mongoid_slug (= 0.7.2)
64 | safe_yaml
65 | sinatra (= 1.2.6)
66 | sinatra-content-for (= 0.2)
67 | unicorn
68 | wirble
69 |
70 | BUNDLED WITH
71 | 1.15.1
72 |
--------------------------------------------------------------------------------
/fabfile.py:
--------------------------------------------------------------------------------
1 | import time
2 | from fabric.api import run, execute, env
3 |
4 | env.use_ssh_config = True
5 | env.hosts = ["staffers@rubyhaus"]
6 |
7 | branch = "master"
8 | repo = "git://github.com/sunlightlabs/staffers.git"
9 |
10 | home = "/projects/staffers"
11 | shared_path = "%s/shared" % home
12 | versions_path = "%s/versions" % home
13 | version_path = "%s/%s" % (versions_path, time.strftime("%Y%m%d%H%M%S"))
14 | current_path = "%s/current" % home
15 |
16 | # how many old releases to be kept at deploy-time
17 | keep = 10
18 |
19 |
20 | ## can be run only as part of deploy
21 |
22 | def checkout():
23 | run('git clone -q -b %s %s %s' % (branch, repo, version_path))
24 |
25 | def links():
26 | run("ln -s %s/config.yml %s/config/config.yml" % (shared_path, version_path))
27 | run("ln -s %s/config.ru %s/config.ru" % (shared_path, version_path))
28 | run("ln -s %s/unicorn.rb %s/unicorn.rb" % (shared_path, version_path))
29 | run("ln -s %s/csv %s/data/csv" % (shared_path, version_path))
30 |
31 | def dependencies():
32 | run("cd %s && bundle install --local" % version_path)
33 |
34 | def create_indexes():
35 | run("cd %s && rake create_indexes" % version_path)
36 |
37 | def make_current():
38 | run('rm -f %s && ln -s %s %s' % (current_path, version_path, current_path))
39 |
40 | def cleanup():
41 | versions = run("ls -x %s" % versions_path).split()
42 | # destroy all but the most recent X
43 | destroy = versions[:-keep]
44 |
45 | for version in destroy:
46 | command = "rm -rf %s/%s" % (versions_path, version)
47 | run(command)
48 |
49 |
50 | ## can be run on their own
51 |
52 | def start():
53 | run("cd %s && unicorn -D -l %s/staffers.sock -c unicorn.rb" % (current_path, shared_path))
54 |
55 | def stop():
56 | run("kill `cat %s/unicorn.pid`" % shared_path)
57 |
58 | def restart():
59 | execute(stop)
60 | execute(start)
61 |
62 | def deploy():
63 | execute(checkout)
64 | execute(links)
65 | execute(dependencies)
66 | execute(create_indexes)
67 | execute(make_current)
68 | execute(restart)
69 | execute(cleanup)
70 |
--------------------------------------------------------------------------------
/data/offices.csv:
--------------------------------------------------------------------------------
1 | OFFICE OF THE SPEAKER,OFFICE OF THE SPEAKER
2 | OFFICE OF THE MAJORITY LEADER,OFFICE OF THE MAJORITY LEADER
3 | OFFICE OF THE MINORITY LEADER,OFFICE OF THE MINORITY LEADER
4 | OFFICE OF THE MAJORITY WHIP,OFFICE OF THE MAJORITY WHIP
5 | OFFICE OF THE MINORITY WHIP,OFFICE OF THE MINORITY WHIP
6 | DEMOCRATIC CAUCUS,DEMOCRATIC CAUCUS
7 | REPUBLICAN CONFERENCE,REPUBLICAN CONFERENCE
8 | CHIEF ADMIN OFCR OF THE HOUSE,CHIEF ADMIN OFCR OF THE HOUSE
9 | CLERK OF THE HOUSE,CLERK OF THE HOUSE
10 | OFFICE OF GENERAL COUNSEL,OFFICE OF GENERAL COUNSEL
11 | SERGEANT AT ARMS,SERGEANT AT ARMS
12 | OFFICE OF THE PARLIAMENTARIAN,OFFICE OF THE PARLIAMENTARIAN
13 | COMPILATION OF PRECEDENTS,COMPILATION OF PRECEDENTS
14 | TECHNICAL ASSISTANTS,TECHNICAL ASSISTANTS
15 | OFFICE OF INSPECTOR GENERAL,OFFICE OF INSPECTOR GENERAL
16 | LAW REVISION COUNSEL,LAW REVISION COUNSEL
17 | LEGISLATIVE COUNSEL,LEGISLATIVE COUNSEL
18 | INTERPARLIAMENTARY AFFAIRS,INTERPARLIAMENTARY AFFAIRS
19 | COMMITTEE ON APPROPRIATIONS,COMMITTEE ON APPROPRIATIONS
20 | COMMITTEE ON BUDGET,COMMITTEE ON BUDGET
21 | COMMITTEE ON AGRICULTURE,COMMITTEE ON AGRICULTURE
22 | ARMED SERVICES COMMITTEE,ARMED SERVICES COMMITTEE
23 | COMMITTEE ON FINANCIAL SERVICE,COMMITTEE ON FINANCIAL SERVICE
24 | COMM ON EDUCATION & WORKFORCE,COMM ON EDUCATION & WORKFORCE
25 | COMMITTEE ON ENERGY & COMMERCE,COMMITTEE ON ENERGY & COMMERCE
26 | COMM ON OVRSIGHT & GOVT REFORM,COMM ON OVRSIGHT & GOVT REFORM
27 | HOUSE ADMINISTRATION,HOUSE ADMINISTRATION
28 | COMMITTEE ON NATURAL RESOURCES,COMMITTEE ON NATURAL RESOURCES
29 | COMMITTEE ON FOREIGN AFFAIRS,COMMITTEE ON FOREIGN AFFAIRS
30 | COMMITTEE ON BENGHAZI,COMMITTEE ON BENGHAZI
31 | COMMITTEE ON JUDICIARY,COMMITTEE ON JUDICIARY
32 | TRANSPORTATION-INFRASTRUCTURE,TRANSPORTATION-INFRASTRUCTURE
33 | COMMITTEE ON RULES,COMMITTEE ON RULES
34 | "COMM ON SCIENCE, SPACE & TECH","COMM ON SCIENCE, SPACE & TECH"
35 | COMMITTEE ON SMALL BUSINESS,COMMITTEE ON SMALL BUSINESS
36 | COMMITTEE ON ETHICS,COMMITTEE ON ETHICS
37 | VETERANS' AFFAIRS,VETERANS' AFFAIRS
38 | COMMITTEE ON WAYS AND MEANS,COMMITTEE ON WAYS AND MEANS
39 | INTELLIGENCE,INTELLIGENCE
40 | HOMELAND SECURITY,HOMELAND SECURITY
41 | GENERAL ADMIN - SPEC & SELECT,GENERAL ADMIN - SPEC & SELECT
42 | HOUSE CHILD CARE CENTER,HOUSE CHILD CARE CENTER
43 | JOINT COMMMITTEE ON TAXATION,JOINT COMMMITTEE ON TAXATION
44 | OFFICE OF CONGRESSIONAL ETHICS,OFFICE OF CONGRESSIONAL ETHICS
45 |
--------------------------------------------------------------------------------
/views/staffer.erb:
--------------------------------------------------------------------------------
1 | <% content_for :footer_id do %>footer-person<% end %>
2 |
3 |
16 |
17 |
18 |
19 |
20 | <%= display_name staffer %>
21 |
22 | Download As CSV
23 |
24 |
25 |
26 | Title
27 | Office
28 | Contact Number
29 | Room/Building
30 | Year/Quarter
31 |
32 |
33 |
34 | <% positions.each do |position| %>
35 |
36 | <%= title_listing position %>
37 |
38 |
39 | <%= position['office']['name'] %>
40 |
41 |
42 |
43 | <%= position['office']['phone'] %>
44 |
45 |
46 | <%= room_for position['office']['building'], position['office']['room'] %>
47 |
48 |
49 | <%= position['quarter'] %>
50 |
51 |
52 | <% end %>
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
New Search
61 | Fill out one or more of the fields below to create a new search.
62 | <%= partial :search, :locals => {:position => "right"} %>
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/models.rb:
--------------------------------------------------------------------------------
1 | class Position
2 | include Mongoid::Document
3 | include Mongoid::Timestamps
4 |
5 | # finding all positions by an office or staffer
6 | index "office.slug"
7 | index "staffer.slug"
8 |
9 | # various search form options
10 | index :quarter
11 | index "title.name"
12 | index "office.member.state"
13 | index "office.member.party"
14 | index "office.member.chamber"
15 | index "staffer.first_name"
16 | index "staffer.last_name"
17 |
18 | validates_presence_of :quarter
19 | end
20 |
21 | class Staffer
22 | include Mongoid::Document
23 | include Mongoid::Timestamps
24 | include Mongoid::Slug
25 |
26 | slug :name
27 | validates_uniqueness_of :slug
28 | index :slug
29 |
30 | field :name
31 | field :original_names, :type => Array
32 | field :first_name
33 | field :last_name
34 |
35 | index :original_names
36 | index [[:last_name, Mongo::ASCENDING], [:first_name, Mongo::ASCENDING]]
37 |
38 | # scope :alphabetical,
39 | end
40 |
41 | class Office
42 | include Mongoid::Document
43 | include Mongoid::Timestamps
44 | include Mongoid::Slug
45 |
46 | index :slug
47 | slug :name
48 | validates_uniqueness_of :slug
49 |
50 | field :original_names, :type => Array
51 | field :name
52 | field :office_type
53 | field :chamber
54 |
55 | index :original_names
56 | index :chamber
57 | index :name
58 | index :office_type
59 |
60 | index "committee.id"
61 | index "member.bioguide_id"
62 |
63 |
64 | scope :members, :where => {:office_type => "member"}
65 | scope :committees, :where => {:office_type => "committee"}
66 | scope :others, :where => {:office_type => "other"}
67 |
68 | scope :house, :where => {:chamber => 'house'}
69 | scope :senate, :where => {:chamber => 'senate'}
70 |
71 | def member?
72 | office_type == 'member'
73 | end
74 |
75 | def committee?
76 | office_type == 'committee'
77 | end
78 |
79 | def other?
80 | office_type == 'other'
81 | end
82 | end
83 |
84 | class Title
85 | include Mongoid::Document
86 | include Mongoid::Timestamps
87 |
88 | field :name
89 | field :original_names, :type => Array
90 |
91 | index :name
92 | index :original_names
93 |
94 | validates_uniqueness_of :name
95 | end
96 |
97 | class Quarter
98 | include Mongoid::Document
99 | include Mongoid::Timestamps
100 |
101 | field :name
102 | index :name
103 |
104 | validates_uniqueness_of :name
105 | end
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## House Staff Directory
2 |
3 | A staff directory for the House of Representatives, using data culled from the House' [quarterly disbursement records](http://disbursements.house.gov/).
4 |
5 | The House publishes each quarter's data by the end of the following quarter, so the records will generally be 3-6 months out of date.
6 |
7 | ### Setup
8 |
9 | Depends on Ruby 1.8.7 - not tested on anything higher. This needs to be updated.
10 |
11 | Install dependencies with bundler:
12 |
13 | ```bash
14 | bundle install
15 | ```
16 |
17 | Copy config.ru:
18 |
19 | ```bash
20 | cp config.ru.example config.ru
21 | ```
22 |
23 | Copy config/config.yml.example:
24 |
25 | ```cp config/config.yml.example config/config.yml ```
26 |
27 | Run with unicorn:
28 |
29 | ```bash
30 | bundle exec unicorn
31 | ```
32 |
33 | ### Loading new staff records
34 |
35 | It's an old, blunt, violent process.
36 |
37 | 1. Get the CSVs generated from the [sunlightlabs/disbursements](https://github.com/sunlightlabs/disbursements) process.
38 |
39 | 2. Put them into the `data/` directory and run:
40 |
41 | ```bash
42 | rake load:all
43 | ```
44 |
45 | 3. Wait for an hour or more as the data is blown away and reloaded from scratch. It's not very efficient, and the website will show incomplete data for that time.
46 |
47 | 4. Update the 'as of' date displayed on the home page in views/index.erb to the last day of the quarter processed.
48 |
49 |
50 | ### data/ expectations
51 |
52 | The `data/` directory expects four CSV files:
53 |
54 | * `staffers.csv`: Unique staffer names as they appear in the original disbursement data, and any standardizations or corrections to those titles.
55 | * `titles.csv`: Unique titles as they appear in the original disbursement data, and any standardizations or corrections to those titles.
56 | * `offices.csv`: Unique office names as they appear in the original disbursement data, and any standardizations or corrections to those titles. Expanded details for each office (committee ID, building, room, telephone number) are added by hand.
57 | * `positions.csv`: The "join table" that links staffer names, title names, and office names together as a "position" for each quarter.
58 |
59 | ### Why not the Senate?
60 |
61 | The [Senate's expenditure data](http://www.senate.gov/legislative/common/generic/report_secsen.htm) is published every 6 months, can be quite out of date, and is much more difficult to parse than the House's.
62 |
63 | Our [parser for the House is here](https://github.com/sunlightlabs/disbursements). The Senate parser is still experimental, but data can be found [here](http://sunlightfoundation.com/blog/2014/08/05/now-its-easier-to-account-for-how-the-senate-spends-your-money/).
64 |
65 | ### License
66 |
67 | Currently [GPLv3](LICENSE).
--------------------------------------------------------------------------------
/views/index.erb:
--------------------------------------------------------------------------------
1 | <% content_for :header do %>
2 |
3 | Finding a staffer has never been easier
4 |
5 | With thousands of Congressional Staffers, finding the right person can be a challenge. Sunlight's House Staff Directory makes it easy to search for Capitol Hill contacts using the latest employee data available from Congress. Because the House is slow to release this information, data is current as of Sept. 30, 2014.
6 | Find your staffer now!
7 |
8 |
9 | <% end %>
10 |
11 | <% content_for :footer_id do %>footer-home<% end %>
12 |
13 |
14 |
15 |
16 |
17 |
18 | Search the Directory
19 | To conduct a search, fill out one or more of the fields below.
20 |
21 | <%= partial :search %>
22 |
23 |
24 |
25 |
26 |
27 | Browse the Directory
28 | Check out just a few of the committees, members, and offices that you can learn more about below.
29 |
30 |
31 |
32 |
33 | <% members.each do |member| %>
34 | <% legislator = member['member'] %>
35 |
36 | <%= member['name'] %>
37 |
38 | (<%= legislator['party']%>) <%= legislator['state']%>-<%= district_for legislator['district'] %>
39 |
40 |
41 | <% end %>
42 |
43 | View All Members
44 |
45 |
46 |
59 |
60 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/views/_search.erb:
--------------------------------------------------------------------------------
1 | <%
2 | id = "directory-search-form"
3 | if defined?(position)
4 | id = "#{id}-#{position}"
5 | end
6 | %>
7 |
8 |
--------------------------------------------------------------------------------
/csv.rb:
--------------------------------------------------------------------------------
1 | require 'csv'
2 |
3 | def csv?
4 | (params[:format] == 'csv') or (params[:captures] and (params[:captures][0] == '.csv'))
5 | end
6 |
7 | def csv_out(filename)
8 | response['Content-Type'] = 'text/csv'
9 | response['Content-Disposition'] = "attachment;filename=#{filename}"
10 | end
11 |
12 |
13 |
14 | def members_to_csv(members)
15 | csv_out 'members.csv'
16 |
17 | CSV.generate do |csv|
18 | csv << [
19 | "Name", "Phone", "Building", "Room",
20 | "Bioguide ID", "Title", "First Name", "Last Name", "Suffix",
21 | "Party", "State", "District", "In Office"
22 | ]
23 |
24 | members.each do |member|
25 | leg = member['member']
26 | csv << [
27 | member.name, member.phone, member.building, member.room,
28 | leg['bioguide_id'], leg['title'], leg['firstname'], leg['lastname'], leg['name_suffix'],
29 | leg['party'], leg['state'], leg['district'], leg['in_office']
30 | ]
31 | end
32 | end
33 | end
34 |
35 | def committees_to_csv(committees)
36 | csv_out 'committees.csv'
37 |
38 | CSV.generate do |csv|
39 | csv << [
40 | "Name", "Phone", "Building", "Room",
41 | "Committee ID"
42 | ]
43 |
44 | committees.each do |committee|
45 | csv << [
46 | committee.name, committee.phone, committee.building, committee.room,
47 | committee['committee']['id']
48 | ]
49 | end
50 | end
51 | end
52 |
53 | def offices_to_csv(offices)
54 | csv_out 'offices.csv'
55 |
56 | CSV.generate do |csv|
57 | csv << [
58 | "Name", "Phone", "Building", "Room"
59 | ]
60 |
61 | offices.each do |office|
62 | csv << [office.name, office.phone, office.building, office.room]
63 | end
64 | end
65 | end
66 |
67 | def office_to_csv(office, positions)
68 | names = {'committee' => 'committee', 'member' => 'member', 'other' => 'office'}
69 | csv_out "#{names[office.office_type]}.csv"
70 |
71 | CSV.generate do |csv|
72 | csv << [
73 | "Office", "Quarter", "Staffer", "Title"
74 | ]
75 |
76 | positions.each do |position|
77 | csv << [position['office']['name'], position['quarter'], position['staffer']['name'], position['title']['name']]
78 | end
79 | end
80 | end
81 |
82 | def staffer_to_csv(staffer, positions)
83 | csv_out 'staffer.csv'
84 |
85 | CSV.generate do |csv|
86 | csv << [
87 | "Staffer", "Quarter", "Title", "Office", "Phone", "Building", "Room"
88 | ]
89 |
90 | positions.each do |position|
91 | csv << [staffer.name, position['quarter'], position['title']['name'], position['office']['name'], position['office']['phone'], position['office']['building'], position['office']['room']]
92 | end
93 | end
94 | end
95 |
96 | def positions_to_csv(positions)
97 | csv_out 'positions.csv'
98 |
99 | CSV.generate do |csv|
100 | csv << [
101 | "Staffer", "Quarter", "Title", "Office", "Phone", "Building", "Room"
102 | ]
103 |
104 | positions.each do |position|
105 | csv << [position['staffer']['name'], position['quarter'], position['title']['name'], position['office']['name'], position['office']['phone'], position['office']['building'], position['office']['room']]
106 | end
107 | end
108 | end
--------------------------------------------------------------------------------
/views/positions.erb:
--------------------------------------------------------------------------------
1 | <% content_for :header_class do %>header-internal<% end %>
2 | <% content_for :footer_id do %>footer-internal<% end %>
3 |
4 |
30 |
31 |
32 |
33 | <% if positions %>
34 |
35 |
36 |
Toggle
37 |
38 |
Your Search Results
39 |
40 |
Fill out one or more of the fields below to revise your search.
42 |
43 |
44 | <%= partial :search, :locals => {:position => "internal"} %>
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | <% if positions.any? %>
53 |
54 |
55 | Download As CSV
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Name
65 | Year/Quarter
66 | Title/Position
67 | Office
68 | Contact Number
69 | Office/Building
70 |
71 |
72 |
73 |
74 | <% positions.each do |position| %>
75 |
76 |
77 |
78 | <%= display_name position['staffer'] %>
79 |
80 |
81 | <%= position['quarter'] %>
82 | <%= title_listing position %>
83 |
84 |
85 | <%= position['office']['name'] %>
86 |
87 |
88 |
89 | <%= position['office']['phone'] %>
90 |
91 |
92 | <%= room_for position['office']['building'], position['office']['room'] %>
93 |
94 |
95 | <% end %>
96 |
97 |
98 |
99 |
100 | <% else %>
101 |
102 |
103 | No staffers found for that search.
104 |
105 |
106 | <% end %>
107 |
108 |
109 |
110 | <% else %>
111 |
112 |
113 | You need to specify at least one field in your search.
114 |
115 |
116 | <% end %>
117 |
118 |
--------------------------------------------------------------------------------
/views/office.erb:
--------------------------------------------------------------------------------
1 | <% content_for :footer_id do %>footer-person<% end %>
2 |
3 |
15 |
16 | <% if office['office_type'] != 'member' %>
17 |
18 |
19 |
20 | <%= office['name'] %>
21 |
22 | Download As CSV
23 |
24 |
25 |
26 |
27 | <% else %>
28 |
29 | <% member = office['member'] %>
30 |
31 |
32 |
33 |
34 |
35 |
66 |
67 |
68 |
69 |
70 | Staffers for <%= office['name'] %>
71 |
72 | Download As CSV
73 |
74 | <% end %>
75 |
76 |
77 |
78 |
79 |
80 |
81 | Name
82 | Title/Position
83 | Year/Quarter
84 |
85 |
86 |
87 |
88 | <% positions.each do |position| %>
89 |
90 |
91 | <%= list_name position['staffer'] %>
92 |
93 |
94 | <%= title_listing position %>
95 |
96 |
97 | <%= position['quarter'] %>
98 |
99 |
100 | <% end %>
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
New Search
110 | Fill out one or more of the fields below to create a new search.
111 |
112 | <%= partial :search, :locals => {:position => 'right'} %>
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/public/javascripts/jquery.tablesorter.pager.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 | $.extend({
3 | tablesorterPager: new function() {
4 |
5 | function updatePageDisplay(c) {
6 | var s = $(c.cssPageDisplay,c.container).val((c.page+1) + c.seperator + c.totalPages);
7 | }
8 |
9 | function setPageSize(table,size) {
10 | var c = table.config;
11 | c.size = size;
12 | c.totalPages = Math.ceil(c.totalRows / c.size);
13 | c.pagerPositionSet = false;
14 | moveToPage(table);
15 | fixPosition(table);
16 | }
17 |
18 | function fixPosition(table) {
19 | var c = table.config;
20 | if(!c.pagerPositionSet && c.positionFixed) {
21 | var c = table.config, o = $(table);
22 | if(o.offset) {
23 | c.container.css({
24 | top: o.offset().top + o.height() + 'px',
25 | position: 'absolute'
26 | });
27 | }
28 | c.pagerPositionSet = true;
29 | }
30 | }
31 |
32 | function moveToFirstPage(table) {
33 | var c = table.config;
34 | c.page = 0;
35 | moveToPage(table);
36 | }
37 |
38 | function moveToLastPage(table) {
39 | var c = table.config;
40 | c.page = (c.totalPages-1);
41 | moveToPage(table);
42 | }
43 |
44 | function moveToNextPage(table) {
45 | var c = table.config;
46 | c.page++;
47 | if(c.page >= (c.totalPages-1)) {
48 | c.page = (c.totalPages-1);
49 | }
50 | moveToPage(table);
51 | }
52 |
53 | function moveToPrevPage(table) {
54 | var c = table.config;
55 | c.page--;
56 | if(c.page <= 0) {
57 | c.page = 0;
58 | }
59 | moveToPage(table);
60 | }
61 |
62 |
63 | function moveToPage(table) {
64 | var c = table.config;
65 | if(c.page < 0 || c.page > (c.totalPages-1)) {
66 | c.page = 0;
67 | }
68 |
69 | renderTable(table,c.rowsCopy);
70 | }
71 |
72 | function renderTable(table,rows) {
73 |
74 | var c = table.config;
75 | var l = rows.length;
76 | var s = (c.page * c.size);
77 | var e = (s + c.size);
78 | if(e > rows.length ) {
79 | e = rows.length;
80 | }
81 |
82 |
83 | var tableBody = $(table.tBodies[0]);
84 |
85 | // clear the table body
86 |
87 | $.tablesorter.clearTableBody(table);
88 |
89 | for(var i = s; i < e; i++) {
90 |
91 | //tableBody.append(rows[i]);
92 |
93 | var o = rows[i];
94 | var l = o.length;
95 | for(var j=0; j < l; j++) {
96 |
97 | tableBody[0].appendChild(o[j]);
98 |
99 | }
100 | }
101 |
102 | fixPosition(table,tableBody);
103 |
104 | $(table).trigger("applyWidgets");
105 |
106 | if( c.page >= c.totalPages ) {
107 | moveToLastPage(table);
108 | }
109 |
110 | updatePageDisplay(c);
111 | }
112 |
113 | this.appender = function(table,rows) {
114 |
115 | var c = table.config;
116 |
117 | c.rowsCopy = rows;
118 | c.totalRows = rows.length;
119 | c.totalPages = Math.ceil(c.totalRows / c.size);
120 |
121 | renderTable(table,rows);
122 | };
123 |
124 | this.defaults = {
125 | size: 10,
126 | offset: 0,
127 | page: 0,
128 | totalRows: 0,
129 | totalPages: 0,
130 | container: null,
131 | cssNext: '.next',
132 | cssPrev: '.prev',
133 | cssFirst: '.first',
134 | cssLast: '.last',
135 | cssPageDisplay: '.pagedisplay',
136 | cssPageSize: '.pagesize',
137 | seperator: "/",
138 | positionFixed: true,
139 | appender: this.appender
140 | };
141 |
142 | this.construct = function(settings) {
143 |
144 | return this.each(function() {
145 |
146 | config = $.extend(this.config, $.tablesorterPager.defaults, settings);
147 |
148 | var table = this, pager = config.container;
149 |
150 | $(this).trigger("appendCache");
151 |
152 | config.size = parseInt($(".pagesize",pager).val());
153 |
154 | $(config.cssFirst,pager).click(function() {
155 | moveToFirstPage(table);
156 | return false;
157 | });
158 | $(config.cssNext,pager).click(function() {
159 | moveToNextPage(table);
160 | return false;
161 | });
162 | $(config.cssPrev,pager).click(function() {
163 | moveToPrevPage(table);
164 | return false;
165 | });
166 | $(config.cssLast,pager).click(function() {
167 | moveToLastPage(table);
168 | return false;
169 | });
170 | $(config.cssPageSize,pager).change(function() {
171 | setPageSize(table,parseInt($(this).val()));
172 | return false;
173 | });
174 | });
175 | };
176 |
177 | }
178 | });
179 | // extend plugin scope
180 | $.fn.extend({
181 | tablesorterPager: $.tablesorterPager.construct
182 | });
183 |
184 | })(jQuery);
--------------------------------------------------------------------------------
/staffers.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require './config/environment'
4 | require 'sinatra/content_for'
5 | require './csv'
6 | require './helpers'
7 |
8 |
9 | set :public, 'public'
10 | set :views, 'views'
11 |
12 | # used by the search dropdown
13 | before do
14 | @committees = Office.committees.order_by([[:name, :asc]]).all
15 | @offices = Office.others.order_by([[:name, :asc]]).all
16 | @quarter_names = Quarter.all.distinct(:name).sort.reverse
17 | end
18 |
19 | get '/' do
20 | # first 10 only
21 | members = Office.members.house.order_by([["member.in_office", :desc], ["member.lastname", :asc], ["member.firstname", :asc]]).limit(10).all
22 |
23 | erb :index, locals: {
24 | committees: @committees,
25 | offices: @offices,
26 | members: members
27 | }
28 | end
29 |
30 | get '/faq' do
31 | erb :faq
32 | end
33 |
34 | get '/positions' do
35 | search = {}
36 |
37 | if params[:quarter].present?
38 | search[:quarter] = params[:quarter]
39 | end
40 |
41 | if params[:first_name].present? and params[:first_name].size >= 2
42 | search["staffer.first_name"] = regex_for params[:first_name]
43 | end
44 |
45 | if params[:last_name].present? and params[:last_name].size >= 2
46 | search["staffer.last_name"] = regex_for params[:last_name]
47 | end
48 |
49 | if params[:title].present? and params[:title].size >= 2
50 | search["title.name"] = regex_for params[:title]
51 | end
52 |
53 | if params[:state].present?
54 | search["office.member.state"] = params[:state]
55 | end
56 |
57 | if params[:party].present?
58 | search["office.member.party"] = params[:party]
59 | end
60 |
61 | if params[:office].present?
62 | search["office.slug"] = params[:office]
63 | end
64 |
65 | if params[:committee].present?
66 | search["office.slug"] = params[:committee]
67 | end
68 |
69 | if search.keys.empty?
70 | positions = nil
71 | else
72 | positions = Position.where(search).desc(:quarter)
73 | # positions = positions.limit(50)
74 | end
75 |
76 | if csv?
77 | positions_to_csv positions
78 | else
79 | erb :positions, locals: {positions: positions}
80 | end
81 | end
82 |
83 | get '/staffer/:slug' do
84 | staffer = Staffer.where(:slug => params[:slug]).first
85 | positions = Position.where("staffer.slug" => params[:slug]).all
86 |
87 | if csv?
88 | staffer_to_csv staffer, positions
89 | else
90 | erb :staffer, :locals => {:staffer => staffer, :positions => positions}
91 | end
92 | end
93 |
94 |
95 | # office URLs
96 | get '/office/:slug' do
97 | office = Office.where(:slug => params[:slug]).first
98 | positions = Position.where("office.slug" => params[:slug]).all
99 |
100 | if csv?
101 | office_to_csv office, positions
102 | else
103 | erb :office, :locals => {:office => office, :positions => positions}
104 | end
105 | end
106 |
107 | # support legacy /legislator/ URL
108 | get %r{/(?:member|legislator)/(\w\d+)} do
109 | bioguide_id = params[:captures].first
110 | office = Office.where("member.bioguide_id" => bioguide_id).first
111 | positions = Position.where("office.member.bioguide_id" => bioguide_id).order_by([["staffer.last_name", :asc], ["staffer.first_name", :asc]]).all
112 |
113 | if csv?
114 | office_to_csv office, positions
115 | else
116 | erb :office, :locals => {:office => office, :positions => positions}
117 | end
118 | end
119 |
120 | get '/committee/:committee_id' do
121 | office = Office.where("committee.id" => params[:committee_id]).first
122 |
123 | positions = Position.where("office.committee.id" => params[:committee_id]).order_by([["staffer.last_name", :asc], ["staffer.first_name", :asc]]).all
124 |
125 | if csv?
126 | office_to_csv office, positions
127 | else
128 | erb :office, :locals => {:office => office, :positions => positions}
129 | end
130 | end
131 |
132 |
133 | get '/members' do
134 | conditions = {}
135 |
136 | [:state, :district, :title].each do |key|
137 | if params[key]
138 | conditions["member.#{key}"] = params[key]
139 | end
140 | end
141 |
142 | offices = Office.members.house.where(conditions).order_by([["member.in_office", :desc], ["member.lastname", :asc], ["member.firstname", :asc]]).all
143 |
144 | if csv?
145 | members_to_csv offices
146 | else
147 | erb :offices, :locals => {:offices => offices, :type => 'members'}
148 | end
149 | end
150 |
151 | get '/committees' do
152 | offices = Office.committees.order_by([[:name, :asc]]).all
153 |
154 | if csv?
155 | committees_to_csv offices
156 | else
157 | erb :offices, :locals => {:offices => offices, :type => 'committees'}
158 | end
159 | end
160 |
161 | get '/offices' do
162 | offices = Office.others.order_by([[:name, :asc]]).all
163 |
164 | if csv?
165 | offices_to_csv offices
166 | else
167 | erb :offices, :locals => {:offices => offices, :type => 'offices'}
168 | end
169 | end
170 |
171 |
172 | def regex_for(value)
173 | regex_value = value.dup
174 | %w{+ ? . * ^ $ ( ) [ ] { } | \ }.each {|char| regex_value.gsub! char, "\\#{char}"}
175 | /^#{regex_value}$/i
176 | end
177 |
--------------------------------------------------------------------------------
/views/offices.erb:
--------------------------------------------------------------------------------
1 | <% content_for :footer_id do %>footer-person<% end %>
2 |
3 |
31 |
32 |
33 |
34 |
35 |
36 | <% if type == 'committees' %>
37 | House Committees
38 | <% elsif type == 'offices' %>
39 | House Offices
40 | <% elsif type == 'members' %>
41 | <% if params[:state].present? and params[:district].present? %>
42 | House Members from <%= state_codes[params[:state]] %>, District <%= district_for params[:district] %>
43 | <% elsif params[:state].present? and params[:title].present? %>
44 | <%= plural_title_for params[:title] %> from <%= state_codes[params[:state]] %>
45 | <% elsif params[:state].present? %>
46 | House Members from <%= state_codes[params[:state]] %>
47 | <% else %>
48 | House Members
49 | <% end %>
50 | <% end %>
51 |
52 |
53 |
54 | Download As CSV
55 | " role="main">
56 |
57 |
58 |
59 | <% if type == 'members' %>
60 |
61 | <% end %>
62 |
63 |
64 | <% if type == 'members' %>
65 |
66 | Name
67 | Party
68 | State
69 | In Office
70 |
71 | <% else %>
72 |
73 | Offices
74 | Contact Number
75 | Office/Building
76 |
77 | <% end %>
78 |
79 |
80 |
81 | <% offices.each do |office| %>
82 |
83 | <% if type == 'members' %>
84 |
85 |
86 | <%= member_name office %>
87 |
88 |
89 |
90 | <%= party_names[office['member']['party']] %>
91 |
92 |
93 | <%= office['member']['state'] %><%= office['member']['district'].to_i != 0 ? "-#{office['member']['district']}" : "" %>
94 |
95 |
96 | <% if office['member']['in_office'] %>
97 |
98 | Yes
99 | <% else %>
100 | No
101 | <% end %>
102 |
103 | <% else %>
104 |
105 |
106 | <%= office['name'] %>
107 |
108 |
109 |
110 | <% unless out?(office) %>
111 | <%= office['phone'] %>
112 | <% end %>
113 |
114 |
115 | <% unless out?(office) %>
116 | <%= room_for office['building'], office['room'] %>
117 | <% end %>
118 |
119 | <% end %>
120 |
121 | <% end %>
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
New Search
131 | Fill out one or more of the fields below to create a new search.
132 | <%= partial :search, :locals => {:position => "right"} %>
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/helpers.rb:
--------------------------------------------------------------------------------
1 | helpers do
2 |
3 | def out?(office)
4 | office.office_type == 'member' and office['member']['in_office'] == false
5 | end
6 |
7 | def office_path(office)
8 | if office['office_type'] == "member"
9 | "/member/#{office['member']['bioguide_id']}"
10 | elsif office['office_type'] == "committee"
11 | "/committee/#{office['committee']['id']}"
12 | else
13 | "/office/#{office['slug']}"
14 | end
15 | end
16 |
17 | def member_name(office)
18 | member = office['member']
19 | "#{member['title']}. #{member['nickname'].present? ? member['nickname'] : member['firstname']} #{member['lastname']} #{member['name_suffix']}".strip
20 | end
21 |
22 | def staffer_path(staffer)
23 | "/staffer/#{staffer['slug']}"
24 | end
25 |
26 | def csv_path
27 | "#{request.fullpath}#{request.fullpath['?'] ? "&" : "?"}format=csv"
28 | end
29 |
30 | def capitalize(words)
31 | first_pass = words.split(' ').map {|word| word.capitalize}.join ' '
32 | first_pass.gsub(/\/(\w)/) {" / #{$1.upcase}"}
33 | end
34 |
35 | def title_listing(position)
36 | name = capitalize position['title']['name']
37 | # original_names = title['original_names'].join(" ").gsub("\"", "\\\"")
38 | original_name = position['original_title']
39 |
40 | "#{name} #{original_name}\">i"
41 | end
42 |
43 | def display_name(staffer)
44 | "#{staffer['first_name']} #{staffer['last_name']}".strip
45 | end
46 |
47 | def list_name(staffer)
48 | "#{staffer['last_name']}, #{staffer['first_name']}".strip
49 | end
50 |
51 | def format_quarter(quarter)
52 | pieces = quarter.match /^(\d+)Q(\d)/
53 | year = pieces[1]
54 | quarter = pieces[2]
55 | ordinal = {
56 | "1" => "st",
57 | "2" => "nd",
58 | "3" => "rd",
59 | "4" => "th"
60 | }[quarter]
61 |
62 | "#{year} #{quarter}#{ordinal} Quarter"
63 | end
64 |
65 | def room_for(building, room, long = false)
66 | if building and room
67 | "#{room} #{building.split(' ').first}#{" House Office Building" if long}"
68 | else
69 | nil
70 | end
71 | end
72 |
73 | def district_for(district)
74 | if district.to_i == 0
75 | "At-Large"
76 | else
77 | district
78 | end
79 | end
80 |
81 | def plural_title_for(title)
82 | {
83 | "Del" => "Delegates",
84 | "Sen" => "Senators",
85 | "Com" => "Commissioners",
86 | "Rep" => "Representatives"
87 | }[title]
88 | end
89 |
90 | def state_codes
91 | {
92 | "AL" => "Alabama",
93 | "AK" => "Alaska",
94 | "AZ" => "Arizona",
95 | "AR" => "Arkansas",
96 | "CA" => "California",
97 | "CO" => "Colorado",
98 | "CT" => "Connecticut",
99 | "DE" => "Delaware",
100 | "DC" => "District of Columbia",
101 | "FL" => "Florida",
102 | "GA" => "Georgia",
103 | "HI" => "Hawaii",
104 | "ID" => "Idaho",
105 | "IL" => "Illinois",
106 | "IN" => "Indiana",
107 | "IA" => "Iowa",
108 | "KS" => "Kansas",
109 | "KY" => "Kentucky",
110 | "LA" => "Louisiana",
111 | "ME" => "Maine",
112 | "MD" => "Maryland",
113 | "MA" => "Massachusetts",
114 | "MI" => "Michigan",
115 | "MN" => "Minnesota",
116 | "MS" => "Mississippi",
117 | "MO" => "Missouri",
118 | "MT" => "Montana",
119 | "NE" => "Nebraska",
120 | "NV" => "Nevada",
121 | "NH" => "New Hampshire",
122 | "NJ" => "New Jersey",
123 | "NM" => "New Mexico",
124 | "NY" => "New York",
125 | "NC" => "North Carolina",
126 | "ND" => "North Dakota",
127 | "OH" => "Ohio",
128 | "OK" => "Oklahoma",
129 | "OR" => "Oregon",
130 | "PA" => "Pennsylvania",
131 | "PR" => "Puerto Rico",
132 | "RI" => "Rhode Island",
133 | "SC" => "South Carolina",
134 | "SD" => "South Dakota",
135 | "TN" => "Tennessee",
136 | "TX" => "Texas",
137 | "UT" => "Utah",
138 | "VT" => "Vermont",
139 | "VA" => "Virginia",
140 | "WA" => "Washington",
141 | "WV" => "West Virginia",
142 | "WI" => "Wisconsin",
143 | "WY" => "Wyoming"
144 | }
145 | end
146 |
147 | def party_names
148 | {
149 | "R" => "Republican",
150 | "D" => "Democrat",
151 | "I" => "Independent"
152 | }
153 | end
154 |
155 | def search_titles
156 | [
157 | "Case Worker",
158 | "Chief of Staff",
159 | "Clerk",
160 | "Constituent Liaison",
161 | "Counsel",
162 | "District Director",
163 | "Executive Assistant",
164 | "Legislative Assistant",
165 | "Legislative Correspondent",
166 | "Legislative Director",
167 | "Office Manager",
168 | "Press Secretary",
169 | "Professional Staff",
170 | "Research Assistant",
171 | "Scheduler",
172 | "Staff Assistant",
173 | "System Administrator"
174 | ]
175 | end
176 |
177 | end
178 |
179 | # stolen from http://github.com/cschneid/irclogger/blob/master/lib/partials.rb
180 | # and made a lot more robust by me
181 | # this implementation uses erb by default. if you want to use any other template mechanism
182 | # then replace `erb` on line 13 and line 17 with `haml` or whatever
183 | module Sinatra::Partials
184 | def partial(template, *args)
185 | template_array = template.to_s.split('/')
186 | template = template_array[0..-2].join('/') + "/_#{template_array[-1]}"
187 | options = args.last.is_a?(Hash) ? args.pop : {}
188 | options.merge!(:layout => false)
189 | if collection = options.delete(:collection) then
190 | collection.inject([]) do |buffer, member|
191 | buffer << erb(:"#{template}", options.merge(:layout =>
192 | false, :locals => {template_array[-1].to_sym => member}))
193 | end.join("\n")
194 | else
195 | erb(:"#{template}", options)
196 | end
197 | end
198 | end
199 |
200 | helpers Sinatra::Partials
--------------------------------------------------------------------------------
/views/layout.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | House Staff Directory
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
65 |
66 |
67 |
74 |
75 |
76 |
85 |
86 | <%= yield %>
87 |
88 |
142 |
143 |
158 |
159 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/public/css/donorbanner.css:
--------------------------------------------------------------------------------
1 | /* Donor Banner */
2 | #donor_banner {
3 | display:block;
4 | font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
5 | position: fixed;
6 | z-index: 10000000;
7 | width: 100%;
8 | min-height: 50px;
9 | margin-top: -20px;
10 | padding-top: 20px;
11 | background: #f3ce51 url(http://assets.sunlightfoundation.com.s3.amazonaws.com/donorbanner/donorbanner_border.png) center bottom repeat-x;
12 | top: 0;
13 | left: 0;
14 | transition: all .8s ease-in-out;
15 | -webkit-transition: all .8s ease-in-out; /** Chrome & Safari **/
16 | -moz-transition: all .8s ease-in-out; /** Firefox **/
17 | -o-transition: all .8s ease-in-out; /** Opera **/
18 | -moz-transform: scale(1) rotate(1deg) translate(0px, 288px) skew(0deg, 0deg);
19 | -webkit-transform: scale(1) rotate(1deg) translate(0px, -288px) skew(0deg, 0deg);
20 | -o-transform: scale(1) rotate(1deg) translate(0px, -288px) skew(0deg, 0deg);
21 | -ms-transform: scale(1) rotate(1deg) translate(0px, -288px) skew(0deg, 0deg);
22 | transform: scale(1) rotate(1deg) translate(0px, -288px) skew(0deg, 0deg);
23 | -webkit-box-shadow: 3px 3px 5px #bfb78f;
24 | box-shadow: 3px 3px 5px #bfb78f;
25 | }
26 | .no-csstransforms #donor_banner {
27 | margin-top:-304px;
28 | }
29 |
30 | html.revealbanner {
31 | transition: all .8s ease-in-out;
32 | -webkit-transition: all .8s ease-in-out; /** Chrome & Safari **/
33 | -moz-transition: all .8s ease-in-out; /** Firefox **/
34 | -o-transition: all .8s ease-in-out; /** Opera **/
35 | -moz-transform: translate(0px, 55px);
36 | -webkit-transform: translate(0px, 55px);
37 | -o-transform: translate(0px, 55px);
38 | -ms-transform: translate(0px, 55px);
39 | transform: translate(0px, 55px);
40 | }
41 | html.no-csstransforms.revealbanner {
42 | margin-top: 55px;
43 | }
44 |
45 | html.revealbanner.collapsed {
46 | -moz-transform: translate(0px, 0px);
47 | -webkit-transform: translate(0px, 0px);
48 | -o-transform: translate(0px, 0px);
49 | -ms-transform: translate(0px, 0px);
50 | transform: translate(0px, 0px);
51 | }
52 | html.no-csstransforms.revealbanner.collapsed {
53 | margin-top: 0;
54 | }
55 |
56 | .revealbanner #donor_banner {
57 | margin-top: -20px;
58 | -moz-transform: scale(1) rotate(1deg) translate(0px, -55px) skew(0deg, 0deg);
59 | -webkit-transform: scale(1) rotate(1deg) translate(0px, -55px) skew(0deg, 0deg);
60 | -o-transform: scale(1) rotate(1deg) translate(0px, -55px) skew(0deg, 0deg);
61 | transform: scale(1) rotate(1deg) translate(0px, -55px) skew(0deg, 0deg); /* This order is wrong and important and should stay this way */
62 | -ms-transform: scale(1) rotate(1deg) translate(0px, 0) skew(0deg, 0deg);
63 | -webkit-box-shadow: 3px 3px 5px #bfb78f;
64 | box-shadow: 3px 3px 5px #bfb78f;
65 | }
66 | .revealbanner.collapsed #donor_banner {
67 | -moz-transform: scale(1) rotate(1deg) translate(0px, -200px) skew(0deg, 0deg);
68 | -webkit-transform: scale(1) rotate(1deg) translate(0px, -200px) skew(0deg, 0deg);
69 | -o-transform: scale(1) rotate(1deg) translate(0px, -200px) skew(0deg, 0deg);
70 | -ms-transform: scale(1) rotate(1deg) translate(0px, -200px) skew(0deg, 0deg);
71 | }
72 | .no-csstransforms.revealbanner.collapsed #donor_banner {
73 | margin-top: -194px;
74 | }
75 |
76 | #donor_banner .donorcontainer {
77 | width: 960px;
78 | margin: 0 auto;
79 | -moz-transform: scale(1) rotate(-1deg) translate(0px, 0px) skew(0deg, 0deg);
80 | -webkit-transform: scale(1) rotate(-1deg) translate(0px, 0px) skew(0deg, 0deg);
81 | -o-transform: scale(1) rotate(-1deg) translate(0px, 0px) skew(0deg, 0deg);
82 | -ms-transform: scale(1) rotate(-1deg) translate(0px, 0px) skew(0deg, 0deg);
83 | transform: scale(1) rotate(-1deg) translate(0px, 0px) skew(0deg, 0deg);
84 | }
85 | #donor_banner .sf_logo {
86 | background: url(http://assets.sunlightfoundation.com.s3.amazonaws.com/donorbanner/smalldonor_sf_logo.png) center top no-repeat;
87 | text-indent: -9999em;
88 | display: block;
89 | width: 119px;
90 | height: 54px;
91 | float: left;
92 | margin-left: -10px;
93 | }
94 | #donor_banner .because {
95 | float: left;
96 | width: 487px;
97 | color: #4d5b5c;
98 | font-size: 13px;
99 | text-align: right;
100 | padding: 0 20px 0 5px;
101 | border-right: 1px solid #ffffff;
102 | margin: 10px 0;
103 | line-height: 1.3;
104 | min-height: 72px;
105 | }
106 | #donor_banner .because.quote {
107 | font-style: italic;
108 | }
109 | #donor_banner .attribution {
110 | display: block;
111 | text-align: right;
112 | }
113 | #donor_banner .attribution em{
114 | font-weight: bold;
115 | }
116 | #donor_banner .bubble {
117 | background: url(http://assets.sunlightfoundation.com.s3.amazonaws.com/donorbanner/donorbanner_bubble.png) center bottom no-repeat;
118 | min-height: 330px;
119 | width: 392px;
120 | position: absolute;
121 | right: -55px;
122 | bottom: -288px;
123 | }
124 | .no-csstransforms #donor_banner .bubble {
125 | bottom: -192px;
126 | right: 155px;
127 | }
128 |
129 | #donor_banner .donationplea {
130 | position: absolute;
131 | top: 8px;
132 | right: 0;
133 | width: 287px;
134 | }
135 | .no-csstransforms #donor_banner .donationplea {
136 | top: 18px;
137 | right: 210px;
138 | }
139 |
140 | #donor_banner .donationplea span {
141 | display: block;
142 | }
143 | #donor_banner .donationplea span.line2 {
144 | margin-left: 60px;
145 | }
146 | #donor_banner .donationplea p {
147 | font-size: 16px;
148 | margin-left: 45px;
149 | color: #4d5b5c;
150 | line-height: 1.2;
151 | margin-bottom: 25px;
152 | }
153 | #donor_banner .donationplea p em {
154 | font-weight: bold;
155 | }
156 | #donor_banner .donationplea .btn {
157 | margin-left: 74px;
158 | }
159 | #donor_banner h2 {
160 | font-family: "Georgia", "Times New Roman", "Times", serif;
161 | color: #4d5b5c;
162 | font-style: italic;
163 | text-transform: none;
164 | font-size: 24px;
165 | font-weight: bold;
166 | line-height: 1.3em;
167 | margin-bottom: 25px;
168 | margin-top: 0;
169 | }
170 | #donor_banner .notnow {
171 | background: url(http://assets.sunlightfoundation.com.s3.amazonaws.com/donorbanner/donorbanner_close.png) center top no-repeat;
172 | display: block;
173 | position: absolute;
174 | width: 126px;
175 | height: 36px;
176 | bottom: 4px;
177 | left: 121px;
178 | opacity: 1;
179 | text-align: center;
180 | padding: 9px 0 0 0;
181 | color: #ffffff;
182 | text-shadow: none;
183 | font-size: 14px;
184 | text-decoration: underline;
185 | cursor: pointer;
186 | border: none;
187 | padding-top: 0;
188 | }
189 | #donor_banner .notnow:focus {
190 | outline: none;
191 | }
192 |
193 | #donor_banner .close:hover, #donor_banner .notnow:hover {
194 | text-decoration: none;
195 | }
196 | #donor_banner .closebanner {
197 | opacity: 0;
198 | -webkit-transition: all .3s ease-in-out; /** Chrome & Safari **/
199 | -moz-transition: all .3s ease-in-out; /** Firefox **/
200 | -o-transition: all .3s ease-in-out; /** Opera **/
201 | transition: all .3s ease-in-out; /** Opera **/
202 | }
203 | #donor_banner .btn {
204 | border: 3px solid #dad8d1;
205 | border: 3px solid rgba(218, 216, 209, 0.8);
206 | background: #cb610b;
207 | background-image: -webkit-linear-gradient(#cb610b 0%, #bc5b0a 55%, #cb610b 55%);
208 | background-image: -moz-linear-gradient(#cb610b 0%, #bc5b0a 55%, #cb610b 55%);
209 | background-image: -ms-linear-gradient(#cb610b 0%, #bc5b0a 55%, #cb610b 55%);
210 | background-image: -o-linear-gradient(#cb610b 0%, #bc5b0a 55%, #cb610b 55%);
211 | background-image: linear-gradient(#cb610b 0%, #bc5b0a 55%, #cb610b 55%);
212 | color: #eee;
213 | font-family: "Georgia", "Times New Roman", "Times", serif;
214 | font-size: 17px;
215 | font-weight: normal;
216 | padding: 0.45em 1.8em;
217 | -webkit-background-clip: padding;
218 | -moz-background-clip: padding;
219 | background-clip: padding-box;
220 | -webkit-border-radius: 6px;
221 | -moz-border-radius: 6px;
222 | -ms-border-radius: 6px;
223 | -o-border-radius: 6px;
224 | border-radius: 6px;
225 | text-shadow: 0 0 0;
226 | cursor: pointer;
227 | }
228 | #donor_banner .btn:hover {
229 | background: #b85301;
230 | background-image: -webkit-linear-gradient(#b85301 0%, #a54e01 55%, #b85301 55%);
231 | background-image: -moz-linear-gradient(#b85301 0%, #a54e01 55%, #b85301 55%);
232 | background-image: -ms-linear-gradient(#b85301 0%, #a54e01 55%, #b85301 55%);
233 | background-image: -o-linear-gradient(#b85301 0%, #a54e01 55%, #b85301 55%);
234 | background-image: linear-gradient(#b85301 0%, #a54e01 55%, #b85301 55%);
235 | color: #fff;
236 | -webkit-background-clip: padding;
237 | -moz-background-clip: padding;
238 | background-clip: padding-box;
239 | }
240 |
241 | #donor_banner.donorbanner_2 .bubble {
242 | bottom: -297px;
243 | }
244 | #donor_banner.donorbanner_2 .donationplea p, .openstates_1#donor_banner .donationplea p{
245 | margin-top: -15px;
246 | }
--------------------------------------------------------------------------------
/views/faq.erb:
--------------------------------------------------------------------------------
1 | <% content_for(:footer_id) do %>footer-person<% end %>
2 |
3 |
4 |
5 | Frequently Asked Questions
6 |
7 |
8 | What is the House Staff Directory?
9 | The House Staff Directory makes it easy to search publicly available information about the House of Representatives to allow Americans to better communicate with their elected representatives. It is no secret that congressional staff are the lifeblood of Congress, but identifying the best staffer to speak with about a particular issue can be a daunting challenge.
10 |
11 |
12 |
13 | What makes the House Staff Directory unique?
14 | Four things combine to make the House Staff Directory unique:
15 |
16 | It's free.
17 |
18 | It's a directory of all House employees, including those who provide legislative support to the functioning of Congress, with data no more than six months old.
19 |
20 | You can perform complex searches by staff title, political party, fiscal quarter or state and download that information into a spreadsheet.
21 |
22 | You can search over multiple quarters to see the congressional employment history for a particular staffer.
23 |
24 |
25 |
26 |
27 | What can I do with this information?
28 | The better question is: What do you want to do?
29 |
30 | If you want a list of all of the press secretaries whose bosses serve on a particular committee, or a myriad of other combinations of information, you can get it here.
31 |
32 | If you met a staffer but lost his or her contact information, you can look that up here.
33 |
34 | If you're trying to find the phone number for a legislative support office, it's available here.
35 |
36 | If you want the room numbers for certain offices, you can get them here.
37 |
38 | You can see what other offices a staffer has worked in, or his or her title.
39 |
40 |
41 | Found another use? Tell us about it.
42 |
43 |
44 | Where does your data come from? How recent is it?
45 | We draw all of our data from three public sources.
46 |
47 | A list of addresses and phone numbers for each personal and committee office is published online by the House Clerk's office. This information is updated after each election and as rooms change.
48 |
49 | Addresses and phone numbers for many miscellaneous House offices are made available in a PDF from the House Clerk. This information is updated at least once every two years.
50 |
51 | Our list of House staff comes from the the House Statement of Disbursements , a quarterly document published by the Clerk that lists every penny spent in the House. Although the report is published in print every quarter, it takes some time (but no more than 3 months) for the Clerk to publish this information online in PDF format. We scrape the data and publish it online on our House Expenditure Reports database in a more usable format. Then, we go through this data and identify each staffer, their title and where they work.
52 |
53 |
54 | At most, our list of staff in a particular office is six months out of date.
55 |
56 |
57 | Where is the direct contact information?
58 | Please note that we only use publicly available information. We do not provide direct phone numbers for particular staff, but rather the number for the main office. For some staff, we do not know if they are based in a district office or Capitol Hill, so we just included the main office phone number in Washington, D.C.
59 |
60 |
61 |
62 | Why is a staffer listed in more than one office?
63 | There are several possible reasons.
64 |
65 | The data we are drawing from is a snapshot of a quarter of the year. Staff move around a lot, including serving in two offices during a particular quarter. Thus, they will show up twice.
66 |
67 | Some staff are shared staff, meaning they have responsibilities in multiple offices. This happens most often with caucus staff and committee staff.
68 |
69 | Two different staffers may have identical names. We have no way of knowing that they are two entirely different people.
70 |
71 |
72 |
73 |
74 | Where are the email addresses?
75 | The House of Representatives does not make publicly available email addresses for staff. Some private companies do gather this information and sell it for a fee. If you wish for a particular staffer's email address, it is best to ask for it. To communicate with a congressional office electronically, the House recommends that you use their WriteRep system .
76 |
77 |
78 |
79 | Where is staff salary information?
80 | Legistorm publishes House staff salary information. Although we do have some salary data in the raw data, our purpose was to build a directory.
81 |
82 |
83 |
84 | How do I know who works on a particular issue?
85 | Unfortunately, there is no public source that identifies the issue areas on which particular staffers work. Your best bet is to contact the office that you're interested in. If you wish to get a list of all staffers who work in your issue area, you will need to contact a commercial vendor that compiles this information.
86 |
87 |
88 |
89 | I found a mistake.
90 | We're sorry to hear that, and hope you'll tell us about it. Please keep in mind some kinds of mistakes we cannot fix because we're not the source of the error. But do let us know .
91 |
92 |
93 |
94 | I have an idea to make this better.
95 | Great! We'd love to hear from you. Drop us a line.
96 |
97 |
98 |
99 | I want to play with the data.
100 |
101 | You can download the expenditure data upon which our staffer data is premised, in bulk, from Sunlight's website . There's no copyright on the data, so have fun.
102 |
103 | The code we wrote to generate the data is available and dedicated to the worldwide public domain . You can also check out our various data APIs . If you build something with our data, we'd love it if you let us know.
104 |
105 | Finally, you can get the source code for this website , licensed under the General Public License v3 .
106 |
107 |
108 |
109 | Who is responsible for the House Staff Directory?
110 | The Sunlight Foundation, a non-profit organization that works to make the government more transparent by encouraging public information to be published online, in real time, and in machine readable formats.
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
New Search
119 | Fill out one or more of the fields below to create a new search.
120 | <%= partial :search, :locals => {:position => "right"} %>
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/data/load.rake:
--------------------------------------------------------------------------------
1 | task loading_environment: :environment do
2 | require 'csv'
3 | require 'congress'
4 |
5 | Congress.key = config['sunlight_api_key']
6 | end
7 |
8 | namespace :load do
9 |
10 | desc "Loads titles from titles.csv"
11 | task titles: :loading_environment do
12 | start = Time.now
13 | debug = ENV['debug'].present?
14 |
15 | # blow away and start from scratch
16 | Title.delete_all
17 |
18 | i = 0
19 | CSV.foreach("data/csv/titles.csv") do |row|
20 | i += 1
21 | next if i == 1 # header row
22 |
23 | title_name_original = row[0].strip
24 | title_name = row[1].blank? ? title_name_original : row[1].strip
25 |
26 | if title = Title.where(:name => title_name).first
27 | title.original_names << title_name_original
28 | puts "Updated title: #{title_name} with original title #{title_name_original}" if debug
29 | else
30 | title = Title.new :name => title_name
31 | title.original_names = [title_name_original]
32 | puts "New title: #{title_name} with original title #{title_name_original}" if debug
33 | end
34 |
35 | title.save!
36 | end
37 |
38 | puts "Loaded #{Title.count} titles."
39 | puts "\nFinished in #{Time.now - start} seconds."
40 | end
41 |
42 |
43 | desc "Loads offices from offices.csv"
44 | task offices: :loading_environment do
45 | start = Time.now
46 |
47 | offline = ENV['offline'].present?
48 |
49 | # don't empty out offices; we don't keep past committees anywhere, so they must be preserved
50 | committees = offline ? {} : committee_cache
51 |
52 | i = 0
53 | CSV.foreach("data/csv/offices.csv") do |row|
54 | i += 1
55 | next if i == 1 # header row
56 |
57 | office_from_row row, i, committees
58 | end
59 |
60 | unless offline
61 | Congress.legislators(per_page: "all")['results'].each do |legislator|
62 | office_from_legislator legislator
63 | end
64 | end
65 |
66 | puts "Loaded #{Office.count} offices."
67 | puts "\t#{Office.members.count} members"
68 | puts "\t#{Office.committees.count} committees"
69 | puts "\t#{Office.others.count} other offices"
70 | puts "\nFinished in #{Time.now - start} seconds."
71 | end
72 |
73 |
74 | desc "Loads staffers from staffers.csv"
75 | task staffers: :loading_environment do
76 | start = Time.now
77 |
78 | Staffer.delete_all
79 |
80 | i = 0
81 | CSV.foreach("data/csv/staffers.csv") do |row|
82 | i += 1
83 | next if i == 1 # header row
84 |
85 | staffer_from_row row, i
86 | end
87 |
88 | puts "Loaded #{Staffer.count} staffers."
89 | puts "\nFinished in #{Time.now - start} seconds."
90 | end
91 |
92 |
93 | desc "Loads database (from scratch) from staffers.csv and titles.csv"
94 | task positions: :loading_environment do
95 | start = Time.now
96 |
97 | debug = ENV['debug'].present?
98 | limit = ENV['limit'].present? ? ENV['limit'].to_i : nil
99 |
100 | Position.delete_all
101 |
102 | i = 0
103 | CSV.foreach("data/csv/positions.csv") do |row|
104 | i += 1
105 | next if i == 1 # header row
106 |
107 | # for debugging usage
108 | break if limit and i > limit
109 |
110 | staffer_name_original = strip row[0]
111 | if staffer_name_original.blank?
112 | puts "WARNING: No staffer name given, skipping row #{i}"
113 | next
114 | end
115 |
116 | title_original = strip row[1]
117 | quarter = strip row[2]
118 | bioguide_id = strip row[3]
119 | office_name_original = strip row[4]
120 |
121 | # also strip off title addendums, we're ignoring these and collapsing them programmatically
122 | ["(OTHER COMPENSATION)", "(OVERTIME)"].each do |addendum|
123 | title_original.sub! addendum, ''
124 | end
125 | title_original.strip!
126 |
127 |
128 | unless staffer = Staffer.where(:original_names => staffer_name_original).first
129 | puts "Couldn't locate staffer by name #{staffer_name_original} in row #{i}, skipping"
130 | next
131 | end
132 |
133 | unless title = Title.where(:original_names => title_original).first
134 | puts "Couldn't locate title by name #{title_original} in row #{i}, skipping"
135 | next
136 | end
137 |
138 | office = nil
139 | if bioguide_id.present?
140 | unless office = Office.where("member.bioguide_id" => bioguide_id).first
141 | puts "Couldn't locate legislator by bioguide_id #{bioguide_id} in row #{i}, skipping"
142 | next
143 | end
144 |
145 | else
146 | unless office = Office.where(original_names: office_name_original).first
147 | puts "Couldn't locate office by name #{office_name_original} in row #{i}, skipping"
148 | next
149 | end
150 | end
151 |
152 | position = Position.where(
153 | :quarter => quarter,
154 | "title.name" => title['name'],
155 | "staffer.slug" => staffer['slug'],
156 | "office.slug" => office['slug']
157 | ).first
158 |
159 | if position.nil?
160 | position = Position.new(
161 | quarter: quarter,
162 | title: title.attributes,
163 | staffer: staffer.attributes,
164 | office: office.attributes,
165 | original_title: title_original
166 | )
167 |
168 | position.save!
169 | end
170 |
171 | puts "[#{i}][#{quarter}] #{staffer.name} works as #{title.name} for #{office.name}" if debug
172 | end
173 |
174 | puts "\nLoaded in #{Position.count} staffer positions."
175 | puts "\nFinished in #{Time.now - start} seconds."
176 | end
177 |
178 | desc "Load in quarters from positions"
179 | task quarters: :loading_environment do
180 | Quarter.delete_all
181 |
182 | Position.all.distinct(:quarter).each do |quarter|
183 | Quarter.create! name: quarter
184 | end
185 |
186 | puts "\nLoaded in #{Quarter.count} quarters: #{Quarter.all.map(&:name).join ', '}"
187 | end
188 |
189 | desc "Run all loading tasks in sequence"
190 | task all: [:loading_environment, "load:titles", "load:offices", "load:staffers", "load:positions", "load:quarters"] do
191 | end
192 |
193 | end
194 |
195 | # format name from Sunlight Congress API
196 | def titled_name(legislator)
197 | "#{legislator.title}. #{legislator.nickname.present? ? legislator.nickname : legislator.firstname} #{legislator.lastname} #{legislator.name_suffix}".strip
198 | end
199 |
200 | # split congress_office out into room and building
201 | def split_office(congress_office)
202 | words = congress_office.split ' '
203 | [words[0], words[1]]
204 | end
205 |
206 | def strip(str)
207 | str.present? ? str.strip : nil
208 | end
209 |
210 | # office from a row in offices.csv
211 | def office_from_row(row, i, committees)
212 | office_name_original = strip row[0]
213 | office_name = strip(row[1]) || office_name_original
214 |
215 | committee_id = strip row[2]
216 | phone = strip row[3]
217 | building = strip row[4]
218 | room = strip row[5]
219 |
220 | debug = ENV['debug'].present?
221 |
222 | if committee_id.present?
223 | office = Office.where("committee.id" => committee_id).first
224 |
225 | # there may be multiple spellings of a given committee that cause it to show up in duplicate rows in committees.csv
226 | if office
227 |
228 | if !office.original_names.include?(office_name_original)
229 | office.original_names << office_name_original
230 | puts "Updated committee office: #{office.name} with new original name #{office_name_original}" if debug
231 | else
232 | puts "Found old committee office with this name, not touching" if debug
233 | end
234 |
235 | # in case remote committee data changed
236 | committee = committees[committee_id]
237 | if committee
238 | office.attributes = {
239 | :name => committee.name,
240 | :committee => {
241 | :id => committee_id,
242 | :name => committee.name,
243 | :chamber => committee.chamber
244 | }
245 | }
246 | office.save!
247 | end
248 |
249 | else
250 | committee = committees[committee_id]
251 |
252 | if committee
253 | office = Office.new name: committee.name
254 | office.attributes = {
255 | :original_names => [office_name_original],
256 | :office_type => "committee",
257 | :phone => phone,
258 | :room => room,
259 | :building => building,
260 | :chamber => 'house',
261 | :committee => {
262 | :id => committee_id,
263 | :name => committee.name,
264 | :chamber => committee.chamber
265 | }
266 | }
267 | else
268 | puts "BAD OR OLD COMMITTEE_ID: #{committee_id}, row #{i}"
269 | return
270 | end
271 |
272 | puts "New committee office: #{office.name} with original name #{office_name_original}" if debug
273 | end
274 |
275 | office.save!
276 |
277 | else
278 | office = Office.where(name: office_name).first
279 |
280 | if office
281 |
282 | if !office.original_names.include?(office_name_original)
283 | office.original_names << office_name_original
284 | puts "Updated other office: #{office.name} with new original name #{office_name_original}" if debug
285 | end
286 |
287 | else
288 | office = Office.new :name => office_name
289 | office.attributes = {
290 | :original_names => [office_name_original],
291 | :office_type => "other",
292 | :phone => phone,
293 | :room => room,
294 | :building => building,
295 | :chamber => 'house'
296 | }
297 |
298 | puts "New other office: #{office.name} with original name #{office_name_original}" if debug
299 | end
300 |
301 | office.save!
302 | end
303 | end
304 |
305 | def office_from_legislator(legislator)
306 |
307 | room, building = split_office legislator.office
308 |
309 | unless office = Office.where("member.bioguide_id" => legislator.bioguide_id).first
310 | office = Office.new name: titled_name(legislator)
311 | puts "[#{legislator.bioguide_id}] not found, making new record"
312 | else
313 | puts "[#{legislator.bioguide_id}] found, updating existing record"
314 | end
315 |
316 | office.attributes = {
317 | original_names: [],
318 | office_type: "member",
319 | phone: legislator.phone,
320 | room: room,
321 | building: building,
322 | chamber: legislator.chamber,
323 | member: {
324 | bioguide_id: legislator.bioguide_id,
325 | firstname: legislator.first_name,
326 | lastname: legislator.last_name,
327 | nickname: legislator.nickname,
328 | party: legislator.party,
329 | name_suffix: legislator.name_suffix,
330 | title: legislator.title,
331 | chamber: legislator.chamber,
332 | congress_office: legislator.office,
333 | phone: legislator.phone,
334 | state: legislator.state,
335 | district: legislator.district,
336 | in_office: legislator.in_office
337 | }
338 | }
339 |
340 | puts "[#{legislator.bioguide_id}] New or updated member office: #{office.name}"
341 | office.save!
342 | end
343 |
344 | def staffer_from_row(row, i)
345 | debug = ENV['debug'].present?
346 |
347 | staffer_name_original = strip row[0]
348 | staffer_name = strip(row[1]) || staffer_name_original
349 |
350 | if staffer_name_original.blank?
351 | puts "WARNING: no staffer original name provided for row #{i}, skipping"
352 | return
353 | end
354 |
355 |
356 | if staffer = Staffer.where(name: staffer_name).first
357 | staffer.original_names << staffer_name_original
358 | puts "[#{i}] Updated staffer: #{staffer_name} with original name #{staffer_name_original}" if debug
359 |
360 | else
361 | # standardize fields
362 | last_name, first_name = staffer_name.split(/,\s?/)
363 |
364 | if last_name
365 | last_name = last_name.split(/\s+/).map {|n| n.capitalize}.join " "
366 | end
367 |
368 | if first_name
369 | first_name = first_name.split(/\s+/).map {|n| n.capitalize}.join " "
370 | end
371 |
372 | staffer = Staffer.new
373 | staffer.attributes = {
374 | name: [first_name, last_name].join(" "),
375 | original_names: [staffer_name_original],
376 | first_name: first_name,
377 | last_name: last_name,
378 | }
379 |
380 | puts "[#{i}] New staffer: #{staffer_name} with original name #{staffer_name_original}" if debug
381 | end
382 |
383 | staffer.save!
384 | end
385 |
386 | def committee_cache
387 | # all parent committees
388 | cache = {}
389 | committees = Congress.committees(subcommittee: false, per_page: 'all')['results']
390 | committees.each do |committee|
391 | cache[committee.id] = committee
392 | end
393 |
394 | cache
395 | end
--------------------------------------------------------------------------------
/public/javascripts/jquery.tablesorter.min.js:
--------------------------------------------------------------------------------
1 |
2 | (function($){$.extend({tablesorter:new
3 | function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($(' ').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((ab)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((ba)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j 0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=C(e[d],"function"),C(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y={}.hasOwnProperty,z;!C(y,"undefined")&&!C(y.call,"undefined")?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},q.canvastext=function(){return!!e.canvas&&!!C(b.createElement("canvas").getContext("2d").fillText,"function")},q.csstransforms=function(){return!!G("transform")},q.csstransforms3d=function(){var a=!!G("perspective");return a&&"webkitPerspective"in g.style&&w("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},q.csstransitions=function(){return G("transition")};for(var H in q)z(q,H)&&(v=H.toLowerCase(),e[v]=q[H](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)z(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},A(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.hasEvent=x,e.testProp=function(a){return E([a])},e.testAllProps=G,e.testStyles=w,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f— Seth Flaxman, TurboVote ",
155 | urls: {
156 | sf: "ES4WiEhrlKfiBxc3Kpg8cYRz2%2bRR%2f1fzLYu6pb7u65ZqNZbZieRkFg%3d%3d",
157 | ie: "ES4WiEhrlKfiBxc3Kpg8cfHj7Aebd6qH9LNcUSj633k83FgeurrtcQ%3d%3d",
158 | staffers: "ES4WiEhrlKfiBxc3Kpg8cWDlfqDH1uxY5GzS5yL%2bUQ1NCDg8WJMkzw%3d%3d",
159 | capitol_words: "ES4WiEhrlKfiBxc3Kpg8ce6YeCbWSMeQaQE3hAEXcsYfk%2fIGzT5K1g%3d%3d",
160 | politwoops: "ES4WiEhrlKfiBxc3Kpg8cWec3Th0pAGlo%2fQVClQngfMsYk%2bKWxuq0w%3d%3d",
161 | party_time: "ES4WiEhrlKfiBxc3Kpg8caGUCsN%2bZHf6YEjh93orBwwHoGnkTtSnkg%3d%3d",
162 | open_states: "ES4WiEhrlKfiBxc3Kpg8cSoqdq3HMdqJCp1bFf10GIejjsNc9W6rcQ%3d%3d",
163 | docket_wrench: "ES4WiEhrlKfiBxc3Kpg8cSeVmriKsVfjkNbyzSZnHB%2bi%2fEDOfmO2FQ%3d%3d"
164 | }
165 | },
166 |
167 | // F
168 | {
169 | quote: true,
170 | bottom: -288,
171 | html: "“I came to Sunlight because I believe technology is incredibly powerful and government is incredibly important. I don't think there's any better place for working to bring the two together.” — Tom Lee, Director of Sunlight Labs ",
172 | urls: {
173 | sf: "ES4WiEhrlKdDXjRIAQuDVNDReMFLMcETTNSqPh2aPnJJfwJooSR4oQ%3d%3d",
174 | ie: "ES4WiEhrlKdDXjRIAQuDVMJKNCEZQctzkjD5GBZJ7VfCiWJS8KbKFQ%3d%3d",
175 | staffers: "ES4WiEhrlKdDXjRIAQuDVMuhVE%2f0VX25PmDKP4qWmwPhPUnnPC6r5w%3d%3d",
176 | capitol_words: "ES4WiEhrlKdDXjRIAQuDVLmIAHZlEp16be5Qmh5Hggspi8RZIjuzLg%3d%3d",
177 | politwoops: "ES4WiEhrlKdDXjRIAQuDVCfxOZR0J0x3nF%2fBimKx4D2gKuWLu%2bT%2bTQ%3d%3d",
178 | party_time: "ES4WiEhrlKdDXjRIAQuDVPoBVZzDImnRdKYZWksI0pDcke46DDHpNg%3d%3d",
179 | open_states: "ES4WiEhrlKdDXjRIAQuDVFRJyBUQ36TPvO6zVffwBy8XoaAY7ICiUA%3d%3d",
180 | docket_wrench: "ES4WiEhrlKdDXjRIAQuDVDDbD3qYmbsmplBi%2fBJTF5X3a68ujD8F0w%3d%3d"
181 | }
182 | },
183 |
184 | // G
185 | {
186 | quote: true,
187 | bottom: -296,
188 | html: "“Sunlight was one of the first organizations to really engage the technology community around improving government, and the organization has continued to inspire and leverage people with these critical skills in this important task. They are the leaders in a movement that matters.” — Jen Pahlka, Founder of Code for America ",
189 | urls: {
190 | sf: "ES4WiEhrlKfGvWU2dfGp3eWO79ir6PwlHnibLmScIoFaYIOveDlleA%3d%3d",
191 | ie: "ES4WiEhrlKfGvWU2dfGp3Zbzsqph%2bGUtjX3zjy2%2bILW2PHhJUKUC0g%3d%3d",
192 | staffers: "ES4WiEhrlKfGvWU2dfGp3fLoCreho%2f7dwq1OECAps8HQqsz%2f9m5DRA%3d%3d",
193 | capitol_words: "ES4WiEhrlKfGvWU2dfGp3Y%2frdMS0Qx6UqbbQn1Svr3LllHNEGrCTuw%3d%3d",
194 | politwoops: "ES4WiEhrlKfGvWU2dfGp3R7JJHsqOyOeP5JQj%2fxiRMMsjikamB4p2Q%3d%3d",
195 | party_time: "ES4WiEhrlKfGvWU2dfGp3V3b6yfnZ4UlFeMxRQmtbWDedwubWbR%2fHA%3d%3d",
196 | open_states: "ES4WiEhrlKfGvWU2dfGp3YvzZnTOP6hbAlgKiBcRQWZ50WkjVeIpuw%3d%3d",
197 | docket_wrench: "ES4WiEhrlKfGvWU2dfGp3ZEkRrkhFGTTmNTBVOedFQAYOJKJNuBxRg%3d%3d"
198 | }
199 | },
200 |
201 | // H
202 | {
203 | quote: true,
204 | bottom: -296,
205 | html: "“Since I began working at Sunlight six years ago, I've seen us evolve from a small non-profit working to expose money in politics to a global leader in the transparency movement. I'm thrilled to be working everyday to help define accountability and create a more open, inclusive democracy.” — John Wonderlich, Sunlight Foundation Policy Director ",
206 | urls: {
207 | sf: "ES4WiEhrlKfJPbNqTm4u93n2EKLmptx%2bXuXhGUhShTkMQxiJ934IDg%3d%3d",
208 | ie: "ES4WiEhrlKfJPbNqTm4u99TMzAAb%2fw22gmRZo%2btPIP1F5bfvt8SeEg%3d%3d",
209 | staffers: "ES4WiEhrlKfJPbNqTm4u9%2fRdaO2x4KdNAAioCGZChq%2bCU5oj%2f7Balw%3d%3d",
210 | capitol_words: "ES4WiEhrlKfJPbNqTm4u9%2fNo%2feShXRMNT658paou%2bCg1cud1cy%2frXg%3d%3d",
211 | politwoops: "ES4WiEhrlKfJPbNqTm4u92wcYDlYpBhwEkV7hT4QKDxgiCMsH2hW4w%3d%3d",
212 | party_time: "ES4WiEhrlKfJPbNqTm4u93LXjTO8fi7nYCtxHhbSdf5nQlWCkA5kLw%3d%3d",
213 | open_states: "ES4WiEhrlKfJPbNqTm4u9%2bOpUJXwEn9FaNSf3AeopvapdHZsh0K%2brg%3d%3d",
214 | docket_wrench: "ES4WiEhrlKfJPbNqTm4u9%2f%2b6uk2bgIknIr7m77ZLNvdxSWKbsy6Syg%3d%3d"
215 | }
216 | },
217 |
218 | // I
219 | {
220 | quote: true,
221 | bottom: -288,
222 | html: "“The Sunlight Foundation exists to seize the potential that technology offers to hold government accountable. Open and accessible data in the hands of citizens are key to that.” — Ellen Miller, Co-Founder and Executive Director of the Sunlight Foundation ",
223 | urls: {
224 | sf: "ES4WiEhrlKcrHsC%2bG4xM%2fIpHYocnOuJGPqa%2fNUMT2%2fmkDvGXBgk28g%3d%3d",
225 | ie: "ES4WiEhrlKcrHsC%2bG4xM%2fP7qWUrWPfFnMgShofpe4jDVGot57NPwNA%3d%3d",
226 | staffers: "ES4WiEhrlKcrHsC%2bG4xM%2fJLtbIXcrupQgQhaW1WxAtG6uXfv2e1JPA%3d%3d",
227 | capitol_words: "ES4WiEhrlKcrHsC%2bG4xM%2fObwYT85cAhLI4hxs1wVSUDF8Ha1w26B4Q%3d%3d",
228 | politwoops: "ES4WiEhrlKcrHsC%2bG4xM%2fFS5KOb8TrRQNgySODlnPMc4YXyYBjCeFQ%3d%3d",
229 | party_time: "ES4WiEhrlKcrHsC%2bG4xM%2fHr6sONflyVB5uYb5v4HZ3m9NoZ0RZPqCw%3d%3d",
230 | open_states: "ES4WiEhrlKcrHsC%2bG4xM%2fKytDEZ3It4B%2fY7l9Qy6SPAxrAHsNsJScg%3d%3d",
231 | docket_wrench: "ES4WiEhrlKcrHsC%2bG4xM%2fFqbmuVWq8PXgPkp0ms1cLF5muRhipIMtA%3d%3d"
232 | }
233 | }
234 | ];
235 |
236 | function abSwap(site) {
237 | var test = Banner.ab[Math.floor(Math.random() * Banner.ab.length)];
238 | var $p = $("#donor_banner p.because");
239 |
240 | if (test.quote)
241 | $p.addClass("quote")
242 | else
243 | $p.removeClass("quote");
244 |
245 | $p.html(test.html);
246 |
247 | var $bubble = $("#donor_banner .bubble");
248 | $bubble.css("bottom", "" + test.bottom + "px");
249 |
250 | var url = test.urls[site];
251 | var base = "https://services.myngp.com/ngponlineservices/contribution.aspx?X=";
252 | $("#donor_banner a.btn").attr("href", base + url);
253 | }
254 |
255 | $(document).ready(function() {
256 | var banner = new Banner($('html'));
257 |
258 | // HEY: change this to your site code, as seen in the above object
259 | abSwap('staffers');
260 | });
261 |
262 | })(jQuery);
--------------------------------------------------------------------------------
/public/css/style.css:
--------------------------------------------------------------------------------
1 | /* HTML5 ✰ Boilerplate */
2 |
3 | html, body, div, span, object, iframe,
4 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
5 | abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
6 | small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
7 | fieldset, form, label, legend,
8 | table, caption, tbody, tfoot, thead, tr, th, td,
9 | article, aside, canvas, details, figcaption, figure,
10 | footer, header, hgroup, menu, nav, section, summary,
11 | time, mark, audio, video {
12 | margin: 0;
13 | padding: 0;
14 | border: 0;
15 | font-size: 100%;
16 | font: inherit;
17 | vertical-align: baseline;
18 | }
19 |
20 | article, aside, details, figcaption, figure,
21 | footer, header, hgroup, menu, nav, section {
22 | display: block;
23 | }
24 |
25 | blockquote, q { quotes: none; }
26 | blockquote:before, blockquote:after,
27 | q:before, q:after { content: ""; content: none; }
28 | ins { background-color: #ff9; color: #000; text-decoration: none; }
29 | mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
30 | del { text-decoration: line-through; }
31 | abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
32 | table { border-collapse: collapse; border-spacing: 0; }
33 | hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
34 | input, select { vertical-align: middle; }
35 |
36 | body { font:13px/1.231 sans-serif; *font-size:small; }
37 | pre, code, kbd, samp { font-family: monospace, sans-serif; }
38 |
39 | html { overflow-y: scroll; }
40 | a:hover, a:active { outline: none; }
41 | ul, ol { margin-left: 2em; }
42 | ol { list-style-type: decimal; }
43 | nav ul, nav li { margin: 0; list-style:none; list-style-image: none; }
44 | small { font-size: 85%; }
45 | strong, th { font-weight: bold; }
46 | td { vertical-align: top; }
47 | sub, sup { font-size: 75%; line-height: 0; position: relative; }
48 | sup { top: -0.5em; }
49 | sub { bottom: -0.25em; }
50 |
51 | pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; padding: 15px; }
52 | textarea { overflow: auto; }
53 | .ie6 legend, .ie7 legend { margin-left: -7px; }
54 | input[type="radio"] { vertical-align: text-bottom; }
55 | input[type="checkbox"] { vertical-align: bottom; }
56 | .ie7 input[type="checkbox"] { vertical-align: baseline; }
57 | .ie6 input { vertical-align: text-bottom; }
58 | label, input[type="button"], input[type="submit"], input[type="image"], button { cursor: pointer; }
59 | button, input, select, textarea { margin: 0; }
60 | input:valid, textarea:valid { }
61 | input:invalid, textarea:invalid { border-radius: 1px; -moz-box-shadow: 0px 0px 5px red; -webkit-box-shadow: 0px 0px 5px red; box-shadow: 0px 0px 5px red; }
62 | .no-boxshadow input:invalid, .no-boxshadow textarea:invalid { background-color: #f0dddd; }
63 |
64 |
65 | ::-moz-selection{ background: #43706d; color:#fff; text-shadow: none; }
66 | ::selection { background:#43706d; color:#fff; text-shadow: none; }
67 | a:link { -webkit-tap-highlight-color: #43706d; }
68 | button { width: auto; overflow: visible; }
69 | .ie7 img { -ms-interpolation-mode: bicubic; }
70 |
71 |
72 | .main a:link, #feature a:link, footer a:link {outline: none; color: #085069;}
73 | .main a:hover, #feature a:hover, footer a:hover {outline: none; color: #ffffff; background-color: #046380;}
74 |
75 | .clear {
76 | clear:both;
77 | }
78 |
79 | .replace {
80 | text-indent: -9999em;
81 | display: block;
82 | }
83 |
84 | ol, ul {
85 | list-style-type: none;
86 | margin-left: 0;
87 | }
88 |
89 | body {
90 | color: #5e5f5f;
91 | background: #f8f6ec url('/images/bg_tile.jpg') top left repeat-x;
92 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
93 | font-size: 13px;
94 | line-height: 16px;
95 | }
96 |
97 | .sf_mini_header {
98 | background: url('/images/sfapp_bg_header.jpg') center bottom repeat-x;
99 | background-color: rgb(231, 240, 233);
100 | height: 53px;
101 | width: 100%;
102 | margin-bottom: 4px;
103 | border-bottom: 1px dashed #fff;
104 | }
105 |
106 | .sf_mini_header_nav_wrapper{
107 | width: 960px;
108 | padding: 0 10px;
109 | margin: 0 auto;
110 | }
111 |
112 | .sf_mini_header .sf-logo{
113 | background: url('/images/sfapp_logo.png') top right no-repeat;
114 | float: right;
115 | height: 40px;
116 | width: 160px;
117 | margin-top: 5px;
118 | margin-right: 10px;
119 | text-indent: -9999px;
120 | color: transparent;
121 | }
122 |
123 | .sf_mini_header_nav_wrapper a{
124 | text-decoration: none;
125 | color: #494442;
126 | }
127 |
128 | .sf_mini_header_nav_wrapper a:hover{
129 | font-weight: bold;
130 | color: #2F4867;
131 | }
132 |
133 | .sf_mini_header_nav_wrapper .about{
134 | width: 40px;
135 | }
136 |
137 | .sf_mini_header_nav_wrapper .blog{
138 | width: 40px;
139 | }
140 |
141 | .sf_mini_header_nav_wrapper .projects{
142 | width: 65px;
143 | }
144 |
145 | .sf_mini_header_nav_wrapper .contact{
146 | width: 40px;
147 | }
148 |
149 | header {
150 | width: 950px;
151 | margin: 0 auto;
152 | padding: 0 5px 0 5px;
153 | }
154 |
155 | .header-internal {
156 | margin: 0 0 0 5%;
157 | }
158 |
159 | h1 {
160 | padding-top: 17px;
161 | float: left;
162 | }
163 |
164 | h1 a {
165 | background: url('/images/hsd_logo.png') top left no-repeat;
166 | width: 227px;
167 | height: 63px;
168 | }
169 |
170 | h2 {
171 | color: #426e6b;
172 | font-size: 22px;
173 | font-weight: bold;
174 | margin: 10px 0 20px 10px;
175 | }
176 |
177 | #feature {
178 | background: url('/images/featurebar.png') top left no-repeat;
179 | height: 177px;
180 | width: 613px;
181 | margin-top: 43px;
182 | margin-left: 17px;
183 | padding-top: 15px;
184 | padding-left: 45px;
185 | float: left;
186 | }
187 |
188 | #feature h2 {
189 | background: url('/images/findingstaffer.png') top left no-repeat;
190 | width: 355px;
191 | height: 75px;
192 | margin: 0px;
193 | }
194 |
195 | #feature p {
196 | width: 488px;
197 | font-size: 12px;
198 | line-height: 18px;
199 | margin: 10px 5px;
200 | }
201 |
202 | #feature p a {
203 | text-decoration: none;
204 | }
205 |
206 | #action {
207 | font-weight: bold;
208 | font-style: italic;
209 | }
210 |
211 | .main {
212 | background: #f4f1e7 url('/images/main_bg.jpg') left top repeat-y;
213 | width: 950px;
214 | }
215 |
216 | .main label {
217 | padding-bottom: 3px;
218 | display: block;
219 | }
220 |
221 | #main-home {
222 | margin: -70px auto 0;
223 | padding: 27px 5px 40px 5px;
224 | }
225 |
226 | #main-internal {
227 | width: 95%;
228 | min-width: 910px;
229 | margin: 6% 0 0 2%;
230 | padding: 27px 1% 40px 1%;
231 | }
232 |
233 | #main-person {
234 | width: 950px;
235 | margin: 80px auto 0;
236 | padding: 27px 5px 40px 5px;
237 | }
238 |
239 | #main-basic {
240 | width: 950px;
241 | margin: 30px auto 0;
242 | padding: 27px 5px 40px 5px;
243 | }
244 |
245 | #directory-search-area {
246 | margin-top: -40px;
247 | margin-left: -20px;
248 | float: left;
249 | }
250 |
251 | #directory-search-corner {
252 | background: url('/images/cornerpiece.png') left top no-repeat;
253 | width: 16px;
254 | height: 13px;
255 | }
256 |
257 | #directory-search {
258 | background: url('/images/searchbar_tile.jpg') top left repeat;
259 | width: 208px;
260 | color: #ffffff;
261 | padding: 15px 0 25px 25px;
262 | border-top: 1px #006666 solid;
263 | border-right: 1px #006666 solid;
264 | border-bottom: 1px #006666 solid;
265 | -moz-border-radius-topright: 25px;
266 | -webkit-border-top-right-radius: 25px;
267 | border-top-right-radius: 25px;
268 | -moz-border-radius-bottomright: 25px;
269 | -webkit-border-bottom-right-radius: 25px;
270 | border-bottom-right-radius: 25px;
271 | -moz-box-shadow: #8b8981 4px 4px 10px;
272 | -webkit-box-shadow: #8b8981 4px 4px 10px;
273 | box-shadow: #8b8981 4px 4px 10px;
274 | }
275 |
276 | #directory-search h2 {
277 | background: url('/images/searchtitle.png') left top no-repeat;
278 | width: 230px;
279 | height: 82px;
280 | margin-left: -7px;
281 | margin-bottom: 11px;
282 | }
283 |
284 | #directory-search-internal {
285 | background: url('/images/searchbar_tile.jpg') top left repeat;
286 | width: 850px;
287 | color: #ffffff;
288 | margin: -55px 0 0 27px;
289 | padding: 15px 0 15px 20px;
290 | border-top: 1px #006666 solid;
291 | border-right: 1px #006666 solid;
292 | border-left: 1px #006666 solid;
293 | -moz-border-radius-topright: 25px;
294 | -webkit-border-top-right-radius: 25px;
295 | border-top-right-radius: 25px;
296 | -moz-box-shadow: #8b8981 2px 2px 5px;
297 | -webkit-box-shadow: #8b8981 2px 2px 5px;
298 | box-shadow: #8b8981 2px 2px 5px;
299 | }
300 |
301 | #directory-search-internal.min {
302 | background: url('/images/searchbar_tile.jpg') top left repeat;
303 | width: 850px;
304 | color: #ffffff;
305 | margin: -55px 0 0 27px;
306 | padding: 10px 15px 40px 13px;
307 | border-top: 1px #006666 solid;
308 | border-right: 1px #006666 solid;
309 | border-left: 1px #006666 solid;
310 | -moz-border-radius-topright: 25px;
311 | -webkit-border-top-right-radius: 25px;
312 | border-top-right-radius: 25px;
313 | -moz-box-shadow: #8b8981 2px 2px 5px;
314 | -webkit-box-shadow: #8b8981 2px 2px 5px;
315 | box-shadow: #8b8981 2px 2px 5px;
316 | }
317 |
318 | #directory-search-internal h2 {
319 | background: url('/images/resultstitle.png') left top no-repeat;
320 | width: 253px;
321 | height: 48px;
322 | margin: -21px 10px 0 -30px;
323 | float: left;
324 | }
325 |
326 | #directory-search-internal.min h2 {
327 | background: url('/images/resultstitle.png') left top no-repeat;
328 | width: 253px;
329 | height: 48px;
330 | float: left;
331 | }
332 |
333 | #directory-search-internal.min h2 {
334 | margin: -16px 10px 0 -30px;
335 | }
336 |
337 | #directory-search-internal.min {
338 | padding: 10px 0 40px 20px;
339 | }
340 |
341 |
342 | a.toggle {
343 | width: 15px;
344 | height: 15px;
345 | margin: 0 0 0 -13px;
346 | text-indent: -9999em;
347 | display: block;
348 | float: left;
349 | position: absolute;
350 | }
351 |
352 | #directory-search-internal.min .toggle {
353 | margin: 0 0 0 -10px;
354 | }
355 |
356 | #directory-search-internal.min span.tip, #directory-search-internal.min form {
357 | display: none;
358 | }
359 |
360 | a.toggle.on {
361 | background: url('/images/toggle-on.png') left top no-repeat;
362 | }
363 |
364 | a.toggle.off {
365 | background: url('/images/toggle-off.png') left top no-repeat;
366 | }
367 |
368 | .tip {
369 | font-family: Georgia, "Times New Roman", Times, serif;
370 | font-style: italic;
371 | line-height: 17px;
372 | display: block;
373 | }
374 |
375 | #search-tip {
376 | width: 150px;
377 | }
378 |
379 | #results-tip {
380 | margin-bottom: 20px;
381 | }
382 |
383 | .info-icon {
384 | background-color: #e4e9e9;
385 | font-family: Georgia, serif;
386 | font-size: 10px;
387 | font-weight: bold;
388 | font-style: italic;
389 | margin: 0 0 0 2px;
390 | padding: 0 3px;
391 | border: 1px solid #e4e9e9;
392 | -moz-border-radius: 10px;
393 | -webkit-border-radius: 10px;
394 | border-radius: 10px;
395 | }
396 |
397 | .basic-form {
398 | margin-top: 17px;
399 | }
400 |
401 | .search-list li{
402 | margin: 20px 0 0 0;
403 | display: inline-block;
404 | }
405 |
406 | #directory-search-form select {
407 | width: 190px;
408 | }
409 |
410 | #directory-search-form input {
411 | width: 183px;
412 | }
413 |
414 | #directory-search-form #search-button {
415 | background: url('/images/search_button.png') center top no-repeat;
416 | width: 141px;
417 | height: 33px;
418 | margin: 5px 0 0 25px;
419 | border: none;
420 | cursor: pointer;
421 | }
422 |
423 | #directory-search-form-internal li {
424 | margin: 5px 10px 0 0;
425 | }
426 |
427 | #directory-search-form-internal #list-year {
428 | margin: 5px 50px 0 0;
429 | }
430 |
431 | #directory-search-form-internal #list-button {
432 | vertical-align: bottom;
433 | }
434 |
435 | #directory-search-form-internal select {
436 | width: 150px;
437 | }
438 |
439 | #directory-search-form-internal input {
440 | width: 143px;
441 | }
442 |
443 | #directory-search-form-internal #search-button {
444 | background: url('/images/newsearch_button.png') center top no-repeat;
445 | width: 129px;
446 | height: 28px;
447 | margin: 0 0 0 8px;
448 | border: none;
449 | cursor: pointer;
450 | }
451 |
452 | .directory-search-area-right {
453 | width: 166px;
454 | margin: 22px -12px 0 0;
455 | float: left;
456 | }
457 |
458 | #right-of-text {
459 | margin: -10px -12px 0 0;
460 | }
461 |
462 | #directory-search-right-corner {
463 | background: url('/images/cornerpiece2.png') left top no-repeat;
464 | width: 29px;
465 | height: 13px;
466 | margin-left: 159px;
467 | }
468 |
469 | #directory-search-right {
470 | background: url('/images/searchbar_tile.jpg') top left repeat;
471 | width: 166px;
472 | color: #ffffff;
473 | padding: 15px 0 25px 20px;
474 | border-top: 1px #006666 solid;
475 | border-left: 1px #006666 solid;
476 | border-bottom: 1px #006666 solid;
477 | -moz-border-radius-topleft: 25px;
478 | -webkit-border-top-left-radius: 25px;
479 | border-top-left-radius: 25px;
480 | -moz-border-radius-bottomleft: 25px;
481 | -webkit-border-bottom-left-radius: 25px;
482 | border-bottom-left-radius: 25px;
483 | -moz-box-shadow: #8b8981 -4px 4px 10px;
484 | -webkit-box-shadow: #8b8981 -4px 4px 10px;
485 | box-shadow: #8b8981 -4px 4px 10px;
486 | }
487 |
488 | #new-search {
489 | background: url('/images/newsearch.png') left top no-repeat;
490 | width: 176px;
491 | height: 40px;
492 | margin-bottom: 10px;
493 | }
494 |
495 | #directory-search-form-right select {
496 | width: 150px;
497 | }
498 |
499 | #directory-search-form-right input {
500 | width: 143px;
501 | }
502 |
503 | #directory-search-form-right #search-button {
504 | background: url('/images/newsearch_button.png') center top no-repeat;
505 | width: 129px;
506 | height: 28px;
507 | margin: 5px 0 0 13px;
508 | border: none;
509 | cursor: pointer;
510 | }
511 |
512 | #person-info {
513 | background: url('/images/personbar.jpg') top left repeat;
514 | width: 615px;
515 | margin: -55px 0 0 27px;
516 | padding: 15px 5px 10px 18px;
517 | border-top: 1px #b7b5aa solid;
518 | border-right: 1px #b7b5aa solid;
519 | border-left: 1px #b7b5aa solid;
520 | -moz-border-radius-topright: 25px;
521 | -webkit-border-top-right-radius: 25px;
522 | border-top-right-radius: 25px;
523 | -moz-border-radius-topleft: 25px;
524 | -webkit-border-top-left-radius: 25px;
525 | border-top-left-radius: 25px;
526 | -moz-box-shadow: #8b8981 2px 2px 5px;
527 | -webkit-box-shadow: #8b8981 2px 2px 5px;
528 | box-shadow: #8b8981 2px 2px 5px;
529 | }
530 |
531 | #id_portrait {
532 | width: 88px;
533 | height: 110px;
534 | margin-right: 20px;
535 | border: 3px #828176 solid;
536 | -moz-border-radius: 5px;
537 | -webkit-border-radius: 5px;
538 | border-radius: 5px;
539 | float: left;
540 | }
541 |
542 | #vcard-wrapper {
543 | float: left;
544 | }
545 |
546 | #id_person-name {
547 | font-size: 23px;
548 | font-weight: bold;
549 | margin: 0px;
550 | padding: 5px 0;
551 | }
552 |
553 | #person-main h2 {
554 | color: #57564e;
555 | }
556 |
557 | #id_party-district {
558 | color: #57564e;
559 | font-size: 16px;
560 | font-weight: 600;
561 | margin-top: 7px;
562 | display: block;
563 | }
564 |
565 | .vcard {
566 | color: #828176;
567 | font-size: 16px;
568 | line-height: 22px;
569 | margin-top: 3px;
570 | }
571 |
572 | .type {
573 | display: none;
574 | }
575 |
576 | .center {
577 | background-color: #f8f7f1;
578 | border: 1px #eeeeee solid;
579 | -moz-box-shadow: #8b8981 0px 1px 5px;
580 | -webkit-box-shadow: #8b8981 0px 1px 5px;
581 | box-shadow: #8b8981 0px 1px 5px;
582 | }
583 |
584 | #directory-browse {
585 | width: 670px;
586 | margin-top: 55px;
587 | margin-left: 160px;
588 | padding: 18px 15px 44px 90px;
589 | }
590 |
591 | #directory-browse h4 {
592 | font-size: 18px;
593 | font-weight: bold;
594 | margin-bottom: 12px;
595 | }
596 |
597 | #search-results {
598 | margin-left: 17px;
599 | padding: 15px 15px 20px 15px;
600 | }
601 |
602 | #basic-content {
603 | width: 880px;
604 | margin-left: 17px;
605 | padding: 15px 0 20px 15px;
606 | }
607 |
608 | #directory-browse h3 {
609 | background: url('/images/browsetitle.png') left top no-repeat;
610 | width: 488px;
611 | height: 25px;
612 | margin: 0 0 20px 70px;
613 | }
614 |
615 | #browse-tip {
616 | color: #005454;
617 | width: 650px;
618 | text-align: center;
619 | font-size: 12px;
620 | font-family: Georgia, "Times New Roman", Times, serif;
621 | font-weight: bold;
622 | font-style: italic;
623 | display: block;
624 | }
625 |
626 | #download-csv {
627 | background: url('/images/download_button.png') center top no-repeat;
628 | width: 115px;
629 | height: 26px;
630 | margin: 0 0 13px 8px;
631 | }
632 |
633 | #three-columns {
634 | width: 700px;
635 | margin: 10px 22px 0 0;
636 | float: left;
637 | }
638 |
639 | .browse-column {
640 | width: 195px;
641 | margin-top: 30px;
642 | float: left;
643 | }
644 |
645 | .browse-column a.view:hover {
646 | color: #ffffff;
647 | }
648 |
649 | .basic-text {
650 | width: 630px;
651 | padding: 0 82px 0 10px;
652 | float: left;
653 | }
654 |
655 | .text-content {
656 | font-size: 15px;
657 | line-height: 20px;
658 | margin-bottom: 20px;
659 | }
660 |
661 | .text-content ul {
662 | margin: 5px 0;
663 | list-style-position: inside;
664 | list-style-type: disc;
665 | }
666 |
667 | .text-content li {
668 | margin: 0 0 8px 12px;
669 | }
670 |
671 | .text-content li:last-child {
672 | margin: 0 0 0 12px;
673 | }
674 |
675 | h4 a:link, h4 a:visited, h4 a:active {
676 | color: #005454;
677 | text-decoration: none;
678 | }
679 |
680 | h3 {
681 | font-size: 19px;
682 | font-weight: bold;
683 | margin-top: 3px;
684 | margin-bottom: 6px;
685 | }
686 |
687 | .person-page-staffers {
688 | margin-left: 10px;
689 | }
690 |
691 | .text-content h4 {
692 | margin-bottom: 10px;
693 | }
694 |
695 | #house-members {
696 | margin-left: 10px;
697 | }
698 |
699 | #house-offices {
700 | margin-left: 5px;
701 | }
702 |
703 | #house-comm {
704 | padding-right: 25px;
705 | }
706 |
707 | #house-offices, #house-comm {
708 | padding-left: 15px;
709 | border-left: #e4e9e9 2px solid;
710 | }
711 |
712 | .browse-column li a {
713 | color: #006666;
714 | font-size: 12px;
715 | line-height: 16px;
716 | text-decoration: none;
717 | display: block;
718 | }
719 |
720 | .browse-column li {
721 | margin-bottom: 10px;
722 | }
723 |
724 | .member-parties {
725 | color: #979797;
726 | font-size: 12px;
727 | }
728 |
729 | .browse-column a.view {
730 | color: #085069;
731 | font-size: 12px;
732 | font-family: Georgia, "Times New Roman", Times, serif;
733 | font-style: italic;
734 | }
735 |
736 | .basic-table {
737 | width: 100%;
738 | text-align: left;
739 | border-collapse: separate;
740 | border-spacing: 10px 0;
741 | }
742 |
743 | .basic-table a:link {
744 | color: #006666;
745 | }
746 |
747 | .basic-table th {
748 | color: #006666;
749 | background-color: #e4e9e9;
750 | padding: 5px;
751 | font-size: 14px;
752 | }
753 |
754 | /** This class is added dynamically by tablesorter to headers that are sortable **/
755 | .basic-table th.header {
756 | cursor: pointer;
757 | }
758 |
759 | #results-table {
760 | min-width: 855px;
761 | }
762 |
763 | #person-results-table .column-sort, #results-table .column-sort, #three-col-results-table .column-sort {
764 | background: #e4e9e9 url('/images/sort_arrows.png') 5px 8px no-repeat;
765 | padding: 5px 5px 5px 20px;
766 | }
767 |
768 | .basic-table td {
769 | font-size: 12px;
770 | padding: 7px 0 7px 7px;
771 | border-bottom: 1px #e4e9e9 dashed;
772 | }
773 |
774 | #results-table td {
775 | width: 14%;
776 | }
777 |
778 | #results-table .wide-col {
779 | width: 30%;
780 | }
781 |
782 | #person-results-table .wide-col, #three-col-results-table .wide-col {
783 | width: 45%;
784 | }
785 |
786 | #person-results-table .short-col {
787 | width: 20%;
788 | }
789 |
790 | #three-col-results-table .short-col {
791 | width: 15%;
792 | }
793 |
794 | #three-col-results-table .short-col {
795 | width: 15%;
796 | }
797 |
798 | #three-col-results-table .no-col {
799 | padding-left:27px;
800 | }
801 |
802 | #results-table th:nth-child(5) {
803 | padding: 5px 0 5px 3px;
804 | }
805 |
806 | .basic-table a:link, .basic-table a:active, .basic-table a:visited {
807 | color: #005454;
808 | text-decoration: none;
809 | }
810 |
811 | .basic-table a:hover {
812 | color: #ffffff;
813 | background-color: #046380;
814 | }
815 |
816 | footer {
817 | width: 950px;
818 | margin: -30px auto 50px;
819 | padding: 0 5px 0 5px;
820 | }
821 |
822 | .footer-internal {
823 | margin: -30px 0 50px 225px;
824 | }
825 |
826 | .footer-content {
827 | background: url('/images/footerbar.png') top left no-repeat;
828 | height: 150px;
829 | width: 575px;
830 | color: #7b7d81;
831 | padding: 25px 40px 0 40px;
832 | }
833 |
834 | #footer-home {
835 | margin-left: 240px;
836 | }
837 |
838 | #footer-person {
839 | margin-left: 170px;
840 | }
841 |
842 | #subnav li {
843 | float:left;
844 | }
845 |
846 | #faqs {
847 | margin-left: 125px;
848 | }
849 |
850 | #feedback {
851 | margin-left: 75px;
852 | }
853 |
854 | #opensource {
855 | margin-left: 70px;
856 | }
857 |
858 | #subnav a {
859 | font-size: 14px;
860 | font-family: Georgia, "Times New Roman", Times, serif;
861 | font-weight: bold;
862 | font-style: italic;
863 | }
864 |
865 | #subnav a:link, #subnav a:visited, #subnav a:active {
866 | color: #006666;
867 | }
868 |
869 | #subnav a:hover, #about a:hover {
870 | color: #ffffff;
871 | }
872 |
873 | #join {
874 | line-height: 17px;
875 | text-align: center;
876 | margin-top: 10px;
877 | display: block;
878 | }
879 |
880 | #join strong {
881 | display: block;
882 | }
883 |
884 | #emailmediarow {
885 | margin-top: 13px;
886 | padding-left: 94px;
887 | }
888 |
889 | #mailinglistform li {
890 | margin-right: 13px;
891 | float: left;
892 | }
893 |
894 | #mailinglistform li label {
895 | display: none;
896 | }
897 |
898 | #mailinglistform input {
899 | width: 103px;
900 | color: #44726f;
901 | font-family: Georgia, "Times New Roman",Times,serif;
902 | font-style: italic;
903 | }
904 |
905 | #join-button {
906 | background: url('/images/join_button.png') center top no-repeat;
907 | width: 66px;
908 | height: 24px;
909 | border: none;
910 | text-indent: -9999em;
911 | display: block;
912 | cursor: pointer;
913 | }
914 |
915 | #facebook {
916 | background: url('/images/facebook_icon.png') left top no-repeat;
917 | width: 22px;
918 | height: 24px;
919 | text-indent: -9999em;
920 | margin-right: 13px;
921 | display: block;
922 | float: left;
923 | cursor: pointer;
924 | }
925 |
926 | #twitter {
927 | background: url('/images/twitter_icon.png') left top no-repeat;
928 | width: 24px;
929 | height: 24px;
930 | text-indent: -9999em;
931 | display: block;
932 | float: left;
933 | cursor: pointer;
934 | }
935 |
936 | #about {
937 | text-align: center;
938 | margin-top: 7px;
939 | display: block;
940 | }
941 |
942 | #about a {
943 | color: #7b7d81;
944 | }
--------------------------------------------------------------------------------
/public/javascripts/jquery.qtip-1.0.0-rc3.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jquery.qtip. The jQuery tooltip plugin
3 | *
4 | * Copyright (c) 2009 Craig Thompson
5 | * http://craigsworks.com
6 | *
7 | * Licensed under MIT
8 | * http://www.opensource.org/licenses/mit-license.php
9 | *
10 | * Launch : February 2009
11 | * Version : 1.0.0-rc3
12 | * Released: Tuesday 12th May, 2009 - 00:00
13 | * Debug: jquery.qtip.debug.js
14 | */
15 | (function(f){f.fn.qtip=function(B,u){var y,t,A,s,x,w,v,z;if(typeof B=="string"){if(typeof f(this).data("qtip")!=="object"){f.fn.qtip.log.error.call(self,1,f.fn.qtip.constants.NO_TOOLTIP_PRESENT,false)}if(B=="api"){return f(this).data("qtip").interfaces[f(this).data("qtip").current]}else{if(B=="interfaces"){return f(this).data("qtip").interfaces}}}else{if(!B){B={}}if(typeof B.content!=="object"||(B.content.jquery&&B.content.length>0)){B.content={text:B.content}}if(typeof B.content.title!=="object"){B.content.title={text:B.content.title}}if(typeof B.position!=="object"){B.position={corner:B.position}}if(typeof B.position.corner!=="object"){B.position.corner={target:B.position.corner,tooltip:B.position.corner}}if(typeof B.show!=="object"){B.show={when:B.show}}if(typeof B.show.when!=="object"){B.show.when={event:B.show.when}}if(typeof B.show.effect!=="object"){B.show.effect={type:B.show.effect}}if(typeof B.hide!=="object"){B.hide={when:B.hide}}if(typeof B.hide.when!=="object"){B.hide.when={event:B.hide.when}}if(typeof B.hide.effect!=="object"){B.hide.effect={type:B.hide.effect}}if(typeof B.style!=="object"){B.style={name:B.style}}B.style=c(B.style);s=f.extend(true,{},f.fn.qtip.defaults,B);s.style=a.call({options:s},s.style);s.user=f.extend(true,{},B)}return f(this).each(function(){if(typeof B=="string"){w=B.toLowerCase();A=f(this).qtip("interfaces");if(typeof A=="object"){if(u===true&&w=="destroy"){while(A.length>0){A[A.length-1].destroy()}}else{if(u!==true){A=[f(this).qtip("api")]}for(y=0;y0))}if(typeof s.options.show.solo=="object"){z=f(s.options.show.solo)}else{if(s.options.show.solo===true){z=f("div.qtip").not(s.elements.tooltip)}}if(z){z.each(function(){if(f(this).qtip("api").status.rendered===true){f(this).qtip("api").hide()}})}if(typeof s.options.show.effect.type=="function"){s.options.show.effect.type.call(s.elements.tooltip,s.options.show.effect.length);s.elements.tooltip.queue(function(){w();f(this).dequeue()})}else{switch(s.options.show.effect.type.toLowerCase()){case"fade":s.elements.tooltip.fadeIn(s.options.show.effect.length,w);break;case"slide":s.elements.tooltip.slideDown(s.options.show.effect.length,function(){w();if(s.options.position.type!=="static"){s.updatePosition(y,true)}});break;case"grow":s.elements.tooltip.show(s.options.show.effect.length,w);break;default:s.elements.tooltip.show(null,w);break}s.elements.tooltip.addClass(s.options.style.classes.active)}return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_SHOWN,"show")},hide:function(y){var x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"hide")}else{if(s.elements.tooltip.css("display")==="none"){return s}}clearTimeout(s.timers.show);s.elements.tooltip.stop(true,false);x=s.beforeHide.call(s,y);if(x===false){return s}function w(){s.onHide.call(s,y)}s.cache.toggle=0;if(typeof s.options.hide.effect.type=="function"){s.options.hide.effect.type.call(s.elements.tooltip,s.options.hide.effect.length);s.elements.tooltip.queue(function(){w();f(this).dequeue()})}else{switch(s.options.hide.effect.type.toLowerCase()){case"fade":s.elements.tooltip.fadeOut(s.options.hide.effect.length,w);break;case"slide":s.elements.tooltip.slideUp(s.options.hide.effect.length,w);break;case"grow":s.elements.tooltip.hide(s.options.hide.effect.length,w);break;default:s.elements.tooltip.hide(null,w);break}s.elements.tooltip.removeClass(s.options.style.classes.active)}return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_HIDDEN,"hide")},updatePosition:function(w,x){var C,G,L,J,H,E,y,I,B,D,K,A,F,z;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updatePosition")}else{if(s.options.position.type=="static"){return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.CANNOT_POSITION_STATIC,"updatePosition")}}G={position:{left:0,top:0},dimensions:{height:0,width:0},corner:s.options.position.corner.target};L={position:s.getPosition(),dimensions:s.getDimensions(),corner:s.options.position.corner.tooltip};if(s.options.position.target!=="mouse"){if(s.options.position.target.get(0).nodeName.toLowerCase()=="area"){J=s.options.position.target.attr("coords").split(",");for(C=0;CG.dimensions.width){G.dimensions.width=J[C]}if(J[C]G.dimensions.height){G.dimensions.height=J[C]}if(J[C]0){if(L.corner.search(/Left/)!==-1){y.left-=s.options.style.border.radius}else{if(L.corner.search(/Right/)!==-1){y.left+=s.options.style.border.radius}}if(L.corner.search(/Top/)!==-1){y.top-=s.options.style.border.radius}else{if(L.corner.search(/Bottom/)!==-1){y.top+=s.options.style.border.radius}}}if(I){if(L.corner.search(/top/)!==-1){y.top-=I}else{if(L.corner.search(/bottom/)!==-1){y.top+=I}}if(L.corner.search(/left/)!==-1){y.left-=I}else{if(L.corner.search(/right/)!==-1){y.left+=I}}if(L.corner.search(/leftMiddle|rightMiddle/)!==-1){y.top-=1}}if(s.options.position.adjust.screen===true){y=o.call(s,y,G,L)}if(s.options.position.target==="mouse"&&s.options.position.adjust.mouse===true){if(s.options.position.adjust.screen===true&&s.elements.tip){K=s.elements.tip.attr("rel")}else{K=s.options.position.corner.tooltip}y.left+=(K.search(/right/i)!==-1)?-6:6;y.top+=(K.search(/bottom/i)!==-1)?-6:6}if(!s.elements.bgiframe&&f.browser.msie&&parseInt(f.browser.version.charAt(0))==6){f("select, object").each(function(){A=f(this).offset();A.bottom=A.top+f(this).height();A.right=A.left+f(this).width();if(y.top+L.dimensions.height>=A.top&&y.left+L.dimensions.width>=A.left){k.call(s)}})}y.left+=s.options.position.adjust.x;y.top+=s.options.position.adjust.y;F=s.getPosition();if(y.left!=F.left||y.top!=F.top){z=s.beforePositionUpdate.call(s,w);if(z===false){return s}s.cache.position=y;if(x===true){s.status.animated=true;s.elements.tooltip.animate(y,200,"swing",function(){s.status.animated=false})}else{s.elements.tooltip.css(y)}s.onPositionUpdate.call(s,w);if(typeof w!=="undefined"&&w.type&&w.type!=="mousemove"){f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_POSITION_UPDATED,"updatePosition")}}return s},updateWidth:function(w){var x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateWidth")}else{if(w&&typeof w!=="number"){return f.fn.qtip.log.error.call(s,2,"newWidth must be of type number","updateWidth")}}x=s.elements.contentWrapper.siblings().add(s.elements.tip).add(s.elements.button);if(!w){if(typeof s.options.style.width.value=="number"){w=s.options.style.width.value}else{s.elements.tooltip.css({width:"auto"});x.hide();if(f.browser.msie){s.elements.wrapper.add(s.elements.contentWrapper.children()).css({zoom:"normal"})}w=s.getDimensions().width+1;if(!s.options.style.width.value){if(w>s.options.style.width.max){w=s.options.style.width.max}if(w").get(0).getContext){z=s.elements.tooltip.find(".qtip-tip canvas:first");x=z.get(0).getContext("2d");x.clearRect(0,0,300,300);y=z.parent("div[rel]:first").attr("rel");B=b(y,s.options.style.tip.size.width,s.options.style.tip.size.height);h.call(s,z,B,s.options.style.tip.color||s.options.style.border.color)}else{if(f.browser.msie){z=s.elements.tooltip.find('.qtip-tip [nodeName="shape"]');z.attr("fillcolor",s.options.style.tip.color||s.options.style.border.color)}}}if(s.options.style.border.radius>0){s.elements.tooltip.find(".qtip-betweenCorners").css({backgroundColor:s.options.style.border.color});if(f("").get(0).getContext){A=g(s.options.style.border.radius);s.elements.tooltip.find(".qtip-wrapper canvas").each(function(){x=f(this).get(0).getContext("2d");x.clearRect(0,0,300,300);y=f(this).parent("div[rel]:first").attr("rel");r.call(s,f(this),A[y],s.options.style.border.radius,s.options.style.border.color)})}else{if(f.browser.msie){s.elements.tooltip.find('.qtip-wrapper [nodeName="arc"]').each(function(){f(this).attr("fillcolor",s.options.style.border.color)})}}}return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_STYLE_UPDATED,"updateStyle")},updateContent:function(A,y){var z,x,w;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateContent")}else{if(!A){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.NO_CONTENT_PROVIDED,"updateContent")}}z=s.beforeContentUpdate.call(s,A);if(typeof z=="string"){A=z}else{if(z===false){return}}if(f.browser.msie){s.elements.contentWrapper.children().css({zoom:"normal"})}if(A.jquery&&A.length>0){A.clone(true).appendTo(s.elements.content).show()}else{s.elements.content.html(A)}x=s.elements.content.find("img[complete=false]");if(x.length>0){w=0;x.each(function(C){f(' ').load(function(){if(++w==x.length){B()}})})}else{B()}function B(){s.updateWidth();if(y!==false){if(s.options.position.type!=="static"){s.updatePosition(s.elements.tooltip.is(":visible"),true)}if(s.options.style.tip.corner!==false){n.call(s)}}}s.onContentUpdate.call(s);return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_CONTENT_UPDATED,"loadContent")},loadContent:function(w,z,A){var y;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"loadContent")}y=s.beforeContentLoad.call(s);if(y===false){return s}if(A=="post"){f.post(w,z,x)}else{f.get(w,z,x)}function x(B){s.onContentLoad.call(s);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_CONTENT_LOADED,"loadContent");s.updateContent(B)}return s},updateTitle:function(w){if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateTitle")}else{if(!w){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.NO_CONTENT_PROVIDED,"updateTitle")}}returned=s.beforeTitleUpdate.call(s);if(returned===false){return s}if(s.elements.button){s.elements.button=s.elements.button.clone(true)}s.elements.title.html(w);if(s.elements.button){s.elements.title.prepend(s.elements.button)}s.onTitleUpdate.call(s);return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_TITLE_UPDATED,"updateTitle")},focus:function(A){var y,x,w,z;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"focus")}else{if(s.options.position.type=="static"){return f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.CANNOT_FOCUS_STATIC,"focus")}}y=parseInt(s.elements.tooltip.css("z-index"));x=6000+f("div.qtip[qtip]").length-1;if(!s.status.focused&&y!==x){z=s.beforeFocus.call(s,A);if(z===false){return s}f("div.qtip[qtip]").not(s.elements.tooltip).each(function(){if(f(this).qtip("api").status.rendered===true){w=parseInt(f(this).css("z-index"));if(typeof w=="number"&&w>-1){f(this).css({zIndex:parseInt(f(this).css("z-index"))-1})}f(this).qtip("api").status.focused=false}});s.elements.tooltip.css({zIndex:x});s.status.focused=true;s.onFocus.call(s,A);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_FOCUSED,"focus")}return s},disable:function(w){if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"disable")}if(w){if(!s.status.disabled){s.status.disabled=true;f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_DISABLED,"disable")}else{f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.TOOLTIP_ALREADY_DISABLED,"disable")}}else{if(s.status.disabled){s.status.disabled=false;f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_ENABLED,"disable")}else{f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.TOOLTIP_ALREADY_ENABLED,"disable")}}return s},destroy:function(){var w,x,y;x=s.beforeDestroy.call(s);if(x===false){return s}if(s.status.rendered){s.options.show.when.target.unbind("mousemove.qtip",s.updatePosition);s.options.show.when.target.unbind("mouseout.qtip",s.hide);s.options.show.when.target.unbind(s.options.show.when.event+".qtip");s.options.hide.when.target.unbind(s.options.hide.when.event+".qtip");s.elements.tooltip.unbind(s.options.hide.when.event+".qtip");s.elements.tooltip.unbind("mouseover.qtip",s.focus);s.elements.tooltip.remove()}else{s.options.show.when.target.unbind(s.options.show.when.event+".qtip-create")}if(typeof s.elements.target.data("qtip")=="object"){y=s.elements.target.data("qtip").interfaces;if(typeof y=="object"&&y.length>0){for(w=0;w0){s.elements.target.data("qtip").current=y.length-1}else{s.elements.target.removeData("qtip")}s.onDestroy.call(s);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_DESTROYED,"destroy");return s.elements.target},getPosition:function(){var w,x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"getPosition")}w=(s.elements.tooltip.css("display")!=="none")?false:true;if(w){s.elements.tooltip.css({visiblity:"hidden"}).show()}x=s.elements.tooltip.offset();if(w){s.elements.tooltip.css({visiblity:"visible"}).hide()}return x},getDimensions:function(){var w,x;if(!s.status.rendered){return f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"getDimensions")}w=(!s.elements.tooltip.is(":visible"))?true:false;if(w){s.elements.tooltip.css({visiblity:"hidden"}).show()}x={height:s.elements.tooltip.outerHeight(),width:s.elements.tooltip.outerWidth()};if(w){s.elements.tooltip.css({visiblity:"visible"}).hide()}return x}})}function p(){var s,w,u,t,v,y,x;s=this;s.beforeRender.call(s);s.status.rendered=true;s.elements.tooltip='';s.elements.tooltip=f(s.elements.tooltip);s.elements.tooltip.appendTo(s.options.position.container);s.elements.tooltip.data("qtip",{current:0,interfaces:[s]});s.elements.wrapper=s.elements.tooltip.children("div:first");s.elements.contentWrapper=s.elements.wrapper.children("div:first").css({background:s.options.style.background});s.elements.content=s.elements.contentWrapper.children("div:first").css(q(s.options.style));if(f.browser.msie){s.elements.wrapper.add(s.elements.content).css({zoom:1})}if(s.options.hide.when.event=="unfocus"){s.elements.tooltip.attr("unfocus",true)}if(typeof s.options.style.width.value=="number"){s.updateWidth()}if(f("").get(0).getContext||f.browser.msie){if(s.options.style.border.radius>0){m.call(s)}else{s.elements.contentWrapper.css({border:s.options.style.border.width+"px solid "+s.options.style.border.color})}if(s.options.style.tip.corner!==false){e.call(s)}}else{s.elements.contentWrapper.css({border:s.options.style.border.width+"px solid "+s.options.style.border.color});s.options.style.border.radius=0;s.options.style.tip.corner=false;f.fn.qtip.log.error.call(s,2,f.fn.qtip.constants.CANVAS_VML_NOT_SUPPORTED,"render")}if((typeof s.options.content.text=="string"&&s.options.content.text.length>0)||(s.options.content.text.jquery&&s.options.content.text.length>0)){u=s.options.content.text}else{if(typeof s.elements.target.attr("title")=="string"&&s.elements.target.attr("title").length>0){u=s.elements.target.attr("title").replace("\\n"," ");s.elements.target.attr("title","")}else{if(typeof s.elements.target.attr("alt")=="string"&&s.elements.target.attr("alt").length>0){u=s.elements.target.attr("alt").replace("\\n"," ");s.elements.target.attr("alt","")}else{u=" ";f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.NO_VALID_CONTENT,"render")}}}if(s.options.content.title.text!==false){j.call(s)}s.updateContent(u);l.call(s);if(s.options.show.ready===true){s.show()}if(s.options.content.url!==false){t=s.options.content.url;v=s.options.content.data;y=s.options.content.method||"get";s.loadContent(t,v,y)}s.onRender.call(s);f.fn.qtip.log.error.call(s,1,f.fn.qtip.constants.EVENT_RENDERED,"render")}function m(){var F,z,t,B,x,E,u,G,D,y,w,C,A,s,v;F=this;F.elements.wrapper.find(".qtip-borderBottom, .qtip-borderTop").remove();t=F.options.style.border.width;B=F.options.style.border.radius;x=F.options.style.border.color||F.options.style.tip.color;E=g(B);u={};for(z in E){u[z]='';if(f("").get(0).getContext){u[z]+=' '}else{if(f.browser.msie){G=B*2+3;u[z]+=' '}}u[z]+="
"}D=F.getDimensions().width-(Math.max(t,B)*2);y='';w='
'+u.topLeft+u.topRight+y;F.elements.wrapper.prepend(w);C='
'+u.bottomLeft+u.bottomRight+y;F.elements.wrapper.append(C);if(f("
").get(0).getContext){F.elements.wrapper.find("canvas").each(function(){A=E[f(this).parent("[rel]:first").attr("rel")];r.call(F,f(this),A,B,x)})}else{if(f.browser.msie){F.elements.tooltip.append(' ')}}s=Math.max(B,(B+(t-B)));v=Math.max(t-B,0);F.elements.contentWrapper.css({border:"0px solid "+x,borderWidth:v+"px "+s+"px"})}function r(u,w,s,t){var v=u.get(0).getContext("2d");v.fillStyle=t;v.beginPath();v.arc(w[0],w[1],s,0,Math.PI*2,false);v.fill()}function e(v){var t,s,x,u,w;t=this;if(t.elements.tip!==null){t.elements.tip.remove()}s=t.options.style.tip.color||t.options.style.border.color;if(t.options.style.tip.corner===false){return}else{if(!v){v=t.options.style.tip.corner}}x=b(v,t.options.style.tip.size.width,t.options.style.tip.size.height);t.elements.tip='';if(f("").get(0).getContext){t.elements.tip+=' '}else{if(f.browser.msie){u=t.options.style.tip.size.width+","+t.options.style.tip.size.height;w="m"+x[0][0]+","+x[0][1];w+=" l"+x[1][0]+","+x[1][1];w+=" "+x[2][0]+","+x[2][1];w+=" xe";t.elements.tip+=' ';t.elements.tip+=' ';t.elements.contentWrapper.css("position","relative")}}t.elements.tooltip.prepend(t.elements.tip+"
");t.elements.tip=t.elements.tooltip.find("."+t.options.style.classes.tip).eq(0);if(f("").get(0).getContext){h.call(t,t.elements.tip.find("canvas:first"),x,s)}if(v.search(/top/)!==-1&&f.browser.msie&&parseInt(f.browser.version.charAt(0))===6){t.elements.tip.css({marginTop:-4})}n.call(t,v)}function h(t,v,s){var u=t.get(0).getContext("2d");u.fillStyle=s;u.beginPath();u.moveTo(v[0][0],v[0][1]);u.lineTo(v[1][0],v[1][1]);u.lineTo(v[2][0],v[2][1]);u.fill()}function n(u){var t,w,s,x,v;t=this;if(t.options.style.tip.corner===false||!t.elements.tip){return}if(!u){u=t.elements.tip.attr("rel")}w=positionAdjust=(f.browser.msie)?1:0;t.elements.tip.css(u.match(/left|right|top|bottom/)[0],0);if(u.search(/top|bottom/)!==-1){if(f.browser.msie){if(parseInt(f.browser.version.charAt(0))===6){positionAdjust=(u.search(/top/)!==-1)?-3:1}else{positionAdjust=(u.search(/top/)!==-1)?1:2}}if(u.search(/Middle/)!==-1){t.elements.tip.css({left:"50%",marginLeft:-(t.options.style.tip.size.width/2)})}else{if(u.search(/Left/)!==-1){t.elements.tip.css({left:t.options.style.border.radius-w})}else{if(u.search(/Right/)!==-1){t.elements.tip.css({right:t.options.style.border.radius+w})}}}if(u.search(/top/)!==-1){t.elements.tip.css({top:-positionAdjust})}else{t.elements.tip.css({bottom:positionAdjust})}}else{if(u.search(/left|right/)!==-1){if(f.browser.msie){positionAdjust=(parseInt(f.browser.version.charAt(0))===6)?1:((u.search(/left/)!==-1)?1:2)}if(u.search(/Middle/)!==-1){t.elements.tip.css({top:"50%",marginTop:-(t.options.style.tip.size.height/2)})}else{if(u.search(/Top/)!==-1){t.elements.tip.css({top:t.options.style.border.radius-w})}else{if(u.search(/Bottom/)!==-1){t.elements.tip.css({bottom:t.options.style.border.radius+w})}}}if(u.search(/left/)!==-1){t.elements.tip.css({left:-positionAdjust})}else{t.elements.tip.css({right:positionAdjust})}}}s="padding-"+u.match(/left|right|top|bottom/)[0];x=t.options.style.tip.size[(s.search(/left|right/)!==-1)?"width":"height"];t.elements.tooltip.css("padding",0);t.elements.tooltip.css(s,x);if(f.browser.msie&&parseInt(f.browser.version.charAt(0))==6){v=parseInt(t.elements.tip.css("margin-top"))||0;v+=parseInt(t.elements.content.css("margin-top"))||0;t.elements.tip.css({marginTop:v})}}function j(){var s=this;if(s.elements.title!==null){s.elements.title.remove()}s.elements.title=f('').css(q(s.options.style.title,true)).css({zoom:(f.browser.msie)?1:0}).prependTo(s.elements.contentWrapper);if(s.options.content.title.text){s.updateTitle.call(s,s.options.content.title.text)}if(s.options.content.title.button!==false&&typeof s.options.content.title.button=="string"){s.elements.button=f('
').css(q(s.options.style.button,true)).html(s.options.content.title.button).prependTo(s.elements.title).click(function(t){if(!s.status.disabled){s.hide(t)}})}}function l(){var t,v,u,s;t=this;v=t.options.show.when.target;u=t.options.hide.when.target;if(t.options.hide.fixed){u=u.add(t.elements.tooltip)}if(t.options.hide.when.event=="inactive"){s=["click","dblclick","mousedown","mouseup","mousemove","mouseout","mouseenter","mouseleave","mouseover"];function y(z){if(t.status.disabled===true){return}clearTimeout(t.timers.inactive);t.timers.inactive=setTimeout(function(){f(s).each(function(){u.unbind(this+".qtip-inactive");t.elements.content.unbind(this+".qtip-inactive")});t.hide(z)},t.options.hide.delay)}}else{if(t.options.hide.fixed===true){t.elements.tooltip.bind("mouseover.qtip",function(){if(t.status.disabled===true){return}clearTimeout(t.timers.hide)})}}function x(z){if(t.status.disabled===true){return}if(t.options.hide.when.event=="inactive"){f(s).each(function(){u.bind(this+".qtip-inactive",y);t.elements.content.bind(this+".qtip-inactive",y)});y()}clearTimeout(t.timers.show);clearTimeout(t.timers.hide);t.timers.show=setTimeout(function(){t.show(z)},t.options.show.delay)}function w(z){if(t.status.disabled===true){return}if(t.options.hide.fixed===true&&t.options.hide.when.event.search(/mouse(out|leave)/i)!==-1&&f(z.relatedTarget).parents("div.qtip[qtip]").length>0){z.stopPropagation();z.preventDefault();clearTimeout(t.timers.hide);return false}clearTimeout(t.timers.show);clearTimeout(t.timers.hide);t.elements.tooltip.stop(true,true);t.timers.hide=setTimeout(function(){t.hide(z)},t.options.hide.delay)}if((t.options.show.when.target.add(t.options.hide.when.target).length===1&&t.options.show.when.event==t.options.hide.when.event&&t.options.hide.when.event!=="inactive")||t.options.hide.when.event=="unfocus"){t.cache.toggle=0;v.bind(t.options.show.when.event+".qtip",function(z){if(t.cache.toggle==0){x(z)}else{w(z)}})}else{v.bind(t.options.show.when.event+".qtip",x);if(t.options.hide.when.event!=="inactive"){u.bind(t.options.hide.when.event+".qtip",w)}}if(t.options.position.type.search(/(fixed|absolute)/)!==-1){t.elements.tooltip.bind("mouseover.qtip",t.focus)}if(t.options.position.target==="mouse"&&t.options.position.type!=="static"){v.bind("mousemove.qtip",function(z){t.cache.mouse={x:z.pageX,y:z.pageY};if(t.status.disabled===false&&t.options.position.adjust.mouse===true&&t.options.position.type!=="static"&&t.elements.tooltip.css("display")!=="none"){t.updatePosition(z)}})}}function o(u,v,A){var z,s,x,y,t,w;z=this;if(A.corner=="center"){return v.position}s=f.extend({},u);y={x:false,y:false};t={left:(s.left
=f.fn.qtip.cache.screen.width+f.fn.qtip.cache.screen.scroll.left),top:(s.top=f.fn.qtip.cache.screen.height+f.fn.qtip.cache.screen.scroll.top)};x={left:(t.left&&(A.corner.search(/right/i)!=-1||(A.corner.search(/right/i)==-1&&!t.right))),right:(t.right&&(A.corner.search(/left/i)!=-1||(A.corner.search(/left/i)==-1&&!t.left))),top:(t.top&&A.corner.search(/top/i)==-1),bottom:(t.bottom&&A.corner.search(/bottom/i)==-1)};if(x.left){if(z.options.position.target!=="mouse"){s.left=v.position.left+v.dimensions.width}else{s.left=z.cache.mouse.x}y.x="Left"}else{if(x.right){if(z.options.position.target!=="mouse"){s.left=v.position.left-A.dimensions.width}else{s.left=z.cache.mouse.x-A.dimensions.width}y.x="Right"}}if(x.top){if(z.options.position.target!=="mouse"){s.top=v.position.top+v.dimensions.height}else{s.top=z.cache.mouse.y}y.y="top"}else{if(x.bottom){if(z.options.position.target!=="mouse"){s.top=v.position.top-A.dimensions.height}else{s.top=z.cache.mouse.y-A.dimensions.height}y.y="bottom"}}if(s.left<0){s.left=u.left;y.x=false}if(s.top<0){s.top=u.top;y.y=false}if(z.options.style.tip.corner!==false){s.corner=new String(A.corner);if(y.x!==false){s.corner=s.corner.replace(/Left|Right|Middle/,y.x)}if(y.y!==false){s.corner=s.corner.replace(/top|bottom/,y.y)}if(s.corner!==z.elements.tip.attr("rel")){e.call(z,s.corner)}}return s}function q(u,t){var v,s;v=f.extend(true,{},u);for(s in v){if(t===true&&s.search(/(tip|classes)/i)!==-1){delete v[s]}else{if(!t&&s.search(/(width|border|tip|title|classes|user)/i)!==-1){delete v[s]}}}return v}function c(s){if(typeof s.tip!=="object"){s.tip={corner:s.tip}}if(typeof s.tip.size!=="object"){s.tip.size={width:s.tip.size,height:s.tip.size}}if(typeof s.border!=="object"){s.border={width:s.border}}if(typeof s.width!=="object"){s.width={value:s.width}}if(typeof s.width.max=="string"){s.width.max=parseInt(s.width.max.replace(/([0-9]+)/i,"$1"))}if(typeof s.width.min=="string"){s.width.min=parseInt(s.width.min.replace(/([0-9]+)/i,"$1"))}if(typeof s.tip.size.x=="number"){s.tip.size.width=s.tip.size.x;delete s.tip.size.x}if(typeof s.tip.size.y=="number"){s.tip.size.height=s.tip.size.y;delete s.tip.size.y}return s}function a(){var s,t,u,x,v,w;s=this;u=[true,{}];for(t=0;t0){v.tip.size.width+=1}if(v.tip.size.height%2>0){v.tip.size.height+=1}if(v.tip.corner===true){v.tip.corner=(s.options.position.corner.tooltip==="center")?false:s.options.position.corner.tooltip}return v}function b(v,u,t){var s={bottomRight:[[0,0],[u,t],[u,0]],bottomLeft:[[0,0],[u,0],[0,t]],topRight:[[0,t],[u,0],[u,t]],topLeft:[[0,0],[0,t],[u,t]],topMiddle:[[0,t],[u/2,0],[u,t]],bottomMiddle:[[0,0],[u,0],[u/2,t]],rightMiddle:[[0,0],[u,t/2],[0,t]],leftMiddle:[[u,0],[u,t],[0,t/2]]};s.leftTop=s.bottomRight;s.rightTop=s.bottomLeft;s.leftBottom=s.topRight;s.rightBottom=s.topLeft;return s[v]}function g(s){var t;if(f("").get(0).getContext){t={topLeft:[s,s],topRight:[0,s],bottomLeft:[s,0],bottomRight:[0,0]}}else{if(f.browser.msie){t={topLeft:[-90,90,0],topRight:[-90,90,-s],bottomLeft:[90,270,0],bottomRight:[90,270,-s]}}}return t}function k(){var s,t,u;s=this;u=s.getDimensions();t='';s.elements.bgiframe=s.elements.wrapper.prepend(t).children(".qtip-bgiframe:first")}f(document).ready(function(){f.fn.qtip.cache={screen:{scroll:{left:f(window).scrollLeft(),top:f(window).scrollTop()},width:f(window).width(),height:f(window).height()}};var s;f(window).bind("resize scroll",function(t){clearTimeout(s);s=setTimeout(function(){if(t.type==="scroll"){f.fn.qtip.cache.screen.scroll={left:f(window).scrollLeft(),top:f(window).scrollTop()}}else{f.fn.qtip.cache.screen.width=f(window).width();f.fn.qtip.cache.screen.height=f(window).height()}for(i=0;i1){u.hide(t)}})}})});f.fn.qtip.interfaces=[];f.fn.qtip.log={error:function(){return this}};f.fn.qtip.constants={};f.fn.qtip.defaults={content:{prerender:false,text:false,url:false,data:null,title:{text:false,button:false}},position:{target:false,corner:{target:"bottomRight",tooltip:"topLeft"},adjust:{x:0,y:0,mouse:true,screen:false,scroll:true,resize:true},type:"absolute",container:false},show:{when:{target:false,event:"mouseover"},effect:{type:"fade",length:100},delay:140,solo:false,ready:false},hide:{when:{target:false,event:"mouseout"},effect:{type:"fade",length:100},delay:0,fixed:false},api:{beforeRender:function(){},onRender:function(){},beforePositionUpdate:function(){},onPositionUpdate:function(){},beforeShow:function(){},onShow:function(){},beforeHide:function(){},onHide:function(){},beforeContentUpdate:function(){},onContentUpdate:function(){},beforeContentLoad:function(){},onContentLoad:function(){},beforeTitleUpdate:function(){},onTitleUpdate:function(){},beforeDestroy:function(){},onDestroy:function(){},beforeFocus:function(){},onFocus:function(){}}};f.fn.qtip.styles={defaults:{background:"white",color:"#111",overflow:"hidden",textAlign:"left",width:{min:0,max:250},padding:"5px 9px",border:{width:1,radius:0,color:"#d3d3d3"},tip:{corner:false,color:false,size:{width:13,height:13},opacity:1},title:{background:"#e1e1e1",fontWeight:"bold",padding:"7px 12px"},button:{cursor:"pointer"},classes:{target:"",tip:"qtip-tip",title:"qtip-title",button:"qtip-button",content:"qtip-content",active:"qtip-active"}},cream:{border:{width:3,radius:0,color:"#F9E98E"},title:{background:"#F0DE7D",color:"#A27D35"},background:"#FBF7AA",color:"#A27D35",classes:{tooltip:"qtip-cream"}},light:{border:{width:3,radius:0,color:"#E2E2E2"},title:{background:"#f1f1f1",color:"#454545"},background:"white",color:"#454545",classes:{tooltip:"qtip-light"}},dark:{border:{width:3,radius:0,color:"#303030"},title:{background:"#404040",color:"#f3f3f3"},background:"#505050",color:"#f3f3f3",classes:{tooltip:"qtip-dark"}},red:{border:{width:3,radius:0,color:"#CE6F6F"},title:{background:"#f28279",color:"#9C2F2F"},background:"#F79992",color:"#9C2F2F",classes:{tooltip:"qtip-red"}},green:{border:{width:3,radius:0,color:"#A9DB66"},title:{background:"#b9db8c",color:"#58792E"},background:"#CDE6AC",color:"#58792E",classes:{tooltip:"qtip-green"}},blue:{border:{width:3,radius:0,color:"#ADD9ED"},title:{background:"#D0E9F5",color:"#5E99BD"},background:"#E5F6FE",color:"#4D9FBF",classes:{tooltip:"qtip-blue"}}}})(jQuery);
--------------------------------------------------------------------------------