Showing preview only (742K chars total). Download the full file or copy to clipboard to get everything.
Repository: jkrall/analytical
Branch: master
Commit: 486e157b7dcd
Files: 213
Total size: 682.5 KB
Directory structure:
gitextract_afh5kztq/
├── .document
├── .gitignore
├── .rspec
├── .rvmrc
├── CHANGELOG.md
├── Gemfile
├── Guardfile
├── LICENSE
├── README.rdoc
├── Rakefile
├── VERSION
├── analytical.gemspec
├── app/
│ └── views/
│ └── application/
│ └── _analytical_javascript.html.erb
├── example/
│ ├── .gitignore
│ ├── rails2.3/
│ │ ├── Gemfile
│ │ ├── README
│ │ ├── Rakefile
│ │ ├── app/
│ │ │ ├── controllers/
│ │ │ │ ├── application_controller.rb
│ │ │ │ └── page_controller.rb
│ │ │ ├── helpers/
│ │ │ │ └── application_helper.rb
│ │ │ └── views/
│ │ │ ├── layouts/
│ │ │ │ └── application.html.erb
│ │ │ └── page/
│ │ │ ├── index.html.erb
│ │ │ ├── test_a.html.erb
│ │ │ └── test_b.html.erb
│ │ ├── config/
│ │ │ ├── boot.rb
│ │ │ ├── database.yml
│ │ │ ├── environment.rb
│ │ │ ├── environments/
│ │ │ │ ├── development.rb
│ │ │ │ ├── production.rb
│ │ │ │ └── test.rb
│ │ │ ├── initializers/
│ │ │ │ ├── backtrace_silencers.rb
│ │ │ │ ├── cookie_verification_secret.rb
│ │ │ │ ├── inflections.rb
│ │ │ │ ├── mime_types.rb
│ │ │ │ ├── new_rails_defaults.rb
│ │ │ │ └── session_store.rb
│ │ │ ├── locales/
│ │ │ │ └── en.yml
│ │ │ └── routes.rb
│ │ ├── db/
│ │ │ ├── development.sqlite3
│ │ │ └── seeds.rb
│ │ ├── doc/
│ │ │ └── README_FOR_APP
│ │ ├── public/
│ │ │ ├── 404.html
│ │ │ ├── 422.html
│ │ │ ├── 500.html
│ │ │ ├── javascripts/
│ │ │ │ ├── application.js
│ │ │ │ ├── controls.js
│ │ │ │ ├── dragdrop.js
│ │ │ │ ├── effects.js
│ │ │ │ └── prototype.js
│ │ │ └── robots.txt
│ │ ├── script/
│ │ │ ├── about
│ │ │ ├── console
│ │ │ ├── dbconsole
│ │ │ ├── destroy
│ │ │ ├── generate
│ │ │ ├── performance/
│ │ │ │ ├── benchmarker
│ │ │ │ └── profiler
│ │ │ ├── plugin
│ │ │ ├── runner
│ │ │ └── server
│ │ └── test/
│ │ ├── performance/
│ │ │ └── browsing_test.rb
│ │ └── test_helper.rb
│ ├── rails3/
│ │ ├── Gemfile
│ │ ├── README
│ │ ├── Rakefile
│ │ ├── app/
│ │ │ ├── controllers/
│ │ │ │ ├── application_controller.rb
│ │ │ │ └── page_controller.rb
│ │ │ ├── helpers/
│ │ │ │ ├── application_helper.rb
│ │ │ │ └── page_helper.rb
│ │ │ └── views/
│ │ │ ├── layouts/
│ │ │ │ └── application.html.erb
│ │ │ └── page/
│ │ │ ├── index.html.erb
│ │ │ ├── test_a.html.erb
│ │ │ └── test_b.html.erb
│ │ ├── config/
│ │ │ ├── analytical.yml
│ │ │ ├── application.rb
│ │ │ ├── boot.rb
│ │ │ ├── database.yml
│ │ │ ├── environment.rb
│ │ │ ├── environments/
│ │ │ │ ├── development.rb
│ │ │ │ ├── production.rb
│ │ │ │ └── test.rb
│ │ │ ├── initializers/
│ │ │ │ ├── backtrace_silencers.rb
│ │ │ │ ├── inflections.rb
│ │ │ │ ├── mime_types.rb
│ │ │ │ ├── secret_token.rb
│ │ │ │ └── session_store.rb
│ │ │ ├── locales/
│ │ │ │ └── en.yml
│ │ │ └── routes.rb
│ │ ├── config.ru
│ │ ├── db/
│ │ │ ├── development.sqlite3
│ │ │ ├── production.sqlite3
│ │ │ └── seeds.rb
│ │ ├── doc/
│ │ │ └── README_FOR_APP
│ │ ├── lib/
│ │ │ └── tasks/
│ │ │ └── .gitkeep
│ │ ├── public/
│ │ │ ├── 404.html
│ │ │ ├── 422.html
│ │ │ ├── 500.html
│ │ │ ├── javascripts/
│ │ │ │ ├── application.js
│ │ │ │ ├── controls.js
│ │ │ │ ├── dragdrop.js
│ │ │ │ ├── effects.js
│ │ │ │ ├── prototype.js
│ │ │ │ └── rails.js
│ │ │ ├── robots.txt
│ │ │ └── stylesheets/
│ │ │ └── .gitkeep
│ │ ├── script/
│ │ │ └── rails
│ │ ├── test/
│ │ │ ├── functional/
│ │ │ │ └── page_controller_test.rb
│ │ │ ├── performance/
│ │ │ │ └── browsing_test.rb
│ │ │ ├── test_helper.rb
│ │ │ └── unit/
│ │ │ └── helpers/
│ │ │ └── page_helper_test.rb
│ │ └── vendor/
│ │ └── plugins/
│ │ └── .gitkeep
│ └── rails3.1/
│ ├── Gemfile
│ ├── README
│ ├── Rakefile
│ ├── app/
│ │ ├── assets/
│ │ │ ├── javascripts/
│ │ │ │ └── application.js
│ │ │ └── stylesheets/
│ │ │ └── application.css
│ │ ├── controllers/
│ │ │ ├── application_controller.rb
│ │ │ └── page_controller.rb
│ │ ├── helpers/
│ │ │ └── application_helper.rb
│ │ ├── mailers/
│ │ │ └── .gitkeep
│ │ ├── models/
│ │ │ └── .gitkeep
│ │ └── views/
│ │ ├── layouts/
│ │ │ └── application.html.erb
│ │ └── page/
│ │ ├── index.html.erb
│ │ ├── test_a.html.erb
│ │ └── test_b.html.erb
│ ├── config/
│ │ ├── application.rb
│ │ ├── boot.rb
│ │ ├── database.yml
│ │ ├── environment.rb
│ │ ├── environments/
│ │ │ ├── development.rb
│ │ │ ├── production.rb
│ │ │ └── test.rb
│ │ ├── initializers/
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── inflections.rb
│ │ │ ├── mime_types.rb
│ │ │ ├── secret_token.rb
│ │ │ ├── session_store.rb
│ │ │ └── wrap_parameters.rb
│ │ ├── locales/
│ │ │ └── en.yml
│ │ └── routes.rb
│ ├── config.ru
│ ├── db/
│ │ ├── development.sqlite3
│ │ └── seeds.rb
│ ├── doc/
│ │ └── README_FOR_APP
│ ├── lib/
│ │ ├── assets/
│ │ │ └── .gitkeep
│ │ └── tasks/
│ │ └── .gitkeep
│ ├── public/
│ │ ├── 404.html
│ │ ├── 422.html
│ │ ├── 500.html
│ │ └── robots.txt
│ ├── script/
│ │ └── rails
│ ├── test/
│ │ ├── fixtures/
│ │ │ └── .gitkeep
│ │ ├── functional/
│ │ │ └── .gitkeep
│ │ ├── integration/
│ │ │ └── .gitkeep
│ │ ├── performance/
│ │ │ └── browsing_test.rb
│ │ ├── test_helper.rb
│ │ └── unit/
│ │ └── .gitkeep
│ └── vendor/
│ ├── assets/
│ │ └── stylesheets/
│ │ └── .gitkeep
│ └── plugins/
│ └── .gitkeep
├── lib/
│ ├── analytical/
│ │ ├── api.rb
│ │ ├── bot_detector.rb
│ │ ├── command_store.rb
│ │ ├── modules/
│ │ │ ├── adroll.rb
│ │ │ ├── adwords.rb
│ │ │ ├── base.rb
│ │ │ ├── chartbeat.rb
│ │ │ ├── click_tale.rb
│ │ │ ├── clicky.rb
│ │ │ ├── comscore.rb
│ │ │ ├── console.rb
│ │ │ ├── crazy_egg.rb
│ │ │ ├── gauges.rb
│ │ │ ├── google.rb
│ │ │ ├── google_optimizer.rb
│ │ │ ├── google_universal.rb
│ │ │ ├── hubspot.rb
│ │ │ ├── kiss_metrics.rb
│ │ │ ├── loopfuse.rb
│ │ │ ├── microsoft_ads.rb
│ │ │ ├── mixpanel.rb
│ │ │ ├── mouseflow.rb
│ │ │ ├── optimizely.rb
│ │ │ ├── performancing.rb
│ │ │ ├── quantcast.rb
│ │ │ ├── reinvigorate.rb
│ │ │ └── segment_io.rb
│ │ ├── rails/
│ │ │ └── engine.rb
│ │ └── session_command_store.rb
│ └── analytical.rb
├── rails/
│ └── init.rb
└── spec/
├── analytical/
│ ├── api_spec.rb
│ ├── bot_detector_spec.rb
│ ├── command_store_spec.rb
│ ├── modules/
│ │ ├── adroll_spec.rb
│ │ ├── adwords_spec.rb
│ │ ├── base_spec.rb
│ │ ├── chartbeat_spec.rb
│ │ ├── clicky_spec.rb
│ │ ├── comscore_spec.rb
│ │ ├── gauges_spec.rb
│ │ ├── google_spec.rb
│ │ ├── google_universal_spec.rb
│ │ ├── kiss_metrics_spec.rb
│ │ ├── mixpanel_spec.rb
│ │ ├── optimizely_spec.rb
│ │ ├── quantcast.rb
│ │ ├── reinvigorate_spec.rb
│ │ └── segment_io_spec.rb
│ └── session_command_store_spec.rb
├── analytical_spec.rb
├── config/
│ └── analytical.yml
├── spec.opts
└── spec_helper.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .document
================================================
README.rdoc
lib/**/*.rb
bin/*
features/**/*.feature
LICENSE
================================================
FILE: .gitignore
================================================
## MAC OS
.DS_Store
## TEXTMATE
*.tmproj
tmtags
## EMACS
*~
\#*
.\#*
## VIM
*.swp
## PROJECT::GENERAL
coverage
rdoc
pkg
## PROJECT::SPECIFIC
.bundle
.idea
bin
# RAILS
log
================================================
FILE: .rspec
================================================
--colour
================================================
FILE: .rvmrc
================================================
#!/usr/bin/env bash
# This is an RVM Project .rvmrc file, used to automatically load the ruby
# development environment upon cd'ing into the directory
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
# Only full ruby name is supported here, for short names use:
# echo "rvm use 2.0.0" > .rvmrc
environment_id="ruby-2.0.0-p353@analytical"
# Uncomment the following lines if you want to verify rvm version per project
# rvmrc_rvm_version="1.24.7 (master)" # 1.10.1 seems like a safe start
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | __rvm_awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
# return 1
# }
# First we attempt to load the desired environment directly from the environment
# file. This is very fast and efficient compared to running through the entire
# CLI and selector. If you want feedback on which environment was used then
# insert the word 'use' after --create as this triggers verbose mode.
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
then
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"*
do
if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]]
then \. "${__hook}" || true
fi
done
unset __hook
if (( ${rvm_use_flag:=1} >= 2 )) # display only when forced
then
if [[ $- == *i* ]] # check for interactive shells
then printf "%b" "Using: $(tput setaf 2 2>/dev/null)$GEM_HOME$(tput sgr0 2>/dev/null)
" # show the user the ruby and gemset they are using in green
else printf "%b" "Using: $GEM_HOME
" # don't use colors in non-interactive shells
fi
fi
else
# If the environment file has not yet been created, use the RVM CLI to select.
rvm --create "$environment_id" || {
echo "Failed to create RVM environment '${environment_id}'."
return 1
}
fi
# If you use bundler, this might be useful to you:
# if [[ -s Gemfile ]] && {
# ! builtin command -v bundle >/dev/null ||
# builtin command -v bundle | GREP_OPTIONS="" \grep $rvm_path/bin/bundle >/dev/null
# }
# then
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
# gem install bundler
# fi
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
# then
# bundle install | GREP_OPTIONS="" \grep -vE '^Using|Your bundle is complete'
# fi
================================================
FILE: CHANGELOG.md
================================================
# Analytical Changelog
## 3.0.12
* Fixed version checking so it works with Rails 3.2
* Fixed example configuration in README
* Enhanced google module
## 3.0.9
* Fixed bug that was causing problems in Rails 2.3 & 3.0 (Issue #19)
* Cleaned up gemspec, Rakefile, added Changelog (Issue #26)
* Added example apps for rails 2.3, 3.0, 3.1.
## 3.0.8
* Pulled in changes to update MixPanel event tracking (#25)
## 3.0.7
* Fixed broken clicky tests (#20)
* "Not all options are a hash and not all options are modules." (#21 and e20b256c8b)
## 3.0.2
* Updated Clicky so use async loading
## 3.0.0
*Significant update (tried to maintain backward compatibility)*
* Support filtering modules, per-request (see README)
* Added javascript helpers, enabled by default (see README)
## 2.11.0
*Significant update (tried to maintain backward compatibility)*
* Modified analytical.yml structure to support environment-specific settings (d5e893c289)
================================================
FILE: Gemfile
================================================
source :rubygems
group :development, :test do
gem 'rails', '3.0.9'
gem 'activesupport'
gem 'activemodel'
gem 'rspec-rails', '~> 2.11'
gem 'jeweler'
gem 'diff-lcs'
gem 'guard'
gem 'guard-rspec'
gem 'rb-fsevent', ">= 0.9.2"
gem 'growl'
end
================================================
FILE: Guardfile
================================================
# A sample Guardfile
# More info at http://github.com/guard/guard#readme
guard 'rspec', :version => 1 do
watch(/^spec\/(.*)_spec.rb/)
watch(/^spec\/spec_helper.rb/) { "spec" }
watch(/^lib\/(.*)\.rb/) { |m| "spec/lib/#{m[1]}_spec.rb" }
end
================================================
FILE: LICENSE
================================================
Copyright (c) 2009 Joshua Krall
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.rdoc
================================================
= Analytical
Gem for managing multiple analytics services in your rails app.
{<img src="https://secure.travis-ci.org/jkrall/analytical.png" />}[http://travis-ci.org/jkrall/analytical]
Service implementations include:
* Google Analytics
* Google Adwords (conversion tracking)
* Clicky[http://getclicky.com]
* KISSMetrics[http://kissmetrics.com]
* Hubspot[http://hubspot.com]
* CrazyEgg[http://www.crazyegg.com]
* Chartbeat[http://chartbeat.com]
* {ComScore Direct}[http://direct.comscore.com]
* Optimizely[http://www.optimizely.com]
* Loopfuse
* Clicktale
* Google Website Optimizer
* Performancing
* Quantcast[http://www.quantcast.com]
* MixPanel[http://www.mixpanel.com]
* Gauges[http://get.gaug.es]
* Segment.io[http://segment.io]
* Mouseflow[http://mouseflow.com]
== Usage
Add the following to your controllers:
analytical
Add a configuration file (config/analytical.yml) to declare your API keys, like so:
production:
google:
key: UA-5555555-5
clicky:
key: 55555
development:
test:
You can add different configurations for different environments.
By default, all the declared analytics modules are loaded. You can override this behavior in the controller.
analytical :modules=>[:console, :google, :clicky]
Then, in your template files, you'll want to add the analytical helper methods for initializing the tracking javascript:
<!DOCTYPE html>
<html>
<head>
<%= raw analytical.head_prepend_javascript %>
<title>Example</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
<% analytical.identify '5', :email=>'josh@transfs.com' %>
<%= raw analytical.head_append_javascript %>
</head>
<body>
<%= raw analytical.body_prepend_javascript %>
<%= yield %>
<%= raw analytical.body_append_javascript %>
</body>
</html>
Note the example above also includes an identify() command that will apply to every page. More likely, you'll want to make this identify() command conditional so that it only applies when you have a logged-in user:
<% analytical.identify(current_user.id, :email=>current_user.email) if current_user %>
You can sprinkle the track() and event() tracking methods throughout your views & controllers as needed.
analytical.track '/a/really/nice/url'
analytical.event 'Some Awesome Event', :with=>:data
It's possible to conditionally disable analytics by specifying a `disable_if` method.
analytical :disable_if => lambda{ |controller| controller.i_can_haz_tracking? }
Analytical also provides the ability to filter your active modules dynamically:
analytical :filter_modules => lambda{ |controller, modules|
controller.use_google_analytics? ? modules : modules - [:google]
}
This can be useful for enabling the console logger optionally in your app, based on a request parameter:
:filter_modules => lambda { |controller, modules|
controller.use_console_logger? ? [:console] : modules
}
You can also configure modules in the controller by passing a hash to the :modules option
analytical :modules => { :google => { key: 'UA-5555555-5' } }
Finally it is also possible to dynamically specify what modules to use and their configurations, which can come in handy if your site uses multi-tenancy, where every tenant might not wish to use the same modules or configurations for each module.
analytical :modules => lambda{ |controller| controller.analytical_modules }
In this case we would then implement a method in the controller that could look like this:
def analytical_modules
case current_tenant.name.parameterize
when "site-1"
{
:google => { key: 'UA-5555555-5' }
}
when "site-2"
{
:google => { key: 'UA-1111111-1' }
}
end
end
hide_action :analytical_modules
== Adding new modules
New modules should be fairly easy to add. Follow the structure that I've used in the Clicky, Google, and KISSMetrics modules... and you should be fine. All modules should include the Analytical::Base::Api module, so that they have some default behavior for methods that they don't support or need.
== Session-based command queues
By default, any Analytical commands that are queued in a controller that subsequently redirects won't be emitted to the client. This is because the redirect triggers a new request, and everything is cleared out at the beginning of each request.
However, if you would like to be able to queue commands between requests... there's a new option that supports this behavior:
analytical :modules=>[:console, :google], :use_session_store=>true
This will store the queued commands in the user session, clearing them out when they are emitted to the client, but allowing you to make calls like:
analytical.track 'something'
... in your controller. After a redirect, the corresponding track() call will be emitted in the next request made by the client.
NOTE: This is new and somewhat experimental, and could cause problems if you store large amounts of data in the session. (there is a 4k limit to session data)
== Javascript tracking/event commands
Sometimes you want to trigger an analytics track/event via javascript. Analytical now provides a solution for this by default. Appended to your <head> is a simple javascript object that will contain "instantaneous" versions of the tracking commands for each of your modules.
You call these analytical commands like this:
<script type="text/javascript">Analytical.track('/some/url');</script>
<script type="text/javascript">Analytical.event('A javascript event', {with: 'data'});</script>
When you call these commands, it will pass the track/event name & data on to each of the modules. (Take a look at the simple javascript helpers in your <head> for more information.)
To disable this functionality, use
analytical :javascript_helpers => false
== Note on Patches/Pull Requests
I would be extremely happy to accept contributions to this project! If you think something should work differently, send me a message and I'd love to discuss your ideas. Even better:
* Fork the project.
* Make your feature addition or bug fix.
* Add specs for it. This is important so I don't break it in a future version unintentionally.
* Commit, do not mess with rakefile, version, or history.
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
* Send me a pull request. Bonus points for topic branches.
== Current Contributors
These fine folks have contributed patches and new features to this project:
* {Adam Anderson}[http://github.com/scudco]
* {Bryan Liles}[http://github.com/bryanl]
* {Nathan Phelps}[http://github.com/nwp]
* {Adam Anderson}[http://github.com/scudco]
* {Kevin Menard}[http://github.com/nirvdrum]
* {Ablyamitov Ablyamit}[http://github.com/unlimit]
* {Kurt Werle}[http://github.com/kwerle]
* {Olivier Lauzon}[http://github.com/olauzon]
* {Chris Ricca}[https://github.com/ChrisRicca]
* {Rajiv Aaron Manglani}[https://github.com/rajiv]
* {Thomas Dippel}[https://github.com/dipth]
Thanks guys!
== Copyright
Copyright (c) 2010 Joshua Krall. See LICENSE for details.
================================================
FILE: Rakefile
================================================
require 'rubygems'
require 'rake'
begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "analytical"
gem.summary = %Q{Gem for managing multiple analytics services in your rails app.}
gem.description = %Q{Gem for managing multiple analytics services in your rails app.}
gem.email = "josh@feefighters.com"
gem.homepage = "http://github.com/jkrall/analytical"
gem.authors = ["Joshua Krall", "Nathan Phelps", "Adam Anderson", "Kevin Menard", "Ablyamitov Ablyamit", "Kurt Werle", "Olivier Lauzon", "Daniel Doubrovkine"]
gem.files = Dir['lib/**/*'] + Dir['app/**/*'] + Dir['rails/**/*']
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
RSpec::Core::RakeTask.new(:rcov)
task :default => :spec
require 'rdoc/task'
Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
rdoc.rdoc_dir = 'rdoc'
rdoc.title = "analytical #{version}"
rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb')
end
================================================
FILE: VERSION
================================================
3.0.12
================================================
FILE: analytical.gemspec
================================================
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{analytical}
s.version = "3.0.12"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Joshua Krall", "Nathan Phelps", "Adam Anderson", "Kevin Menard", "Ablyamitov Ablyamit", "Kurt Werle", "Olivier Lauzon", "Daniel Doubrovkine"]
s.date = %q{2012-01-24}
s.description = %q{Gem for managing multiple analytics services in your rails app.}
s.email = %q{josh@feefighters.com}
s.extra_rdoc_files = [
"LICENSE",
"README.rdoc"
]
s.files = [
"app/views/application/_analytical_javascript.html.erb",
"lib/analytical.rb",
"lib/analytical/api.rb",
"lib/analytical/bot_detector.rb",
"lib/analytical/command_store.rb",
"lib/analytical/modules/adroll.rb",
"lib/analytical/modules/adwords.rb",
"lib/analytical/modules/base.rb",
"lib/analytical/modules/chartbeat.rb",
"lib/analytical/modules/click_tale.rb",
"lib/analytical/modules/clicky.rb",
"lib/analytical/modules/comscore.rb",
"lib/analytical/modules/console.rb",
"lib/analytical/modules/crazy_egg.rb",
"lib/analytical/modules/google.rb",
"lib/analytical/modules/google_optimizer.rb",
"lib/analytical/modules/hubspot.rb",
"lib/analytical/modules/kiss_metrics.rb",
"lib/analytical/modules/loopfuse.rb",
"lib/analytical/modules/microsoft_ads.rb",
"lib/analytical/modules/mixpanel.rb",
"lib/analytical/modules/optimizely.rb",
"lib/analytical/modules/performancing.rb",
"lib/analytical/modules/quantcast.rb",
"lib/analytical/modules/reinvigorate.rb",
"lib/analytical/rails/engine.rb",
"lib/analytical/session_command_store.rb",
"rails/init.rb"
]
s.homepage = %q{http://github.com/jkrall/analytical}
s.require_paths = ["lib"]
s.rubygems_version = %q{1.6.2}
s.summary = %q{Gem for managing multiple analytics services in your rails app.}
if s.respond_to? :specification_version then
s.specification_version = 3
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_development_dependency(%q<rails>, ["= 3.0.9"])
s.add_development_dependency(%q<activesupport>, [">= 0"])
s.add_development_dependency(%q<activemodel>, [">= 0"])
s.add_development_dependency(%q<rspec>, ["= 2.6.0"])
s.add_development_dependency(%q<rspec-core>, ["= 2.6.4"])
s.add_development_dependency(%q<rspec-expectations>, ["= 2.6.0"])
s.add_development_dependency(%q<rspec-mocks>, ["= 2.6.0"])
s.add_development_dependency(%q<rspec-rails>, ["= 2.6.0"])
s.add_development_dependency(%q<jeweler>, [">= 0"])
s.add_development_dependency(%q<diff-lcs>, [">= 0"])
s.add_development_dependency(%q<guard>, [">= 0"])
s.add_development_dependency(%q<guard-rspec>, [">= 0"])
s.add_development_dependency(%q<rb-fsevent>, [">= 0"])
s.add_development_dependency(%q<growl>, [">= 0"])
else
s.add_dependency(%q<rails>, ["= 3.0.9"])
s.add_dependency(%q<activesupport>, [">= 0"])
s.add_dependency(%q<activemodel>, [">= 0"])
s.add_dependency(%q<rspec>, ["= 2.6.0"])
s.add_dependency(%q<rspec-core>, ["= 2.6.4"])
s.add_dependency(%q<rspec-expectations>, ["= 2.6.0"])
s.add_dependency(%q<rspec-mocks>, ["= 2.6.0"])
s.add_dependency(%q<rspec-rails>, ["= 2.6.0"])
s.add_dependency(%q<jeweler>, [">= 0"])
s.add_dependency(%q<diff-lcs>, [">= 0"])
s.add_dependency(%q<guard>, [">= 0"])
s.add_dependency(%q<guard-rspec>, [">= 0"])
s.add_dependency(%q<rb-fsevent>, [">= 0"])
s.add_dependency(%q<growl>, [">= 0"])
end
else
s.add_dependency(%q<rails>, ["= 3.0.9"])
s.add_dependency(%q<activesupport>, [">= 0"])
s.add_dependency(%q<activemodel>, [">= 0"])
s.add_dependency(%q<rspec>, ["= 2.6.0"])
s.add_dependency(%q<rspec-core>, ["= 2.6.4"])
s.add_dependency(%q<rspec-expectations>, ["= 2.6.0"])
s.add_dependency(%q<rspec-mocks>, ["= 2.6.0"])
s.add_dependency(%q<rspec-rails>, ["= 2.6.0"])
s.add_dependency(%q<jeweler>, [">= 0"])
s.add_dependency(%q<diff-lcs>, [">= 0"])
s.add_dependency(%q<guard>, [">= 0"])
s.add_dependency(%q<guard-rspec>, [">= 0"])
s.add_dependency(%q<rb-fsevent>, [">= 0"])
s.add_dependency(%q<growl>, [">= 0"])
end
end
================================================
FILE: app/views/application/_analytical_javascript.html.erb
================================================
<script type="text/javascript">
var Analytical = {
track: function(page) {
<%= raw analytical.now.track('__PAGE__').gsub(/"__PAGE__"/,'page') %>
},
event: function(name, data) {
if (typeof data === 'undefined') { data = {}; }
<%= raw analytical.now.event('__EVENT__', {}).gsub(/"__EVENT__"/,'name').gsub(/"?\{\}"?/,'data') %>
}
};
</script>
================================================
FILE: example/.gitignore
================================================
.bundle
db/*.sqlite3
log/*.log
tmp/**/*
================================================
FILE: example/rails2.3/Gemfile
================================================
source 'http://rubygems.org'
gem 'rails', '~> 2.3.0'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'analytical', :path => '../..'
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# Bundle the extra gems:
# gem 'bj'
# gem 'nokogiri', '1.4.1'
# gem 'sqlite3-ruby', :require => 'sqlite3'
# gem 'aws-s3', :require => 'aws/s3'
# Bundle gems for certain environments:
# gem 'rspec', :group => :test
# group :test do
# gem 'webrat'
# end
================================================
FILE: example/rails2.3/README
================================================
== Welcome to Rails
Rails is a web-application framework that includes everything needed to create
database-backed web applications according to the Model-View-Control pattern.
This pattern splits the view (also called the presentation) into "dumb" templates
that are primarily responsible for inserting pre-built data in between HTML tags.
The model contains the "smart" domain objects (such as Account, Product, Person,
Post) that holds all the business logic and knows how to persist themselves to
a database. The controller handles the incoming requests (such as Save New Account,
Update Product, Show Post) by manipulating the model and directing data to the view.
In Rails, the model is handled by what's called an object-relational mapping
layer entitled Active Record. This layer allows you to present the data from
database rows as objects and embellish these data objects with business logic
methods. You can read more about Active Record in
link:files/vendor/rails/activerecord/README.html.
The controller and view are handled by the Action Pack, which handles both
layers by its two parts: Action View and Action Controller. These two layers
are bundled in a single package due to their heavy interdependence. This is
unlike the relationship between the Active Record and Action Pack that is much
more separate. Each of these packages can be used independently outside of
Rails. You can read more about Action Pack in
link:files/vendor/rails/actionpack/README.html.
== Getting Started
1. At the command prompt, start a new Rails application using the <tt>rails</tt> command
and your application name. Ex: rails myapp
2. Change directory into myapp and start the web server: <tt>script/server</tt> (run with --help for options)
3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!"
4. Follow the guidelines to start developing your application
== Web Servers
By default, Rails will try to use Mongrel if it's are installed when started with script/server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails
with a variety of other web servers.
Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
getting up and running with mongrel is as easy as: <tt>gem install mongrel</tt>.
More info at: http://mongrel.rubyforge.org
Say other Ruby web servers like Thin and Ebb or regular web servers like Apache or LiteSpeed or
Lighttpd or IIS. The Ruby web servers are run through Rack and the latter can either be setup to use
FCGI or proxy to a pack of Mongrels/Thin/Ebb servers.
== Apache .htaccess example for FCGI/CGI
# General Apache options
AddHandler fastcgi-script .fcgi
AddHandler cgi-script .cgi
Options +FollowSymLinks +ExecCGI
# If you don't want Rails to look in certain directories,
# use the following rewrite rules so that Apache won't rewrite certain requests
#
# Example:
# RewriteCond %{REQUEST_URI} ^/notrails.*
# RewriteRule .* - [L]
# Redirect all requests not available on the filesystem to Rails
# By default the cgi dispatcher is used which is very slow
#
# For better performance replace the dispatcher with the fastcgi one
#
# Example:
# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
RewriteEngine On
# If your Rails application is accessed via an Alias directive,
# then you MUST also set the RewriteBase in this htaccess file.
#
# Example:
# Alias /myrailsapp /path/to/myrailsapp/public
# RewriteBase /myrailsapp
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
# In case Rails experiences terminal errors
# Instead of displaying this message you can supply a file here which will be rendered instead
#
# Example:
# ErrorDocument 500 /500.html
ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
== Debugging Rails
Sometimes your application goes wrong. Fortunately there are a lot of tools that
will help you debug it and get it back on the rails.
First area to check is the application log files. Have "tail -f" commands running
on the server.log and development.log. Rails will automatically display debugging
and runtime information to these files. Debugging info will also be shown in the
browser on requests from 127.0.0.1.
You can also log your own messages directly into the log file from your code using
the Ruby logger class from inside your controllers. Example:
class WeblogController < ActionController::Base
def destroy
@weblog = Weblog.find(params[:id])
@weblog.destroy
logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
end
end
The result will be a message in your log file along the lines of:
Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1
More information on how to use the logger is at http://www.ruby-doc.org/core/
Also, Ruby documentation can be found at http://www.ruby-lang.org/ including:
* The Learning Ruby (Pickaxe) Book: http://www.ruby-doc.org/docs/ProgrammingRuby/
* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
These two online (and free) books will bring you up to speed on the Ruby language
and also on programming in general.
== Debugger
Debugger support is available through the debugger command when you start your Mongrel or
Webrick server with --debugger. This means that you can break out of execution at any point
in the code, investigate and change the model, AND then resume execution!
You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'
Example:
class WeblogController < ActionController::Base
def index
@posts = Post.find(:all)
debugger
end
end
So the controller will accept the action, run the first line, then present you
with a IRB prompt in the server window. Here you can do things like:
>> @posts.inspect
=> "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
#<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
>> @posts.first.title = "hello from a debugger"
=> "hello from a debugger"
...and even better is that you can examine how your runtime objects actually work:
>> f = @posts.first
=> #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
>> f.
Display all 152 possibilities? (y or n)
Finally, when you're ready to resume execution, you enter "cont"
== Console
You can interact with the domain model by starting the console through <tt>script/console</tt>.
Here you'll have all parts of the application configured, just like it is when the
application is running. You can inspect domain models, change values, and save to the
database. Starting the script without arguments will launch it in the development environment.
Passing an argument will specify a different environment, like <tt>script/console production</tt>.
To reload your controllers and models after launching the console run <tt>reload!</tt>
== dbconsole
You can go to the command line of your database directly through <tt>script/dbconsole</tt>.
You would be connected to the database with the credentials defined in database.yml.
Starting the script without arguments will connect you to the development database. Passing an
argument will connect you to a different database, like <tt>script/dbconsole production</tt>.
Currently works for mysql, postgresql and sqlite.
== Description of Contents
app
Holds all the code that's specific to this particular application.
app/controllers
Holds controllers that should be named like weblogs_controller.rb for
automated URL mapping. All controllers should descend from ApplicationController
which itself descends from ActionController::Base.
app/models
Holds models that should be named like post.rb.
Most models will descend from ActiveRecord::Base.
app/views
Holds the template files for the view that should be named like
weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby
syntax.
app/views/layouts
Holds the template files for layouts to be used with views. This models the common
header/footer method of wrapping views. In your views, define a layout using the
<tt>layout :default</tt> and create a file named default.html.erb. Inside default.html.erb,
call <% yield %> to render the view using this layout.
app/helpers
Holds view helpers that should be named like weblogs_helper.rb. These are generated
for you automatically when using script/generate for controllers. Helpers can be used to
wrap functionality for your views into methods.
config
Configuration files for the Rails environment, the routing map, the database, and other dependencies.
db
Contains the database schema in schema.rb. db/migrate contains all
the sequence of Migrations for your schema.
doc
This directory is where your application documentation will be stored when generated
using <tt>rake doc:app</tt>
lib
Application specific libraries. Basically, any kind of custom code that doesn't
belong under controllers, models, or helpers. This directory is in the load path.
public
The directory available for the web server. Contains subdirectories for images, stylesheets,
and javascripts. Also contains the dispatchers and the default HTML files. This should be
set as the DOCUMENT_ROOT of your web server.
script
Helper scripts for automation and generation.
test
Unit and functional tests along with fixtures. When using the script/generate scripts, template
test files will be generated for you and placed in this directory.
vendor
External libraries that the application depends on. Also includes the plugins subdirectory.
If the app has frozen rails, those gems also go here, under vendor/rails/.
This directory is in the load path.
================================================
FILE: example/rails2.3/Rakefile
================================================
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'tasks/rails'
================================================
FILE: example/rails2.3/app/controllers/application_controller.rb
================================================
class ApplicationController < ActionController::Base
helper :all
protect_from_forgery
analytical :modules=>[:console, :google, :clicky], :disable_if=>lambda{|controller| false}, :use_session_store=>true
end
================================================
FILE: example/rails2.3/app/controllers/page_controller.rb
================================================
class PageController < ApplicationController
def index
end
def test_a
end
def test_b
analytical.clicky.track('track link in A')
analytical.track 'track in controller'
end
def test_c
analytical.track 'track in controller that redirects'
redirect_to root_path
end
end
================================================
FILE: example/rails2.3/app/helpers/application_helper.rb
================================================
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
end
================================================
FILE: example/rails2.3/app/views/layouts/application.html.erb
================================================
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<% analytical.identify '5', :email=>'josh@feefighters.com' %>
<%= analytical.head_javascript %>
</head>
<body>
<%= analytical.body_prepend_javascript %>
<%= yield %>
<%= analytical.body_append_javascript %>
</body>
</html>
================================================
FILE: example/rails2.3/app/views/page/index.html.erb
================================================
<h1>Page#index</h1>
<p>
<%= link_to 'A', '/page/test_a' %><br />
<%= link_to 'B', '/page/test_b' %><br />
<%= link_to 'C', '/page/test_c' %><br />
</p>
================================================
FILE: example/rails2.3/app/views/page/test_a.html.erb
================================================
<% analytical.track 'track in view A' %>
<% analytical.event 'Something Important', {:some=>'data'} %>
<h1>Page#test_a</h1>
<p>
<%= link_to 'B', '/page/test_b' %><br />
<%= link_to 'C', '/page/test_c' %><br />
<%= link_to 'index', '/' %><br />
<a href='#' onclick="<%= analytical.now.track('track link in A') %>; return false;">click me to track all modules</a><br />
</p>
================================================
FILE: example/rails2.3/app/views/page/test_b.html.erb
================================================
<h1>Page#test_b</h1>
<p>
<%= link_to 'A', '/page/test_a' %><br />
<%= link_to 'C', '/page/test_c' %><br />
<%= link_to 'index', '/' %><br />
<a href='#' onclick="<%= analytical.console.track('track link in A') %>; return false;">track console only</a><br />
</p>
================================================
FILE: example/rails2.3/config/boot.rb
================================================
# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
module Rails
class << self
def boot!
unless booted?
preinitialize
pick_boot.run
end
end
def booted?
defined? Rails::Initializer
end
def pick_boot
(vendor_rails? ? VendorBoot : GemBoot).new
end
def vendor_rails?
File.exist?("#{RAILS_ROOT}/vendor/rails")
end
def preinitialize
load(preinitializer_path) if File.exist?(preinitializer_path)
end
def preinitializer_path
"#{RAILS_ROOT}/config/preinitializer.rb"
end
end
class Boot
def run
load_initializer
Rails::Initializer.run(:set_load_path)
end
end
class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
Rails::GemDependency.add_frozen_gem_path
end
end
class GemBoot < Boot
def load_initializer
self.class.load_rubygems
load_rails_gem
require 'initializer'
end
def load_rails_gem
if version = self.class.gem_version
gem 'rails', version
else
gem 'rails'
end
rescue Gem::LoadError => load_error
if load_error.message =~ /Could not find RubyGem rails/
STDERR.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
exit 1
else
raise
end
end
class << self
def rubygems_version
Gem::RubyGemsVersion rescue nil
end
def gem_version
if defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION
elsif ENV.include?('RAILS_GEM_VERSION')
ENV['RAILS_GEM_VERSION']
else
parse_gem_version(read_environment_rb)
end
end
def load_rubygems
min_version = '1.3.2'
require 'rubygems'
unless rubygems_version >= min_version
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
exit 1
end
rescue LoadError
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
exit 1
end
def parse_gem_version(text)
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
end
private
def read_environment_rb
File.read("#{RAILS_ROOT}/config/environment.rb")
end
end
end
end
# All that for this:
Rails.boot!
================================================
FILE: example/rails2.3/config/database.yml
================================================
# SQLite version 3.x
# gem install sqlite3-ruby (not necessary on OS X Leopard)
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000
================================================
FILE: example/rails2.3/config/environment.rb
================================================
# Be sure to restart your server when you modify this file
# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.14' unless defined? RAILS_GEM_VERSION
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
Rails::Initializer.run do |config|
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Add additional load paths for your own custom dirs
# config.autoload_paths += %W( #{RAILS_ROOT}/extras )
# Specify gems that this application depends on and have them installed with rake gems:install
# config.gem "bj"
# config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
# config.gem "sqlite3-ruby", :lib => "sqlite3"
# config.gem "aws-s3", :lib => "aws/s3"
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Skip frameworks you're not going to use. To use Rails without a database,
# you must remove the Active Record framework.
# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
config.time_zone = 'UTC'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
# config.i18n.default_locale = :de
end
================================================
FILE: example/rails2.3/config/environments/development.rb
================================================
# Settings specified here will take precedence over those in config/environment.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
================================================
FILE: example/rails2.3/config/environments/production.rb
================================================
# Settings specified here will take precedence over those in config/environment.rb
# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.action_view.cache_template_loading = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Use a different logger for distributed setups
# config.logger = SyslogLogger.new
# Use a different cache store in production
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
================================================
FILE: example/rails2.3/config/environments/test.rb
================================================
# Settings specified here will take precedence over those in config/environment.rb
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_view.cache_template_loading = true
# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Use SQL instead of Active Record's schema dumper when creating the test database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
================================================
FILE: example/rails2.3/config/initializers/backtrace_silencers.rb
================================================
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
================================================
FILE: example/rails2.3/config/initializers/cookie_verification_secret.rb
================================================
# Be sure to restart your server when you modify this file.
# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
ActionController::Base.cookie_verifier_secret = '9f8775eb823fb91b025741105b96651584bd80dca1c1b53e93ddb30e0c093bf3a2fed5326d90f516903dc2b32dc29872b2e380e706cdff5972d6820a7ce3f1fb';
================================================
FILE: example/rails2.3/config/initializers/inflections.rb
================================================
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format
# (all these examples are active by default):
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
================================================
FILE: example/rails2.3/config/initializers/mime_types.rb
================================================
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register_alias "text/html", :iphone
================================================
FILE: example/rails2.3/config/initializers/new_rails_defaults.rb
================================================
# Be sure to restart your server when you modify this file.
# These settings change the behavior of Rails 2 apps and will be defaults
# for Rails 3. You can remove this initializer when Rails 3 is released.
if defined?(ActiveRecord)
# Include Active Record class name as root for JSON serialized output.
ActiveRecord::Base.include_root_in_json = true
# Store the full class name (including module namespace) in STI type column.
ActiveRecord::Base.store_full_sti_class = true
end
ActionController::Routing.generate_best_match = false
# Use ISO 8601 format for JSON serialized times and dates.
ActiveSupport.use_standard_json_time_format = true
# Don't escape HTML entities in JSON, leave that for the #json_escape helper.
# if you're including raw json in an HTML page.
ActiveSupport.escape_html_entities_in_json = false
================================================
FILE: example/rails2.3/config/initializers/session_store.rb
================================================
# Be sure to restart your server when you modify this file.
# Your secret key for verifying cookie session data integrity.
# If you change this key, all old sessions will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
ActionController::Base.session = {
:key => '_example_session',
:secret => '857713e3e2406c40a81798264d0523a082862e124f5b7998ff6c8af1358f58b54e86f0a0793d252d596c9cbbba2c38fd7c08c475977684aaeb58f75872c51850'
}
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rake db:sessions:create")
# ActionController::Base.session_store = :active_record_store
================================================
FILE: example/rails2.3/config/locales/en.yml
================================================
# Sample localization file for English. Add more files in this directory for other locales.
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
en:
hello: "Hello world"
================================================
FILE: example/rails2.3/config/routes.rb
================================================
ActionController::Routing::Routes.draw do |map|
# The priority is based upon order of creation: first created -> highest priority.
# Sample of regular route:
# map.connect 'products/:id', :controller => 'catalog', :action => 'view'
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
# This route can be invoked with purchase_url(:id => product.id)
# Sample resource route (maps HTTP verbs to controller actions automatically):
# map.resources :products
# Sample resource route with options:
# map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
# Sample resource route with sub-resources:
# map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller
# Sample resource route with more complex sub-resources
# map.resources :products do |products|
# products.resources :comments
# products.resources :sales, :collection => { :recent => :get }
# end
# Sample resource route within a namespace:
# map.namespace :admin do |admin|
# # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb)
# admin.resources :products
# end
# You can have the root of your site routed with map.root -- just remember to delete public/index.html.
map.root :controller => "page"
# See how all your routes lay out with "rake routes"
# Install the default routes as the lowest priority.
# Note: These default routes make all actions in every controller accessible via GET requests. You should
# consider removing or commenting them out if you're using named routes and resources.
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
================================================
FILE: example/rails2.3/db/development.sqlite3
================================================
================================================
FILE: example/rails2.3/db/seeds.rb
================================================
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
# Major.create(:name => 'Daley', :city => cities.first)
================================================
FILE: example/rails2.3/doc/README_FOR_APP
================================================
Use this README file to introduce your application and point to useful places in the API for learning more.
Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
================================================
FILE: example/rails2.3/public/404.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>The page you were looking for doesn't exist (404)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
</body>
</html>
================================================
FILE: example/rails2.3/public/422.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>The change you wanted was rejected (422)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
</body>
</html>
================================================
FILE: example/rails2.3/public/500.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>We're sorry, but something went wrong (500)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<h1>We're sorry, but something went wrong.</h1>
<p>We've been notified about this issue and we'll take a look at it shortly.</p>
</div>
</body>
</html>
================================================
FILE: example/rails2.3/public/javascripts/application.js
================================================
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
================================================
FILE: example/rails2.3/public/javascripts/controls.js
================================================
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
var Autocompleter = { };
Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
element = $(element);
this.element = element;
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
this.oldElementValue = this.element.value;
if(this.setOptions)
this.setOptions(options);
else
this.options = options || { };
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.minChars = this.options.minChars || 1;
this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
Position.clone(element, update, {
setHeight: false,
offsetTop: element.offsetHeight
});
}
Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
// Force carriage returns as token delimiters anyway
if (!this.options.tokens.include('\n'))
this.options.tokens.push('\n');
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
(Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
if(this.active)
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.markPrevious();
this.render();
Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
onHover: function(event) {
var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex)
{
this.index = element.autocompleteIndex;
this.render();
}
Event.stop(event);
},
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.selectEntry();
this.hide();
},
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
if(this.hasFocus) {
this.show();
this.active = true;
}
} else {
this.active = false;
this.hide();
}
},
markPrevious: function() {
if(this.index > 0) this.index--;
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++;
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
},
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
getCurrentEntry: function() {
return this.getEntry(this.index);
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = '';
if (this.options.select) {
var nodes = $(selectedElement).select('.' + this.options.select) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var bounds = this.getTokenBounds();
if (bounds[0] != -1) {
var newValue = this.element.value.substr(0, bounds[0]);
var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
this.element.value = newValue + value + this.element.value.substr(bounds[1]);
} else {
this.element.value = value;
}
this.oldElementValue = this.element.value;
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.down().childNodes) {
this.entryCount =
this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
} else {
this.render();
}
}
},
addObservers: function(element) {
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},
onObserverEvent: function() {
this.changed = false;
this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
this.oldElementValue = this.element.value;
},
getToken: function() {
var bounds = this.getTokenBounds();
return this.element.value.substring(bounds[0], bounds[1]).strip();
},
getTokenBounds: function() {
if (null != this.tokenBounds) return this.tokenBounds;
var value = this.element.value;
if (value.strip().empty()) return [-1, 0];
var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
var offset = (diff == this.oldElementValue.length ? 1 : 0);
var prevTokenPos = -1, nextTokenPos = value.length;
var tp;
for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
if (tp > prevTokenPos) prevTokenPos = tp;
tp = value.indexOf(this.options.tokens[index], diff + offset);
if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
});
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
var boundary = Math.min(newS.length, oldS.length);
for (var index = 0; index < boundary; ++index)
if (newS[index] != oldS[index])
return index;
return boundary;
};
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
this.startIndicator();
var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
Autocompleter.Local = Class.create(Autocompleter.Base, {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
},
getUpdatedChoices: function() {
this.updateChoices(this.options.selector(this));
},
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
return "<ul>" + ret.join('') + "</ul>";
}
}, options || { });
}
});
// AJAX in-place editor and collection editor
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
};
Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
this.url = url;
this.element = element = $(element);
this.prepareOptions();
this._controls = { };
arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
Object.extend(this.options, options || { });
if (!this.options.formId && this.element.id) {
this.options.formId = this.element.id + '-inplaceeditor';
if ($(this.options.formId))
this.options.formId = '';
}
if (this.options.externalControl)
this.options.externalControl = $(this.options.externalControl);
if (!this.options.externalControl)
this.options.externalControlOnly = false;
this._originalBackground = this.element.getStyle('background-color') || 'transparent';
this.element.title = this.options.clickToEditText;
this._boundCancelHandler = this.handleFormCancellation.bind(this);
this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
this._boundFailureHandler = this.handleAJAXFailure.bind(this);
this._boundSubmitHandler = this.handleFormSubmission.bind(this);
this._boundWrapperHandler = this.wrapUp.bind(this);
this.registerListeners();
},
checkForEscapeOrReturn: function(e) {
if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
if (Event.KEY_ESC == e.keyCode)
this.handleFormCancellation(e);
else if (Event.KEY_RETURN == e.keyCode)
this.handleFormSubmission(e);
},
createControl: function(mode, handler, extraClasses) {
var control = this.options[mode + 'Control'];
var text = this.options[mode + 'Text'];
if ('button' == control) {
var btn = document.createElement('input');
btn.type = 'submit';
btn.value = text;
btn.className = 'editor_' + mode + '_button';
if ('cancel' == mode)
btn.onclick = this._boundCancelHandler;
this._form.appendChild(btn);
this._controls[mode] = btn;
} else if ('link' == control) {
var link = document.createElement('a');
link.href = '#';
link.appendChild(document.createTextNode(text));
link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
link.className = 'editor_' + mode + '_link';
if (extraClasses)
link.className += ' ' + extraClasses;
this._form.appendChild(link);
this._controls[mode] = link;
}
},
createEditField: function() {
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
var fld;
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
fld = document.createElement('input');
fld.type = 'text';
var size = this.options.size || this.options.cols || 0;
if (0 < size) fld.size = size;
} else {
fld = document.createElement('textarea');
fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
fld.cols = this.options.cols || 40;
}
fld.name = this.options.paramName;
fld.value = text; // No HTML breaks conversion anymore
fld.className = 'editor_field';
if (this.options.submitOnBlur)
fld.onblur = this._boundSubmitHandler;
this._controls.editor = fld;
if (this.options.loadTextURL)
this.loadExternalText();
this._form.appendChild(this._controls.editor);
},
createForm: function() {
var ipe = this;
function addText(mode, condition) {
var text = ipe.options['text' + mode + 'Controls'];
if (!text || condition === false) return;
ipe._form.appendChild(document.createTextNode(text));
};
this._form = $(document.createElement('form'));
this._form.id = this.options.formId;
this._form.addClassName(this.options.formClassName);
this._form.onsubmit = this._boundSubmitHandler;
this.createEditField();
if ('textarea' == this._controls.editor.tagName.toLowerCase())
this._form.appendChild(document.createElement('br'));
if (this.options.onFormCustomization)
this.options.onFormCustomization(this, this._form);
addText('Before', this.options.okControl || this.options.cancelControl);
this.createControl('ok', this._boundSubmitHandler);
addText('Between', this.options.okControl && this.options.cancelControl);
this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
addText('After', this.options.okControl || this.options.cancelControl);
},
destroy: function() {
if (this._oldInnerHTML)
this.element.innerHTML = this._oldInnerHTML;
this.leaveEditMode();
this.unregisterListeners();
},
enterEditMode: function(e) {
if (this._saving || this._editing) return;
this._editing = true;
this.triggerCallback('onEnterEditMode');
if (this.options.externalControl)
this.options.externalControl.hide();
this.element.hide();
this.createForm();
this.element.parentNode.insertBefore(this._form, this.element);
if (!this.options.loadTextURL)
this.postProcessEditField();
if (e) Event.stop(e);
},
enterHover: function(e) {
if (this.options.hoverClassName)
this.element.addClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onEnterHover');
},
getText: function() {
return this.element.innerHTML.unescapeHTML();
},
handleAJAXFailure: function(transport) {
this.triggerCallback('onFailure', transport);
if (this._oldInnerHTML) {
this.element.innerHTML = this._oldInnerHTML;
this._oldInnerHTML = null;
}
},
handleFormCancellation: function(e) {
this.wrapUp();
if (e) Event.stop(e);
},
handleFormSubmission: function(e) {
var form = this._form;
var value = $F(this._controls.editor);
this.prepareSubmission();
var params = this.options.callback(form, value) || '';
if (Object.isString(params))
params = params.toQueryParams();
params.editorId = this.element.id;
if (this.options.htmlResponse) {
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Updater({ success: this.element }, this.url, options);
} else {
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.url, options);
}
if (e) Event.stop(e);
},
leaveEditMode: function() {
this.element.removeClassName(this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
if (this.options.externalControl)
this.options.externalControl.show();
this._saving = false;
this._editing = false;
this._oldInnerHTML = null;
this.triggerCallback('onLeaveEditMode');
},
leaveHover: function(e) {
if (this.options.hoverClassName)
this.element.removeClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onLeaveHover');
},
loadExternalText: function() {
this._form.addClassName(this.options.loadingClassName);
this._controls.editor.disabled = true;
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._form.removeClassName(this.options.loadingClassName);
var text = transport.responseText;
if (this.options.stripLoadedTextTags)
text = text.stripTags();
this._controls.editor.value = text;
this._controls.editor.disabled = false;
this.postProcessEditField();
}.bind(this),
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.options.loadTextURL, options);
},
postProcessEditField: function() {
var fpc = this.options.fieldPostCreation;
if (fpc)
$(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
},
prepareOptions: function() {
this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
[this._extraDefaultOptions].flatten().compact().each(function(defs) {
Object.extend(this.options, defs);
}.bind(this));
},
prepareSubmission: function() {
this._saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
registerListeners: function() {
this._listeners = { };
var listener;
$H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
listener = this[pair.value].bind(this);
this._listeners[pair.key] = listener;
if (!this.options.externalControlOnly)
this.element.observe(pair.key, listener);
if (this.options.externalControl)
this.options.externalControl.observe(pair.key, listener);
}.bind(this));
},
removeForm: function() {
if (!this._form) return;
this._form.remove();
this._form = null;
this._controls = { };
},
showSaving: function() {
this._oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
this.element.addClassName(this.options.savingClassName);
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
},
triggerCallback: function(cbName, arg) {
if ('function' == typeof this.options[cbName]) {
this.options[cbName](this, arg);
}
},
unregisterListeners: function() {
$H(this._listeners).each(function(pair) {
if (!this.options.externalControlOnly)
this.element.stopObserving(pair.key, pair.value);
if (this.options.externalControl)
this.options.externalControl.stopObserving(pair.key, pair.value);
}.bind(this));
},
wrapUp: function(transport) {
this.leaveEditMode();
// Can't use triggerCallback due to backward compatibility: requires
// binding + direct element
this._boundComplete(transport, this.element);
}
});
Object.extend(Ajax.InPlaceEditor.prototype, {
dispose: Ajax.InPlaceEditor.prototype.destroy
});
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
initialize: function($super, element, url, options) {
this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
$super(element, url, options);
},
createEditField: function() {
var list = document.createElement('select');
list.name = this.options.paramName;
list.size = 1;
this._controls.editor = list;
this._collection = this.options.collection || [];
if (this.options.loadCollectionURL)
this.loadCollection();
else
this.checkForExternalText();
this._form.appendChild(this._controls.editor);
},
loadCollection: function() {
this._form.addClassName(this.options.loadingClassName);
this.showLoadingText(this.options.loadingCollectionText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
var js = transport.responseText.strip();
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
throw('Server returned an invalid collection representation.');
this._collection = eval(js);
this.checkForExternalText();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadCollectionURL, options);
},
showLoadingText: function(text) {
this._controls.editor.disabled = true;
var tempOption = this._controls.editor.firstChild;
if (!tempOption) {
tempOption = document.createElement('option');
tempOption.value = '';
this._controls.editor.appendChild(tempOption);
tempOption.selected = true;
}
tempOption.update((text || '').stripScripts().stripTags());
},
checkForExternalText: function() {
this._text = this.getText();
if (this.options.loadTextURL)
this.loadExternalText();
else
this.buildOptionList();
},
loadExternalText: function() {
this.showLoadingText(this.options.loadingText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._text = transport.responseText.strip();
this.buildOptionList();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadTextURL, options);
},
buildOptionList: function() {
this._form.removeClassName(this.options.loadingClassName);
this._collection = this._collection.map(function(entry) {
return 2 === entry.length ? entry : [entry, entry].flatten();
});
var marker = ('value' in this.options) ? this.options.value : this._text;
var textFound = this._collection.any(function(entry) {
return entry[0] == marker;
}.bind(this));
this._controls.editor.update('');
var option;
this._collection.each(function(entry, index) {
option = document.createElement('option');
option.value = entry[0];
option.selected = textFound ? entry[0] == marker : 0 == index;
option.appendChild(document.createTextNode(entry[1]));
this._controls.editor.appendChild(option);
}.bind(this));
this._controls.editor.disabled = false;
Field.scrollFreeActivate(this._controls.editor);
}
});
//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
//**** This only exists for a while, in order to let ****
//**** users adapt to the new API. Read up on the new ****
//**** API and convert your code to it ASAP! ****
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
if (!options) return;
function fallback(name, expr) {
if (name in options || expr === undefined) return;
options[name] = expr;
};
fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
options.cancelLink == options.cancelButton == false ? false : undefined)));
fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
options.okLink == options.okButton == false ? false : undefined)));
fallback('highlightColor', options.highlightcolor);
fallback('highlightEndColor', options.highlightendcolor);
};
Object.extend(Ajax.InPlaceEditor, {
DefaultOptions: {
ajaxOptions: { },
autoRows: 3, // Use when multi-line w/ rows == 1
cancelControl: 'link', // 'link'|'button'|false
cancelText: 'cancel',
clickToEditText: 'Click to edit',
externalControl: null, // id|elt
externalControlOnly: false,
fieldPostCreation: 'activate', // 'activate'|'focus'|false
formClassName: 'inplaceeditor-form',
formId: null, // id|elt
highlightColor: '#ffff99',
highlightEndColor: '#ffffff',
hoverClassName: '',
htmlResponse: true,
loadingClassName: 'inplaceeditor-loading',
loadingText: 'Loading...',
okControl: 'button', // 'link'|'button'|false
okText: 'ok',
paramName: 'value',
rows: 1, // If 1 and multi-line, uses autoRows
savingClassName: 'inplaceeditor-saving',
savingText: 'Saving...',
size: 0,
stripLoadedTextTags: false,
submitOnBlur: false,
textAfterControls: '',
textBeforeControls: '',
textBetweenControls: ''
},
DefaultCallbacks: {
callback: function(form) {
return Form.serialize(form);
},
onComplete: function(transport, element) {
// For backward compatibility, this one is bound to the IPE, and passes
// the element directly. It was too often customized, so we don't break it.
new Effect.Highlight(element, {
startcolor: this.options.highlightColor, keepBackgroundImage: true });
},
onEnterEditMode: null,
onEnterHover: function(ipe) {
ipe.element.style.backgroundColor = ipe.options.highlightColor;
if (ipe._effect)
ipe._effect.cancel();
},
onFailure: function(transport, ipe) {
alert('Error communication with the server: ' + transport.responseText.stripTags());
},
onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
onLeaveEditMode: null,
onLeaveHover: function(ipe) {
ipe._effect = new Effect.Highlight(ipe.element, {
startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
restorecolor: ipe._originalBackground, keepBackgroundImage: true
});
}
},
Listeners: {
click: 'enterEditMode',
keydown: 'checkForEscapeOrReturn',
mouseover: 'enterHover',
mouseout: 'leaveHover'
}
});
Ajax.InPlaceCollectionEditor.DefaultOptions = {
loadingCollectionText: 'Loading options...'
};
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create({
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
});
================================================
FILE: example/rails2.3/public/javascripts/dragdrop.js
================================================
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if(Object.isUndefined(Effect))
throw("dragdrop.js requires including script.aculo.us' effects.js library");
var Droppables = {
drops: [],
remove: function(element) {
this.drops = this.drops.reject(function(d) { return d.element==$(element) });
},
add: function(element) {
element = $(element);
var options = Object.extend({
greedy: true,
hoverclass: null,
tree: false
}, arguments[1] || { });
// cache containers
if(options.containment) {
options._containers = [];
var containment = options.containment;
if(Object.isArray(containment)) {
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
}
}
if(options.accept) options.accept = [options.accept].flatten();
Element.makePositioned(element); // fix IE
options.element = element;
this.drops.push(options);
},
findDeepestChild: function(drops) {
deepest = drops[0];
for (i = 1; i < drops.length; ++i)
if (Element.isParent(drops[i].element, deepest.element))
deepest = drops[i];
return deepest;
},
isContained: function(element, drop) {
var containmentNode;
if(drop.tree) {
containmentNode = element.treeNode;
} else {
containmentNode = element.parentNode;
}
return drop._containers.detect(function(c) { return containmentNode == c });
},
isAffected: function(point, element, drop) {
return (
(drop.element!=element) &&
((!drop._containers) ||
this.isContained(element, drop)) &&
((!drop.accept) ||
(Element.classNames(element).detect(
function(v) { return drop.accept.include(v) } ) )) &&
Position.within(drop.element, point[0], point[1]) );
},
deactivate: function(drop) {
if(drop.hoverclass)
Element.removeClassName(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(drop.hoverclass)
Element.addClassName(drop.element, drop.hoverclass);
this.last_active = drop;
},
show: function(point, element) {
if(!this.drops.length) return;
var drop, affected = [];
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
if (drop) {
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
if (drop != this.last_active) Droppables.activate(drop);
}
},
fire: function(event, element) {
if(!this.last_active) return;
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
if (this.last_active.onDrop) {
this.last_active.onDrop(element, this.last_active.element, event);
return true;
}
},
reset: function() {
if(this.last_active)
this.deactivate(this.last_active);
}
};
var Draggables = {
drags: [],
observers: [],
register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},
unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},
activate: function(draggable) {
if(draggable.options.delay) {
this._timeout = setTimeout(function() {
Draggables._timeout = null;
window.focus();
Draggables.activeDraggable = draggable;
}.bind(this), draggable.options.delay);
} else {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
}
},
deactivate: function() {
this.activeDraggable = null;
},
updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
// Mozilla-based browsers fire successive mousemove events with
// the same coordinates, prevent needless redrawing (moz bug?)
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},
endDrag: function(event) {
if(this._timeout) {
clearTimeout(this._timeout);
this._timeout = null;
}
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},
addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},
removeObserver: function(element) { // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
if(o[eventName]) o[eventName](eventName, draggable, event);
});
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},
_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
function(o) { return o[eventName]; }
).length;
});
}
};
/*--------------------------------------------------------------------------*/
var Draggable = Class.create({
initialize: function(element) {
var defaults = {
handle: false,
reverteffect: function(element, top_offset, left_offset) {
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
queue: {scope:'_draggable', position:'end'}
});
},
endeffect: function(element) {
var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
Draggable._dragging[element] = false
}
});
},
zindex: 1000,
revert: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
delay: 0
};
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
Draggable._dragging[element] = true;
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
}
});
var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = $(options.scroll);
this._isScrollChild = Element.childOf(this.element, options.scroll);
}
Element.makePositioned(this.element); // fix IE
this.options = options;
this.dragging = false;
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Draggables.register(this);
},
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Draggables.unregister(this);
},
currentDelta: function() {
return([
parseInt(Element.getStyle(this.element,'left') || '0'),
parseInt(Element.getStyle(this.element,'top') || '0')]);
},
initDrag: function(event) {
if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
var src = Event.element(event);
if((tag_name = src.tagName.toUpperCase()) && (
tag_name=='INPUT' ||
tag_name=='SELECT' ||
tag_name=='OPTION' ||
tag_name=='BUTTON' ||
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var pos = Position.cumulativeOffset(this.element);
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
Event.stop(event);
}
},
startDrag: function(event) {
this.dragging = true;
if(!this.delta)
this.delta = this.currentDelta();
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
this.element.style.zIndex = this.options.zindex;
}
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
if (!this._originallyAbsolute)
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
if(this.options.scroll) {
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
this.originalScrollLeft = where.left;
this.originalScrollTop = where.top;
} else {
this.originalScrollLeft = this.options.scroll.scrollLeft;
this.originalScrollTop = this.options.scroll.scrollTop;
}
}
Draggables.notify('onStart', this, event);
if(this.options.starteffect) this.options.starteffect(this.element);
},
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
if(!this.options.quiet){
Position.prepare();
Droppables.show(pointer, this.element);
}
Draggables.notify('onDrag', this, event);
this.draw(pointer);
if(this.options.change) this.options.change(this);
if(this.options.scroll) {
this.stopScrolling();
var p;
if (this.options.scroll == window) {
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
} else {
p = Position.page(this.options.scroll);
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
p[1] += this.options.scroll.scrollTop + Position.deltaY;
p.push(p[0]+this.options.scroll.offsetWidth);
p.push(p[1]+this.options.scroll.offsetHeight);
}
var speed = [0,0];
if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
this.startScrolling(speed);
}
// fix AppleWebKit rendering
if(Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
},
finishDrag: function(event, success) {
this.dragging = false;
if(this.options.quiet){
Position.prepare();
var pointer = [Event.pointerX(event), Event.pointerY(event)];
Droppables.show(pointer, this.element);
}
if(this.options.ghosting) {
if (!this._originallyAbsolute)
Position.relativize(this.element);
delete this._originallyAbsolute;
Element.remove(this._clone);
this._clone = null;
}
var dropped = false;
if(success) {
dropped = Droppables.fire(event, this.element);
if (!dropped) dropped = false;
}
if(dropped && this.options.onDropped) this.options.onDropped(this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
if(revert && Object.isFunction(revert)) revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
if (dropped == 0 || revert != 'failure')
this.options.reverteffect(this.element,
d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
Draggables.deactivate(this);
Droppables.reset();
},
keyPress: function(event) {
if(event.keyCode!=Event.KEY_ESC) return;
this.finishDrag(event, false);
Event.stop(event);
},
endDrag: function(event) {
if(!this.dragging) return;
this.stopScrolling();
this.finishDrag(event, true);
Event.stop(event);
},
draw: function(point) {
var pos = Position.cumulativeOffset(this.element);
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}
var d = this.currentDelta();
pos[0] -= d[0]; pos[1] -= d[1];
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}
var p = [0,1].map(function(i){
return (point[i]-pos[i]-this.offset[i])
}.bind(this));
if(this.options.snap) {
if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
} else {
p = p.map( function(v) {
return (v/this.options.snap).round()*this.options.snap }.bind(this));
}
}}
var style = this.element.style;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px";
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
stopScrolling: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
this.scrollInterval = null;
Draggables._lastScrollPointer = null;
}
},
startScrolling: function(speed) {
if(!(speed[0] || speed[1])) return;
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},
scroll: function() {
var current = new Date();
var delta = current - this.lastScrolled;
this.lastScrolled = current;
if(this.options.scroll == window) {
with (this._getWindowScroll(this.options.scroll)) {
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
var d = delta / 1000;
this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
}
}
} else {
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
Position.prepare();
Droppables.show(Draggables._lastPointer, this.element);
Draggables.notify('onDrag', this);
if (this._isScrollChild) {
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
if (Draggables._lastScrollPointer[0] < 0)
Draggables._lastScrollPointer[0] = 0;
if (Draggables._lastScrollPointer[1] < 0)
Draggables._lastScrollPointer[1] = 0;
this.draw(Draggables._lastScrollPointer);
}
if(this.options.change) this.options.change(this);
},
_getWindowScroll: function(w) {
var T, L, W, H;
with (w.document) {
if (w.document.documentElement && documentElement.scrollTop) {
T = documentElement.scrollTop;
L = documentElement.scrollLeft;
} else if (w.document.body) {
T = body.scrollTop;
L = body.scrollLeft;
}
if (w.innerWidth) {
W = w.innerWidth;
H = w.innerHeight;
} else if (w.document.documentElement && documentElement.clientWidth) {
W = documentElement.clientWidth;
H = documentElement.clientHeight;
} else {
W = body.offsetWidth;
H = body.offsetHeight;
}
}
return { top: T, left: L, width: W, height: H };
}
});
Draggable._dragging = { };
/*--------------------------------------------------------------------------*/
var SortableObserver = Class.create({
initialize: function(element, observer) {
this.element = $(element);
this.observer = observer;
this.lastValue = Sortable.serialize(this.element);
},
onStart: function() {
this.lastValue = Sortable.serialize(this.element);
},
onEnd: function() {
Sortable.unmark();
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
});
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
sortables: { },
_findRootElement: function(element) {
while (element.tagName.toUpperCase() != "BODY") {
if(element.id && Sortable.sortables[element.id]) return element;
element = element.parentNode;
}
},
options: function(element) {
element = Sortable._findRootElement($(element));
if(!element) return;
return Sortable.sortables[element.id];
},
destroy: function(element){
element = $(element);
var s = Sortable.sortables[element.id];
if(s) {
Draggables.removeObserver(s.element);
s.droppables.each(function(d){ Droppables.remove(d) });
s.draggables.invoke('destroy');
delete Sortable.sortables[s.element.id];
}
},
create: function(element) {
element = $(element);
var options = Object.extend({
element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
dropOnEmpty: false,
tree: false,
treeTag: 'ul',
overlap: 'vertical', // one of 'vertical', 'horizontal'
constraint: 'vertical', // one of 'vertical', 'horizontal', false
containment: element, // also takes array of elements (or id's); or false
handle: false, // or a CSS class
only: false,
delay: 0,
hoverclass: null,
ghosting: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
// these take arrays of elements or ids and can be
// used for better initialization performance
elements: false,
handles: false,
onChange: Prototype.emptyFunction,
onUpdate: Prototype.emptyFunction
}, arguments[1] || { });
// clear any old sortable with same element
this.destroy(element);
// build options for the draggables
var options_for_draggable = {
revert: true,
quiet: options.quiet,
scroll: options.scroll,
scrollSpeed: options.scrollSpeed,
scrollSensitivity: options.scrollSensitivity,
delay: options.delay,
ghosting: options.ghosting,
constraint: options.constraint,
handle: options.handle };
if(options.starteffect)
options_for_draggable.starteffect = options.starteffect;
if(options.reverteffect)
options_for_draggable.reverteffect = options.reverteffect;
else
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
element.style.top = 0;
element.style.left = 0;
};
if(options.endeffect)
options_for_draggable.endeffect = options.endeffect;
if(options.zindex)
options_for_draggable.zindex = options.zindex;
// build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
tree: options.tree,
hoverclass: options.hoverclass,
onHover: Sortable.onHover
};
var options_for_tree = {
onHover: Sortable.onEmptyHover,
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass
};
// fix for gecko engine
Element.cleanWhitespace(element);
options.draggables = [];
options.droppables = [];
// drop on empty handling
if(options.dropOnEmpty || options.tree) {
Droppables.add(element, options_for_tree);
options.droppables.push(element);
}
(options.elements || this.findElements(element, options) || []).each( function(e,i) {
var handle = options.handles ? $(options.handles[i]) :
(options.handle ? $(e).select('.' + options.handle)[0] : e);
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
if(options.tree) e.treeNode = element;
options.droppables.push(e);
});
if(options.tree) {
(Sortable.findTreeElements(element, options) || []).each( function(e) {
Droppables.add(e, options_for_tree);
e.treeNode = element;
options.droppables.push(e);
});
}
// keep reference
this.sortables[element.id] = options;
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
},
// return all suitable-for-sortable elements in a guaranteed order
findElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.tag);
},
findTreeElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.treeTag);
},
onHover: function(element, dropon, overlap) {
if(Element.isParent(dropon, element)) return;
if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
return;
} else if(overlap>0.5) {
Sortable.mark(dropon, 'before');
if(dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
} else {
Sortable.mark(dropon, 'after');
var nextElement = dropon.nextSibling || null;
if(nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
}
},
onEmptyHover: function(element, dropon, overlap) {
var oldParentNode = element.parentNode;
var droponOptions = Sortable.options(dropon);
if(!Element.isParent(dropon, element)) {
var index;
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
var child = null;
if(children) {
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
for (index = 0; index < children.length; index += 1) {
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
offset -= Element.offsetSize (children[index], droponOptions.overlap);
} else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
child = index + 1 < children.length ? children[index + 1] : null;
break;
} else {
child = children[index];
break;
}
}
}
dropon.insertBefore(element, child);
Sortable.options(oldParentNode).onChange(element);
droponOptions.onChange(element);
}
},
unmark: function() {
if(Sortable._marker) Sortable._marker.hide();
},
mark: function(dropon, position) {
// mark on ghosting only
var sortable = Sortable.options(dropon.parentNode);
if(sortable && !sortable.ghosting) return;
if(!Sortable._marker) {
Sortable._marker =
($('dropmarker') || Element.extend(document.createElement('DIV'))).
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
var offsets = Position.cumulativeOffset(dropon);
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after')
if(sortable.overlap == 'horizontal')
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
else
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
Sortable._marker.show();
},
_tree: function(element, options, parent) {
var children = Sortable.findElements(element, options) || [];
for (var i = 0; i < children.length; ++i) {
var match = children[i].id.match(options.format);
if (!match) continue;
var child = {
id: encodeURIComponent(match ? match[1] : null),
element: element,
parent: parent,
children: [],
position: parent.children.length,
container: $(children[i]).down(options.treeTag)
};
/* Get the element containing the children and recurse over it */
if (child.container)
this._tree(child.container, options, child);
parent.children.push (child);
}
return parent;
},
tree: function(element) {
element = $(element);
var sortableOptions = this.options(element);
var options = Object.extend({
tag: sortableOptions.tag,
treeTag: sortableOptions.treeTag,
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
}, arguments[1] || { });
var root = {
id: null,
parent: null,
children: [],
container: element,
position: 0
};
return Sortable._tree(element, options, root);
},
/* Construct a [i] index for a particular node */
_constructIndex: function(node) {
var index = '';
do {
if (node.id) index = '[' + node.position + ']' + index;
} while ((node = node.parent) != null);
return index;
},
sequence: function(element) {
element = $(element);
var options = Object.extend(this.options(element), arguments[1] || { });
return $(this.findElements(element, options) || []).map( function(item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
});
},
setSequence: function(element, new_sequence) {
element = $(element);
var options = Object.extend(this.options(element), arguments[2] || { });
var nodeMap = { };
this.findElements(element, options).each( function(n) {
if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
n.parentNode.removeChild(n);
});
new_sequence.each(function(ident) {
var n = nodeMap[ident];
if (n) {
n[1].appendChild(n[0]);
delete nodeMap[ident];
}
});
},
serialize: function(element) {
element = $(element);
var options = Object.extend(Sortable.options(element), arguments[1] || { });
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
if (options.tree) {
return Sortable.tree(element, arguments[1]).children.map( function (item) {
return [name + Sortable._constructIndex(item) + "[id]=" +
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}).flatten().join('&');
} else {
return Sortable.sequence(element, arguments[1]).map( function(item) {
return name + "[]=" + encodeURIComponent(item);
}).join('&');
}
}
};
// Returns true if child is contained within element
Element.isParent = function(child, element) {
if (!child.parentNode || child == element) return false;
if (child.parentNode == element) return true;
return Element.isParent(child.parentNode, element);
};
Element.findChildren = function(element, only, recursive, tagName) {
if(!element.hasChildNodes()) return null;
tagName = tagName.toUpperCase();
if(only) only = [only].flatten();
var elements = [];
$A(element.childNodes).each( function(e) {
if(e.tagName && e.tagName.toUpperCase()==tagName &&
(!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
elements.push(e);
if(recursive) {
var grandchildren = Element.findChildren(e, only, recursive, tagName);
if(grandchildren) elements.push(grandchildren);
}
});
return (elements.length>0 ? elements.flatten() : []);
};
Element.offsetSize = function (element, type) {
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
};
================================================
FILE: example/rails2.3/public/javascripts/effects.js
================================================
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
// Martin Bialasinki
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// converts rgb() and #xxx to #xxxxxx format,
// returns self (or first argument) if not convertable
String.prototype.parseColor = function() {
var color = '#';
if (this.slice(0,4) == 'rgb(') {
var cols = this.slice(4,this.length-1).split(',');
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
} else {
if (this.slice(0,1) == '#') {
if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
if (this.length==7) color = this.toLowerCase();
}
}
return (color.length==7 ? color : (arguments[0] || this));
};
/*--------------------------------------------------------------------------*/
Element.collectTextNodes = function(element) {
return $A($(element).childNodes).collect( function(node) {
return (node.nodeType==3 ? node.nodeValue :
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
};
Element.collectTextNodesIgnoreClass = function(element, className) {
return $A($(element).childNodes).collect( function(node) {
return (node.nodeType==3 ? node.nodeValue :
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
Element.collectTextNodesIgnoreClass(node, className) : ''));
}).flatten().join('');
};
Element.setContentZoom = function(element, percent) {
element = $(element);
element.setStyle({fontSize: (percent/100) + 'em'});
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
return element;
};
Element.getInlineOpacity = function(element){
return $(element).style.opacity || '';
};
Element.forceRerendering = function(element) {
try {
element = $(element);
var n = document.createTextNode(' ');
element.appendChild(n);
element.removeChild(n);
} catch(e) { }
};
/*--------------------------------------------------------------------------*/
var Effect = {
_elementDoesNotExistError: {
name: 'ElementDoesNotExistError',
message: 'The specified DOM element does not exist, but is required for this effect to operate'
},
Transitions: {
linear: Prototype.K,
sinoidal: function(pos) {
return (-Math.cos(pos*Math.PI)/2) + .5;
},
reverse: function(pos) {
return 1-pos;
},
flicker: function(pos) {
var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
return pos > 1 ? 1 : pos;
},
wobble: function(pos) {
return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
},
pulse: function(pos, pulses) {
return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
},
spring: function(pos) {
return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
},
none: function(pos) {
return 0;
},
full: function(pos) {
return 1;
}
},
DefaultOptions: {
duration: 1.0, // seconds
fps: 100, // 100= assume 66fps max.
sync: false, // true for combining
from: 0.0,
to: 1.0,
delay: 0.0,
queue: 'parallel'
},
tagifyText: function(element) {
var tagifyStyle = 'position:relative';
if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
element = $(element);
$A(element.childNodes).each( function(child) {
if (child.nodeType==3) {
child.nodeValue.toArray().each( function(character) {
element.insertBefore(
new Element('span', {style: tagifyStyle}).update(
character == ' ' ? String.fromCharCode(160) : character),
child);
});
Element.remove(child);
}
});
},
multiple: function(element, effect) {
var elements;
if (((typeof element == 'object') ||
Object.isFunction(element)) &&
(element.length))
elements = element;
else
elements = $(element).childNodes;
var options = Object.extend({
speed: 0.1,
delay: 0.0
}, arguments[2] || { });
var masterDelay = options.delay;
$A(elements).each( function(element, index) {
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
});
},
PAIRS: {
'slide': ['SlideDown','SlideUp'],
'blind': ['BlindDown','BlindUp'],
'appear': ['Appear','Fade']
},
toggle: function(element, effect) {
element = $(element);
effect = (effect || 'appear').toLowerCase();
var options = Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
}, arguments[2] || { });
Effect[element.visible() ?
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}
};
Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
/* ------------- core effects ------------- */
Effect.ScopedQueue = Class.create(Enumerable, {
initialize: function() {
this.effects = [];
this.interval = null;
},
_each: function(iterator) {
this.effects._each(iterator);
},
add: function(effect) {
var timestamp = new Date().getTime();
var position = Object.isString(effect.options.queue) ?
effect.options.queue : effect.options.queue.position;
switch(position) {
case 'front':
// move unstarted effects after this effect
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
e.startOn += effect.finishOn;
e.finishOn += effect.finishOn;
});
break;
case 'with-last':
timestamp = this.effects.pluck('startOn').max() || timestamp;
break;
case 'end':
// start effect after last queued effect has finished
timestamp = this.effects.pluck('finishOn').max() || timestamp;
break;
}
effect.startOn += timestamp;
effect.finishOn += timestamp;
if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
this.effects.push(effect);
if (!this.interval)
this.interval = setInterval(this.loop.bind(this), 15);
},
remove: function(effect) {
this.effects = this.effects.reject(function(e) { return e==effect });
if (this.effects.length == 0) {
clearInterval(this.interval);
this.interval = null;
}
},
loop: function() {
var timePos = new Date().getTime();
for(var i=0, len=this.effects.length;i<len;i++)
this.effects[i] && this.effects[i].loop(timePos);
}
});
Effect.Queues = {
instances: $H(),
get: function(queueName) {
if (!Object.isString(queueName)) return queueName;
return this.instances.get(queueName) ||
this.instances.set(queueName, new Effect.ScopedQueue());
}
};
Effect.Queue = Effect.Queues.get('global');
Effect.Base = Class.create({
position: null,
start: function(options) {
function codeForEvent(options,eventName){
return (
(options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
(options[eventName] ? 'this.options.'+eventName+'(this);' : '')
);
}
if (options && options.transition === false) options.transition = Effect.Transitions.linear;
this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
this.currentFrame = 0;
this.state = 'idle';
this.startOn = this.options.delay*1000;
this.finishOn = this.startOn+(this.options.duration*1000);
this.fromToDelta = this.options.to-this.options.from;
this.totalTime = this.finishOn-this.startOn;
this.totalFrames = this.options.fps*this.options.duration;
this.render = (function() {
function dispatch(effect, eventName) {
if (effect.options[eventName + 'Internal'])
effect.options[eventName + 'Internal'](effect);
if (effect.options[eventName])
effect.options[eventName](effect);
}
return function(pos) {
if (this.state === "idle") {
this.state = "running";
dispatch(this, 'beforeSetup');
if (this.setup) this.setup();
dispatch(this, 'afterSetup');
}
if (this.state === "running") {
pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
this.position = pos;
dispatch(this, 'beforeUpdate');
if (this.update) this.update(pos);
dispatch(this, 'afterUpdate');
}
};
})();
this.event('beforeStart');
if (!this.options.sync)
Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).add(this);
},
loop: function(timePos) {
if (timePos >= this.startOn) {
if (timePos >= this.finishOn) {
this.render(1.0);
this.cancel();
this.event('beforeFinish');
if (this.finish) this.finish();
this.event('afterFinish');
return;
}
var pos = (timePos - this.startOn) / this.totalTime,
frame = (pos * this.totalFrames).round();
if (frame > this.currentFrame) {
this.render(pos);
this.currentFrame = frame;
}
}
},
cancel: function() {
if (!this.options.sync)
Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).remove(this);
this.state = 'finished';
},
event: function(eventName) {
if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
if (this.options[eventName]) this.options[eventName](this);
},
inspect: function() {
var data = $H();
for(property in this)
if (!Object.isFunction(this[property])) data.set(property, this[property]);
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
}
});
Effect.Parallel = Class.create(Effect.Base, {
initialize: function(effects) {
this.effects = effects || [];
this.start(arguments[1]);
},
update: function(position) {
this.effects.invoke('render', position);
},
finish: function(position) {
this.effects.each( function(effect) {
effect.render(1.0);
effect.cancel();
effect.event('beforeFinish');
if (effect.finish) effect.finish(position);
effect.event('afterFinish');
});
}
});
Effect.Tween = Class.create(Effect.Base, {
initialize: function(object, from, to) {
object = Object.isString(object) ? $(object) : object;
var args = $A(arguments), method = args.last(),
options = args.length == 5 ? args[3] : null;
this.method = Object.isFunction(method) ? method.bind(object) :
Object.isFunction(object[method]) ? object[method].bind(object) :
function(value) { object[method] = value };
this.start(Object.extend({ from: from, to: to }, options || { }));
},
update: function(position) {
this.method(position);
}
});
Effect.Event = Class.create(Effect.Base, {
initialize: function() {
this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
},
update: Prototype.emptyFunction
});
Effect.Opacity = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
// make this work on IE on elements without 'layout'
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
var options = Object.extend({
from: this.element.getOpacity() || 0.0,
to: 1.0
}, arguments[1] || { });
this.start(options);
},
update: function(position) {
this.element.setOpacity(position);
}
});
Effect.Move = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
x: 0,
y: 0,
mode: 'relative'
}, arguments[1] || { });
this.start(options);
},
setup: function() {
this.element.makePositioned();
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
if (this.options.mode == 'absolute') {
this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
},
update: function(position) {
this.element.setStyle({
left: (this.options.x * position + this.originalLeft).round() + 'px',
top: (this.options.y * position + this.originalTop).round() + 'px'
});
}
});
// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
return new Effect.Move(element,
Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};
Effect.Scale = Class.create(Effect.Base, {
initialize: function(element, percent) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
scaleMode: 'box', // 'box' or 'contents' or { } with provided values
scaleFrom: 100.0,
scaleTo: percent
}, arguments[2] || { });
this.start(options);
},
setup: function() {
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = this.element.getStyle('position');
this.originalStyle = { };
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k] = this.element.style[k];
}.bind(this));
this.originalTop = this.element.offsetTop;
this.originalLeft = this.element.offsetLeft;
var fontSize = this.element.getStyle('font-size') || '100%';
['em','px','%','pt'].each( function(fontSizeType) {
if (fontSize.indexOf(fontSizeType)>0) {
this.fontSize = parseFloat(fontSize);
this.fontSizeType = fontSizeType;
}
}.bind(this));
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
this.dims = null;
if (this.options.scaleMode=='box')
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
if (/^content/.test(this.options.scaleMode))
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
if (!this.dims)
this.dims = [this.options.scaleMode.originalHeight,
this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
if (this.options.scaleContent && this.fontSize)
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
},
setDimensions: function(height, width) {
var d = { };
if (this.options.scaleX) d.width = width.round() + 'px';
if (this.options.scaleY) d.height = height.round() + 'px';
if (this.options.scaleFromCenter) {
var topd = (height - this.dims[0])/2;
var leftd = (width - this.dims[1])/2;
if (this.elementPositioning == 'absolute') {
if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
} else {
if (this.options.scaleY) d.top = -topd + 'px';
if (this.options.scaleX) d.left = -leftd + 'px';
}
}
this.element.setStyle(d);
}
});
Effect.Highlight = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
this.start(options);
},
setup: function() {
// Prevent executing on elements not in the layout flow
if (this.element.getStyle('display')=='none') { this.cancel(); return; }
// Disable background image during the effect
this.oldStyle = { };
if (!this.options.keepBackgroundImage) {
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
this.element.setStyle({backgroundImage: 'none'});
}
if (!this.options.endcolor)
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
if (!this.options.restorecolor)
this.options.restorecolor = this.element.getStyle('background-color');
// init color calculations
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
},
update: function(position) {
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
},
finish: function() {
this.element.setStyle(Object.extend(this.oldStyle, {
backgroundColor: this.options.restorecolor
}));
}
});
Effect.ScrollTo = function(element) {
var options = arguments[1] || { },
scrollOffsets = document.viewport.getScrollOffsets(),
elementOffsets = $(element).cumulativeOffset();
if (options.offset) elementOffsets[1] += options.offset;
return new Effect.Tween(null,
scrollOffsets.top,
elementOffsets[1],
options,
function(p){ scrollTo(scrollOffsets.left, p.round()); }
);
};
/* ------------- combination effects ------------- */
Effect.Fade = function(element) {
element = $(element);
var oldOpacity = element.getInlineOpacity();
var options = Object.extend({
from: element.getOpacity() || 1.0,
to: 0.0,
afterFinishInternal: function(effect) {
if (effect.options.to!=0) return;
effect.element.hide().setStyle({opacity: oldOpacity});
}
}, arguments[1] || { });
return new Effect.Opacity(element,options);
};
Effect.Appear = function(element) {
element = $(element);
var options = Object.extend({
from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
to: 1.0,
// force Safari to render floated elements properly
afterFinishInternal: function(effect) {
effect.element.forceRerendering();
},
beforeSetup: function(effect) {
effect.element.setOpacity(effect.options.from).show();
}}, arguments[1] || { });
return new Effect.Opacity(element,options);
};
Effect.Puff = function(element) {
element = $(element);
var oldStyle = {
opacity: element.getInlineOpacity(),
position: element.getStyle('position'),
top: element.style.top,
left: element.style.left,
width: element.style.width,
height: element.style.height
};
return new Effect.Parallel(
[ new Effect.Scale(element, 200,
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
Object.extend({ duration: 1.0,
beforeSetupInternal: function(effect) {
Position.absolutize(effect.effects[0].element);
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().setStyle(oldStyle); }
}, arguments[1] || { })
);
};
Effect.BlindUp = function(element) {
element = $(element);
element.makeClipping();
return new Effect.Scale(element, 0,
Object.extend({ scaleContent: false,
scaleX: false,
restoreAfterFinish: true,
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping();
}
}, arguments[1] || { })
);
};
Effect.BlindDown = function(element) {
element = $(element);
var elementDimensions = element.getDimensions();
return new Effect.Scale(element, 100, Object.extend({
scaleContent: false,
scaleX: false,
scaleFrom: 0,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) {
effect.element.makeClipping().setStyle({height: '0px'}).show();
},
afterFinishInternal: function(effect) {
effect.element.undoClipping();
}
}, arguments[1] || { }));
};
Effect.SwitchOff = function(element) {
element = $(element);
var oldOpacity = element.getInlineOpacity();
return new Effect.Appear(element, Object.extend({
duration: 0.4,
from: 0,
transition: Effect.Transitions.flicker,
afterFinishInternal: function(effect) {
new Effect.Scale(effect.element, 1, {
duration: 0.3, scaleFromCenter: true,
scaleX: false, scaleContent: false, restoreAfterFinish: true,
beforeSetup: function(effect) {
effect.element.makePositioned().makeClipping();
},
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
}
});
}
}, arguments[1] || { }));
};
Effect.DropOut = function(element) {
element = $(element);
var oldStyle = {
top: element.getStyle('top'),
left: element.getStyle('left'),
opacity: element.getInlineOpacity() };
return new Effect.Parallel(
[ new Effect.Move(element, {x: 0, y: 100, sync: true }),
new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
Object.extend(
{ duration: 0.5,
beforeSetup: function(effect) {
effect.effects[0].element.makePositioned();
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
}
}, arguments[1] || { }));
};
Effect.Shake = function(element) {
element = $(element);
var options = Object.extend({
distance: 20,
duration: 0.5
}, arguments[1] || {});
var distance = parseFloat(options.distance);
var split = parseFloat(options.duration) / 10.0;
var oldStyle = {
top: element.getStyle('top'),
left: element.getStyle('left') };
return new Effect.Move(element,
{ x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
{ x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
effect.element.undoPositioned().setStyle(oldStyle);
}}); }}); }}); }}); }}); }});
};
Effect.SlideDown = function(element) {
element = $(element).cleanWhitespace();
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
var oldInnerBottom = element.down().getStyle('bottom');
var elementDimensions = element.getDimensions();
return new Effect.Scale(element, 100, Object.extend({
scaleContent: false,
scaleX: false,
scaleFrom: window.opera ? 0 : 1,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) {
effect.element.makePositioned();
effect.element.down().makePositioned();
if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().setStyle({height: '0px'}).show();
},
afterUpdateInternal: function(effect) {
effect.element.down().setStyle({bottom:
(effect.dims[0] - effect.element.clientHeight) + 'px' });
},
afterFinishInternal: function(effect) {
effect.element.undoClipping().undoPositioned();
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
}, arguments[1] || { })
);
};
Effect.SlideUp = function(element) {
element = $(element).cleanWhitespace();
var oldInnerBottom = element.down().getStyle('bottom');
var elementDimensions = element.getDimensions();
return new Effect.Scale(element, window.opera ? 0 : 1,
Object.extend({ scaleContent: false,
scaleX: false,
scaleMode: 'box',
scaleFrom: 100,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) {
effect.element.makePositioned();
effect.element.down().makePositioned();
if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().show();
},
afterUpdateInternal: function(effect) {
effect.element.down().setStyle({bottom:
(effect.dims[0] - effect.element.clientHeight) + 'px' });
},
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().undoPositioned();
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
}
}, arguments[1] || { })
);
};
// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
return new Effect.Scale(element, window.opera ? 1 : 0, {
restoreAfterFinish: true,
beforeSetup: function(effect) {
effect.element.makeClipping();
},
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping();
}
});
};
Effect.Grow = function(element) {
element = $(element);
var options = Object.extend({
direction: 'center',
moveTransition: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.full
}, arguments[1] || { });
var oldStyle = {
top: element.style.top,
left: element.style.left,
height: element.style.height,
width: element.style.width,
opacity: element.getInlineOpacity() };
var dims = element.getDimensions();
var initialMoveX, initialMoveY;
var moveX, moveY;
switch (options.direction) {
case 'top-left':
initialMoveX = initialMoveY = moveX = moveY = 0;
break;
case 'top-right':
initialMoveX = dims.width;
initialMoveY = moveY = 0;
moveX = -dims.width;
break;
case 'bottom-left':
initialMoveX = moveX = 0;
initialMoveY = dims.height;
moveY = -dims.height;
break;
case 'bottom-right':
initialMoveX = dims.width;
initialMoveY = dims.height;
moveX = -dims.width;
moveY = -dims.height;
break;
case 'center':
initialMoveX = dims.width / 2;
initialMoveY = dims.height / 2;
moveX = -dims.width / 2;
moveY = -dims.height / 2;
break;
}
return new Effect.Move(element, {
x: initialMoveX,
y: initialMoveY,
duration: 0.01,
beforeSetup: function(effect) {
effect.element.hide().makeClipping().makePositioned();
},
afterFinishInternal: function(effect) {
new Effect.Parallel(
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
new Effect.Scale(effect.element, 100, {
scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
], Object.extend({
beforeSetup: function(effect) {
effect.effects[0].element.setStyle({height: '0px'}).show();
},
afterFinishInternal: function(effect) {
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
}
}, options)
);
}
});
};
Effect.Shrink = function(element) {
element = $(element);
var options = Object.extend({
direction: 'center',
moveTransition: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.none
}, arguments[1] || { });
var oldStyle = {
top: element.style.top,
left: element.style.left,
height: element.style.height,
width: element.style.width,
opacity: element.getInlineOpacity() };
var dims = element.getDimensions();
var moveX, moveY;
switch (options.direction) {
case 'top-left':
moveX = moveY = 0;
break;
case 'top-right':
moveX = dims.width;
moveY = 0;
break;
case 'bottom-left':
moveX = 0;
moveY = dims.height;
break;
case 'bottom-right':
moveX = dims.width;
moveY = dims.height;
break;
case 'center':
moveX = dims.width / 2;
moveY = dims.height / 2;
break;
}
return new Effect.Parallel(
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
], Object.extend({
beforeStartInternal: function(effect) {
effect.effects[0].element.makePositioned().makeClipping();
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
}, options)
);
};
Effect.Pulsate = function(element) {
element = $(element);
var options = arguments[1] || { },
oldOpacity = element.getInlineOpacity(),
transition = options.transition || Effect.Transitions.linear,
reverser = function(pos){
return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
};
return new Effect.Opacity(element,
Object.extend(Object.extend({ duration: 2.0, from: 0,
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
}, options), {transition: reverser}));
};
Effect.Fold = function(element) {
element = $(element);
var oldStyle = {
top: element.style.top,
left: element.style.left,
width: element.style.width,
height: element.style.height };
element.makeClipping();
return new Effect.Scale(element, 5, Object.extend({
scaleContent: false,
scaleX: false,
afterFinishInternal: function(effect) {
new Effect.Scale(element, 1, {
scaleContent: false,
scaleY: false,
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().setStyle(oldStyle);
} });
}}, arguments[1] || { }));
};
Effect.Morph = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
style: { }
}, arguments[1] || { });
if (!Object.isString(options.style)) this.style = $H(options.style);
else {
if (options.style.include(':'))
this.style = options.style.parseStyle();
else {
this.element.addClassName(options.style);
this.style = $H(this.element.getStyles());
this.element.removeClassName(options.style);
var css = this.element.getStyles();
this.style = this.style.reject(function(style) {
return style.value == css[style.key];
});
options.afterFinishInternal = function(effect) {
effect.element.addClassName(effect.options.style);
effect.transforms.each(function(transform) {
effect.element.style[transform.style] = '';
});
};
}
}
this.start(options);
},
setup: function(){
function parseColor(color){
if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
color = color.parseColor();
return $R(0,2).map(function(i){
return parseInt( color.slice(i*2+1,i*2+3), 16 );
});
}
this.transforms = this.style.map(function(pair){
var property = pair[0], value = pair[1], unit = null;
if (value.parseColor('#zzzzzz') != '#zzzzzz') {
value = value.parseColor();
unit = 'color';
} else if (property == 'opacity') {
value = parseFloat(value);
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
} else if (Element.CSS_LENGTH.test(value)) {
var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
value = parseFloat(components[1]);
unit = (components.length == 3) ? components[2] : null;
}
var originalValue = this.element.getStyle(property);
return {
style: property.camelize(),
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
targetValue: unit=='color' ? parseColor(value) : value,
unit: unit
};
}.bind(this)).reject(function(transform){
return (
(transform.originalValue == transform.targetValue) ||
(
transform.unit != 'color' &&
(isNaN(transform.originalValue) || isNaN(transform.targetValue))
)
);
});
},
update: function(position) {
var style = { }, transform, i = this.transforms.length;
while(i--)
style[(transform = this.transforms[i]).style] =
transform.unit=='color' ? '#'+
(Math.round(transform.originalValue[0]+
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
(Math.round(transform.originalValue[1]+
(transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
(Math.round(transform.originalValue[2]+
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
(transform.originalValue +
(transform.targetValue - transform.originalValue) * position).toFixed(3) +
(transform.unit === null ? '' : transform.unit);
this.element.setStyle(style, true);
}
});
Effect.Transform = Class.create({
initialize: function(tracks){
this.tracks = [];
this.options = arguments[1] || { };
this.addTracks(tracks);
},
addTracks: function(tracks){
tracks.each(function(track){
track = $H(track);
var data = track.values().first();
this.tracks.push($H({
ids: track.keys().first(),
effect: Effect.Morph,
options: { style: data }
}));
}.bind(this));
return this;
},
play: function(){
return new Effect.Parallel(
this.tracks.map(function(track){
var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
var elements = [$(ids) || $$(ids)].flatten();
return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
}).flatten(),
this.options
);
}
});
Element.CSS_PROPERTIES = $w(
'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
'fontSize fontWeight height left letterSpacing lineHeight ' +
'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
'right textIndent top width wordSpacing zIndex');
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
var style, styleRules = $H();
if (Prototype.Browser.WebKit)
style = new Element('div',{style:this}).style;
else {
String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
style = String.__parseStyleElement.childNodes[0].style;
}
Element.CSS_PROPERTIES.each(function(property){
if (style[property]) styleRules.set(property, style[property]);
});
if (Prototype.Browser.IE && this.include('opacity'))
styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
return styleRules;
};
if (document.defaultView && document.defaultView.getComputedStyle) {
Element.getStyles = function(element) {
var css = document.defaultView.getComputedStyle($(element), null);
return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
styles[property] = css[property];
return styles;
});
};
} else {
Element.getStyles = function(element) {
element = $(element);
var css = element.currentStyle, styles;
styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
results[property] = css[property];
return results;
});
if (!styles.opacity) styles.opacity = element.getOpacity();
return styles;
};
}
Effect.Methods = {
morph: function(element, style) {
element = $(element);
new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
return element;
},
visualEffect: function(element, effect, options) {
element = $(element);
var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
new Effect[klass](element, options);
return element;
},
highlight: function(element, options) {
element = $(element);
new Effect.Highlight(element, options);
return element;
}
};
$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
'pulsate shake puff squish switchOff dropOut').each(
function(effect) {
Effect.Methods[effect] = function(element, options){
element = $(element);
Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
return element;
};
}
);
$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
function(f) { Effect.Methods[f] = Element[f]; }
);
Element.addMethods(Effect.Methods);
================================================
FILE: example/rails2.3/public/javascripts/prototype.js
================================================
/* Prototype JavaScript framework, version 1.6.0.3
* (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*
*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.6.0.3',
Browser: {
IE: !!(window.attachEvent &&
navigator.userAgent.indexOf('Opera') === -1),
Opera: navigator.userAgent.indexOf('Opera') > -1,
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
navigator.userAgent.indexOf('KHTML') === -1,
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
},
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: !!window.HTMLElement,
SpecificElementExtensions:
document.createElement('div')['__proto__'] &&
document.createElement('div')['__proto__'] !==
document.createElement('form')['__proto__']
},
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;
/* Based on Alex Arnell's inheritance implementation. */
var Class = {
create: function() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))
parent = properties.shift();
function klass() {
this.initialize.apply(this, arguments);
}
Object.extend(klass, Class.Methods);
klass.superclass = parent;
klass.subclasses = [];
if (parent) {
var subclass = function() { };
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}
for (var i = 0; i < properties.length; i++)
klass.addMethods(properties[i]);
if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction;
klass.prototype.constructor = klass;
return klass;
}
};
Class.Methods = {
addMethods: function(source) {
var ancestor = this.superclass && this.superclass.prototype;
var properties = Object.keys(source);
if (!Object.keys({ toString: true }).length)
properties.push("toString", "valueOf");
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i], value = source[property];
if (ancestor && Object.isFunction(value) &&
value.argumentNames().first() == "$super") {
var method = value;
value = (function(m) {
return function() { return ancestor[m].apply(this, arguments) };
})(property).wrap(method);
value.valueOf = method.valueOf.bind(method);
value.toString = method.toString.bind(method);
}
this.prototype[property] = value;
}
return this;
}
};
var Abstract = { };
Object.extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
};
Object.extend(Object, {
inspect: function(object) {
try {
if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
},
toJSON: function(object) {
var type = typeof object;
switch (type) {
case 'undefined':
case 'function':
case 'unknown': return;
case 'boolean': return object.toString();
}
if (object === null) return 'null';
if (object.toJSON) return object.toJSON();
if (Object.isElement(object)) return;
var results = [];
for (var property in object) {
var value = Object.toJSON(object[property]);
if (!Object.isUndefined(value))
results.push(property.toJSON() + ': ' + value);
}
return '{' + results.join(', ') + '}';
},
toQueryString: function(object) {
return $H(object).toQueryString();
},
toHTML: function(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
},
keys: function(object) {
var keys = [];
for (var property in object)
keys.push(property);
return keys;
},
values: function(object) {
var values = [];
for (var property in object)
values.push(object[property]);
return values;
},
clone: function(object) {
return Object.extend({ }, object);
},
isElement: function(object) {
return !!(object && object.nodeType == 1);
},
isArray: function(object) {
return object != null && typeof object == "object" &&
'splice' in object && 'join' in object;
},
isHash: function(object) {
return object instanceof Hash;
},
isFunction: function(object) {
return typeof object == "function";
},
isString: function(object) {
return typeof object == "string";
},
isNumber: function(object) {
return typeof object == "number";
},
isUndefined: function(object) {
return typeof object == "undefined";
}
});
Object.extend(Function.prototype, {
argumentNames: function() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
},
bind: function() {
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
var __method = this, args = $A(arguments), object = args.shift();
return function() {
return __method.apply(object, args.concat($A(arguments)));
}
},
bindAsEventListener: function() {
var __method = this, args = $A(arguments), object = args.shift();
return function(event) {
return __method.apply(object, [event || window.event].concat(args));
}
},
curry: function() {
if (!arguments.length) return this;
var __method = this, args = $A(arguments);
return function() {
return __method.apply(this, args.concat($A(arguments)));
}
},
delay: function() {
var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
},
defer: function() {
var args = [0.01].concat($A(arguments));
return this.delay.apply(this, args);
},
wrap: function(wrapper) {
var __method = this;
return function() {
return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
}
},
methodize: function() {
if (this._methodized) return this._methodized;
var __method = this;
return this._methodized = function() {
return __method.apply(null, [this].concat($A(arguments)));
};
}
});
Date.prototype.toJSON = function() {
return '"' + this.getUTCFullYear() + '-' +
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +
this.getUTCDate().toPaddedString(2) + 'T' +
this.getUTCHours().toPaddedString(2) + ':' +
this.getUTCMinutes().toPaddedString(2) + ':' +
this.getUTCSeconds().toPaddedString(2) + 'Z"';
};
var Try = {
these: function() {
var returnValue;
for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) { }
}
return returnValue;
}
};
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(str) {
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
/*--------------------------------------------------------------------------*/
var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
execute: function() {
this.callback(this);
},
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.execute();
} finally {
this.currentlyExecuting = false;
}
}
}
});
Object.extend(String, {
interpret: function(value) {
return value == null ? '' : String(value);
},
specialChar: {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
});
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
var result = '', source = this, match;
replacement = arguments.callee.prepareReplacement(replacement);
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
}
}
return result;
},
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
return replacement(match);
});
},
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
return String(this);
},
truncate: function(length, truncation) {
length = length || 30;
truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
},
strip: function() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
},
stripTags: function() {
return this.replace(/<\/?[^>]+>/gi, '');
},
stripScripts: function() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
},
extractScripts: function() {
var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
return (this.match(matchAll) || []).map(function(scriptTag) {
return (scriptTag.match(matchOne) || ['', ''])[1];
});
},
evalScripts: function() {
return this.extractScripts().map(function(script) { return eval(script) });
},
escapeHTML: function() {
var self = arguments.callee;
self.text.data = this;
return self.div.innerHTML;
},
unescapeHTML: function() {
var div = new Element('div');
div.innerHTML = this.stripTags();
return div.childNodes[0] ? (div.childNodes.length > 1 ?
$A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
div.childNodes[0].nodeValue) : '';
},
toQueryParams: function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };
return match[1].split(separator || '&').inject({ }, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var key = decodeURIComponent(pair.shift());
var value = pair.length > 1 ? pair.join('=') : pair[0];
if (value != undefined) value = decodeURIComponent(value);
if (key in hash) {
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
hash[key].push(value);
}
else hash[key] = value;
}
return hash;
});
},
toArray: function() {
return this.split('');
},
succ: function() {
return this.slice(0, this.length - 1) +
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
},
times: function(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
},
camelize: function() {
var parts = this.split('-'), len = parts.length;
if (len == 1) return parts[0];
var camelized = this.charAt(0) == '-'
? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
: parts[0];
for (var i = 1; i < len; i++)
camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
return camelized;
},
capitalize: function() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
},
underscore: function() {
return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
},
dasherize: function() {
return this.gsub(/_/,'-');
},
inspect: function(useDoubleQuotes) {
var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
var character = String.specialChar[match[0]];
return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
});
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
},
toJSON: function() {
return this.inspect(true);
},
unfilterJSON: function(filter) {
return this.sub(filter || Prototype.JSONFilter, '#{1}');
},
isJSON: function() {
var str = this;
if (str.blank()) return false;
str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
},
evalJSON: function(sanitize) {
var json = this.unfilterJSON();
try {
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
},
include: function(pattern) {
return this.indexOf(pattern) > -1;
},
startsWith: function(pattern) {
return this.indexOf(pattern) === 0;
},
endsWith: function(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
},
empty: function() {
return this == '';
},
blank: function() {
return /^\s*$/.test(this);
},
interpolate: function(object, pattern) {
return new Template(this, pattern).evaluate(object);
}
});
if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
escapeHTML: function() {
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
},
unescapeHTML: function() {
return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
});
String.prototype.gsub.prepareReplacement = function(replacement) {
if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
};
String.prototype.parseQuery = String.prototype.toQueryParams;
Object.extend(String.prototype.escapeHTML, {
div: document.createElement('div'),
text: document.createTextNode('')
});
String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
if (Object.isFunction(object.toTemplateReplacements))
object = object.toTemplateReplacements();
return this.template.gsub(this.pattern, function(match) {
if (object == null) return '';
var before = match[1] || '';
if (before == '\\') return match[2];
var ctx = object, expr = match[3];
var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
match = pattern.exec(expr);
if (match == null) return before;
while (match != null) {
var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
ctx = ctx[comp];
if (null == ctx || '' == match[3]) break;
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
match = pattern.exec(expr);
}
return before + String.interpret(ctx);
});
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = { };
var Enumerable = {
each: function(iterator, context) {
var index = 0;
try {
this._each(function(value) {
iterator.call(context, value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
return this;
},
eachSlice: function(number, iterator, context) {
var index = -number, slices = [], array = this.toArray();
if (number < 1) return array;
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
return slices.collect(iterator, context);
},
all: function(iterator, context) {
iterator = iterator || Prototype.K;
var result = true;
this.each(function(value, index) {
result = result && !!iterator.call(context, value, index);
if (!result) throw $break;
});
return result;
},
any: function(iterator, context) {
iterator = iterator || Prototype.K;
var result = false;
this.each(function(value, index) {
if (result = !!iterator.call(context, value, index))
throw $break;
});
return result;
},
collect: function(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator.call(context, value, index));
});
return results;
},
detect: function(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
result = value;
throw $break;
}
});
return result;
},
findAll: function(iterator, context) {
var results = [];
this.each(function(value, index) {
if (iterator.call(context, value, index))
results.push(value);
});
return results;
},
grep: function(filter, iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
if (Object.isString(filter))
filter = new RegExp(filter);
this.each(function(value, index) {
if (filter.match(value))
results.push(iterator.call(context, value, index));
});
return results;
},
include: function(object) {
if (Object.isFunction(this.indexOf))
if (this.indexOf(object) != -1) return true;
var found = false;
this.each(function(value) {
if (value == object) {
found = true;
throw $break;
}
});
return found;
},
inGroupsOf: function(number, fillWith) {
fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
},
inject: function(memo, iterator, context) {
this.each(function(value, index) {
memo = iterator.call(context, memo, value, index);
});
return memo;
},
invoke: function(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
},
max: function(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value >= result)
result = value;
});
return result;
},
min: function(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value < result)
result = value;
});
return result;
},
partition: function(iterator, context) {
iterator = iterator || Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
(iterator.call(context, value, index) ?
trues : falses).push(value);
});
return [trues, falses];
},
pluck: function(property) {
var results = [];
this.each(function(value) {
results.push(value[property]);
});
return results;
},
reject: function(iterator, context) {
var results = [];
this.each(function(value, index) {
if (!iterator.call(context, value, index))
results.push(value);
});
return results;
},
sortBy: function(iterator, context) {
return this.map(function(value, index) {
return {
value: value,
criteria: iterator.call(context, value, index)
};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}).pluck('value');
},
toArray: function() {
return this.map();
},
zip: function() {
var iterator = Prototype.K, args = $A(arguments);
if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
return this.map(function(value, index) {
return iterator(collections.pluck(index));
});
},
size: function() {
return this.toArray().length;
},
inspect: function() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
};
Object.extend(Enumerable, {
map: Enumerable.collect,
find: Enumerable.detect,
select: Enumerable.findAll,
filter: Enumerable.findAll,
member: Enumerable.include,
entries: Enumerable.toArray,
every: Enumerable.all,
some: Enumerable.any
});
function $A(iterable) {
if (!iterable) return [];
if (iterable.toArray) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
if (Prototype.Browser.WebKit) {
$A = function(iterable) {
if (!iterable) return [];
// In Safari, only use the `toArray` method if it's not a NodeList.
// A NodeList is a function, has an function `item` property, and a numeric
// `length` property. Adapted from Google Doctype.
if (!(typeof iterable === 'function' && typeof iterable.length ===
'number' && typeof iterable.item === 'function') && iterable.toArray)
return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
};
}
Array.from = $A;
Object.extend(Array.prototype, Enumerable);
if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
clear: function() {
this.length = 0;
return this;
},
first: function() {
return this[0];
},
last: function() {
return this[this.length - 1];
},
compact: function() {
return this.select(function(value) {
return value != null;
});
},
flatten: function() {
return this.inject([], function(array, value) {
return array.concat(Object.isArray(value) ?
value.flatten() : [value]);
});
},
without: function() {
var values = $A(arguments);
return this.select(function(value) {
return !values.include(value);
});
},
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
reduce: function() {
return this.length > 1 ? this : this[0];
},
uniq: function(sorted) {
return this.inject([], function(array, value, index) {
if (0 == index || (sorted ? array.last() != value : !array.include(value)))
array.push(value);
return array;
});
},
intersect: function(array) {
return this.uniq().findAll(function(item) {
return array.detect(function(value) { return item === value });
});
},
clone: function() {
return [].concat(this);
},
size: function() {
return this.length;
},
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
},
toJSON: function() {
var results = [];
this.each(function(object) {
var value = Object.toJSON(object);
if (!Object.isUndefined(value)) results.push(value);
});
return '[' + results.join(', ') + ']';
}
});
// use native browser JS 1.6 implementation if available
if (Object.isFunction(Array.prototype.forEach))
Array.prototype._each = Array.prototype.forEach;
if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
};
if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
var n = this.slice(0, i).reverse().indexOf(item);
return (n < 0) ? n : i - n - 1;
};
Array.prototype.toArray = Array.prototype.clone;
function $w(string) {
if (!Object.isString(string)) return [];
string = string.strip();
return string ? string.split(/\s+/) : [];
}
if (Prototype.Browser.Opera){
Array.prototype.concat = function() {
var array = [];
for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
for (var i = 0, length = arguments.length; i < length; i++) {
if (Object.isArray(arguments[i])) {
for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
array.push(arguments[i][j]);
} else {
array.push(arguments[i]);
}
}
return array;
};
}
Object.extend(Number.prototype, {
toColorPart: function() {
return this.toPaddedString(2, 16);
},
succ: function() {
return this + 1;
},
times: function(iterator, context) {
$R(0, this, true).each(iterator, context);
return this;
},
toPaddedString: function(length, radix) {
var string = this.toString(radix || 10);
return '0'.times(length - string.length) + string;
},
toJSON: function() {
return isFinite(this) ? this.toString() : 'null';
}
});
$w('abs round ceil floor').each(function(method){
Number.prototype[method] = Math[method].methodize();
});
function $H(object) {
return new Hash(object);
};
var Hash = Class.create(Enumerable, (function() {
function toQueryPair(key, value) {
if (Object.isUndefined(value)) return key;
return key + '=' + encodeURIComponent(String.interpret(value));
}
return {
initialize: function(object) {
this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
},
_each: function(iterator) {
for (var key in this._object) {
var value = this._object[key], pair = [key, value];
pair.key = key;
pair.value = value;
iterator(pair);
}
},
set: function(key, value) {
return this._object[key] = value;
},
get: function(key) {
// simulating poorly supported hasOwnProperty
if (this._object[key] !== Object.prototype[key])
return this._object[key];
},
unset: function(key) {
var value = this._object[key];
delete this._object[key];
return value;
},
toObject: function() {
return Object.clone(this._object);
},
keys: function() {
return this.pluck('key');
},
values: function() {
return this.pluck('value');
},
index: function(value) {
var match = this.detect(function(pair) {
return pair.value === value;
});
return match && match.key;
},
merge: function(object) {
return this.clone().update(object);
},
update: function(object) {
return new Hash(object).inject(this, function(result, pair) {
result.set(pair.key, pair.value);
return result;
});
},
toQueryString: function() {
return this.inject([], function(results, pair) {
var key = encodeURIComponent(pair.key), values = pair.value;
if (values && typeof values == 'object') {
if (Object.isArray(values))
return results.concat(values.map(toQueryPair.curry(key)));
} else results.push(toQueryPair(key, values));
return results;
}).join('&');
},
inspect: function() {
return '#<Hash:{' + this.map(function(pair) {
return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
},
toJSON: function() {
return Object.toJSON(this.toObject());
},
clone: function() {
return new Hash(this);
}
}
})());
Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
Hash.from = $H;
var ObjectRange = Class.create(Enumerable, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
},
_each: function(iterator) {
var value = this.start;
while (this.include(value)) {
iterator(value);
value = value.succ();
}
},
include: function(value) {
if (value < this.start)
return false;
if (this.exclusive)
return value < this.end;
return value <= this.end;
}
});
var $R = function(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
};
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},
activeRequestCount: 0
};
Ajax.Responders = {
responders: [],
_each: function(iterator) {
this.responders._each(iterator);
},
register: function(responder) {
if (!this.include(responder))
this.responders.push(responder);
},
unregister: function(responder) {
this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) { }
}
});
}
};
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
onCreate: function() { Ajax.activeRequestCount++ },
onComplete: function() { Ajax.activeRequestCount-- }
});
Ajax.Base = Class.create({
initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: '',
evalJSON: true,
evalJS: true
};
Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
if (Object.isString(this.options.parameters))
this.options.parameters = this.options.parameters.toQueryParams();
else if (Object.isHash(this.options.parameters))
this.options.parameters = this.options.parameters.toObject();
}
});
Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
initialize: function($super, url, options) {
$super(options);
this.transport = Ajax.getTransport();
this.request(url);
},
request: function(url) {
this.url = url;
this.method = this.options.method;
var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
// simulate other verbs over post
params['_method'] = this.method;
this.method = 'post';
}
this.parameters = params;
if (params = Object.toQueryString(params)) {
// when GET, append parameters to URL
if (this.method == 'get')
this.url += (this.url.include('?') ? '&' : '?') + params;
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
params += '&_=';
}
try {
var response = new Ajax.Response(this);
if (this.options.onCreate) this.options.onCreate(response);
Ajax.Responders.dispatch('onCreate', this, response);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
this.transport.send(this.body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
}
catch (e) {
this.dispatchException(e);
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1 && !((readyState == 4) && this._complete))
this.respondToReadyState(this.transport.readyState);
},
setRequestHeaders: function() {
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};
if (this.method == 'post') {
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
// user-defined headers
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
if (Object.isFunction(extras.push))
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
}
for (var name in headers)
this.transport.setRequestHeader(name, headers[name]);
},
success: function() {
var status = this.getStatus();
return !status || (status >= 200 && status < 300);
},
getStatus: function() {
try {
return this.transport.status || 0;
} catch (e) { return 0 }
},
respondToReadyState: function(readyState) {
var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
if (state == 'Complete') {
try {
this._complete = true;
(this.options['on' + response.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
var contentType = response.getHeader('Content-type');
if (this.options.evalJS == 'force'
|| (this.options.evalJS && this.isSameOrigin() && contentType
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
try {
(this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
if (state == 'Complete') {
// avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
isSameOrigin: function() {
var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
protocol: location.protocol,
domain: document.domain,
port: location.port ? ':' + location.port : ''
}));
},
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name) || null;
} catch (e) { return null }
},
evalResponse: function() {
try {
return eval((this.transport.responseText || '').unfilterJSON());
} catch (e) {
this.dispatchException(e);
}
},
dispatchException: function(exception) {
(this.options.onException || Prototype.emptyFunction)(this, exception);
Ajax.Responders.dispatch('onException', this, exception);
}
});
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Response = Class.create({
initialize: function(request){
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = String.interpret(transport.responseText);
this.headerJSON = this._getHeaderJSON();
}
if(readyState == 4) {
var xml = transport.responseXML;
this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
status: 0,
statusText: '',
getStatus: Ajax.Request.prototype.getStatus,
getStatusText: function() {
try {
return this.transport.statusText || '';
} catch (e) { return '' }
},
getHeader: Ajax.Request.prototype.getHeader,
getAllHeaders: function() {
try {
return this.getAllResponseHeaders();
} catch (e) { return null }
},
getResponseHeader: function(name) {
return this.transport.getResponseHeader(name);
},
getAllResponseHeaders: function() {
return this.transport.getAllResponseHeaders();
},
_getHeaderJSON: function() {
var json = this.getHeader('X-JSON');
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
return json.evalJSON(this.request.options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
},
_getResponseJSON: function() {
var options = this.request.options;
if (!options.evalJSON || (options.evalJSON != 'force' &&
!(this.getHeader('Content-type') || '').include('application/json')) ||
this.responseText.blank())
return null;
try {
return this.responseText.evalJSON(options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
}
});
Ajax.Updater = Class.create(Ajax.Request, {
initialize: function($super, container, url, options) {
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
};
options = Object.clone(options);
var onComplete = options.onComplete;
options.onComplete = (function(response, json) {
this.updateContent(response.responseText);
if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
$super(url, options);
},
updateContent: function(responseText) {
var receiver = this.container[this.success() ? 'success' : 'failure'],
options = this.options;
if (!options.evalScripts) responseText = responseText.stripScripts();
if (receiver = $(receiver)) {
if (options.insertion) {
if (Object.isString(options.insertion)) {
var insertion = { }; insertion[options.insertion] = responseText;
receiver.insert(insertion);
}
else options.insertion(receiver, responseText);
}
else receiver.update(responseText);
}
}
});
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
initialize: function($super, container, url, options) {
$super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.o
gitextract_afh5kztq/
├── .document
├── .gitignore
├── .rspec
├── .rvmrc
├── CHANGELOG.md
├── Gemfile
├── Guardfile
├── LICENSE
├── README.rdoc
├── Rakefile
├── VERSION
├── analytical.gemspec
├── app/
│ └── views/
│ └── application/
│ └── _analytical_javascript.html.erb
├── example/
│ ├── .gitignore
│ ├── rails2.3/
│ │ ├── Gemfile
│ │ ├── README
│ │ ├── Rakefile
│ │ ├── app/
│ │ │ ├── controllers/
│ │ │ │ ├── application_controller.rb
│ │ │ │ └── page_controller.rb
│ │ │ ├── helpers/
│ │ │ │ └── application_helper.rb
│ │ │ └── views/
│ │ │ ├── layouts/
│ │ │ │ └── application.html.erb
│ │ │ └── page/
│ │ │ ├── index.html.erb
│ │ │ ├── test_a.html.erb
│ │ │ └── test_b.html.erb
│ │ ├── config/
│ │ │ ├── boot.rb
│ │ │ ├── database.yml
│ │ │ ├── environment.rb
│ │ │ ├── environments/
│ │ │ │ ├── development.rb
│ │ │ │ ├── production.rb
│ │ │ │ └── test.rb
│ │ │ ├── initializers/
│ │ │ │ ├── backtrace_silencers.rb
│ │ │ │ ├── cookie_verification_secret.rb
│ │ │ │ ├── inflections.rb
│ │ │ │ ├── mime_types.rb
│ │ │ │ ├── new_rails_defaults.rb
│ │ │ │ └── session_store.rb
│ │ │ ├── locales/
│ │ │ │ └── en.yml
│ │ │ └── routes.rb
│ │ ├── db/
│ │ │ ├── development.sqlite3
│ │ │ └── seeds.rb
│ │ ├── doc/
│ │ │ └── README_FOR_APP
│ │ ├── public/
│ │ │ ├── 404.html
│ │ │ ├── 422.html
│ │ │ ├── 500.html
│ │ │ ├── javascripts/
│ │ │ │ ├── application.js
│ │ │ │ ├── controls.js
│ │ │ │ ├── dragdrop.js
│ │ │ │ ├── effects.js
│ │ │ │ └── prototype.js
│ │ │ └── robots.txt
│ │ ├── script/
│ │ │ ├── about
│ │ │ ├── console
│ │ │ ├── dbconsole
│ │ │ ├── destroy
│ │ │ ├── generate
│ │ │ ├── performance/
│ │ │ │ ├── benchmarker
│ │ │ │ └── profiler
│ │ │ ├── plugin
│ │ │ ├── runner
│ │ │ └── server
│ │ └── test/
│ │ ├── performance/
│ │ │ └── browsing_test.rb
│ │ └── test_helper.rb
│ ├── rails3/
│ │ ├── Gemfile
│ │ ├── README
│ │ ├── Rakefile
│ │ ├── app/
│ │ │ ├── controllers/
│ │ │ │ ├── application_controller.rb
│ │ │ │ └── page_controller.rb
│ │ │ ├── helpers/
│ │ │ │ ├── application_helper.rb
│ │ │ │ └── page_helper.rb
│ │ │ └── views/
│ │ │ ├── layouts/
│ │ │ │ └── application.html.erb
│ │ │ └── page/
│ │ │ ├── index.html.erb
│ │ │ ├── test_a.html.erb
│ │ │ └── test_b.html.erb
│ │ ├── config/
│ │ │ ├── analytical.yml
│ │ │ ├── application.rb
│ │ │ ├── boot.rb
│ │ │ ├── database.yml
│ │ │ ├── environment.rb
│ │ │ ├── environments/
│ │ │ │ ├── development.rb
│ │ │ │ ├── production.rb
│ │ │ │ └── test.rb
│ │ │ ├── initializers/
│ │ │ │ ├── backtrace_silencers.rb
│ │ │ │ ├── inflections.rb
│ │ │ │ ├── mime_types.rb
│ │ │ │ ├── secret_token.rb
│ │ │ │ └── session_store.rb
│ │ │ ├── locales/
│ │ │ │ └── en.yml
│ │ │ └── routes.rb
│ │ ├── config.ru
│ │ ├── db/
│ │ │ ├── development.sqlite3
│ │ │ ├── production.sqlite3
│ │ │ └── seeds.rb
│ │ ├── doc/
│ │ │ └── README_FOR_APP
│ │ ├── lib/
│ │ │ └── tasks/
│ │ │ └── .gitkeep
│ │ ├── public/
│ │ │ ├── 404.html
│ │ │ ├── 422.html
│ │ │ ├── 500.html
│ │ │ ├── javascripts/
│ │ │ │ ├── application.js
│ │ │ │ ├── controls.js
│ │ │ │ ├── dragdrop.js
│ │ │ │ ├── effects.js
│ │ │ │ ├── prototype.js
│ │ │ │ └── rails.js
│ │ │ ├── robots.txt
│ │ │ └── stylesheets/
│ │ │ └── .gitkeep
│ │ ├── script/
│ │ │ └── rails
│ │ ├── test/
│ │ │ ├── functional/
│ │ │ │ └── page_controller_test.rb
│ │ │ ├── performance/
│ │ │ │ └── browsing_test.rb
│ │ │ ├── test_helper.rb
│ │ │ └── unit/
│ │ │ └── helpers/
│ │ │ └── page_helper_test.rb
│ │ └── vendor/
│ │ └── plugins/
│ │ └── .gitkeep
│ └── rails3.1/
│ ├── Gemfile
│ ├── README
│ ├── Rakefile
│ ├── app/
│ │ ├── assets/
│ │ │ ├── javascripts/
│ │ │ │ └── application.js
│ │ │ └── stylesheets/
│ │ │ └── application.css
│ │ ├── controllers/
│ │ │ ├── application_controller.rb
│ │ │ └── page_controller.rb
│ │ ├── helpers/
│ │ │ └── application_helper.rb
│ │ ├── mailers/
│ │ │ └── .gitkeep
│ │ ├── models/
│ │ │ └── .gitkeep
│ │ └── views/
│ │ ├── layouts/
│ │ │ └── application.html.erb
│ │ └── page/
│ │ ├── index.html.erb
│ │ ├── test_a.html.erb
│ │ └── test_b.html.erb
│ ├── config/
│ │ ├── application.rb
│ │ ├── boot.rb
│ │ ├── database.yml
│ │ ├── environment.rb
│ │ ├── environments/
│ │ │ ├── development.rb
│ │ │ ├── production.rb
│ │ │ └── test.rb
│ │ ├── initializers/
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── inflections.rb
│ │ │ ├── mime_types.rb
│ │ │ ├── secret_token.rb
│ │ │ ├── session_store.rb
│ │ │ └── wrap_parameters.rb
│ │ ├── locales/
│ │ │ └── en.yml
│ │ └── routes.rb
│ ├── config.ru
│ ├── db/
│ │ ├── development.sqlite3
│ │ └── seeds.rb
│ ├── doc/
│ │ └── README_FOR_APP
│ ├── lib/
│ │ ├── assets/
│ │ │ └── .gitkeep
│ │ └── tasks/
│ │ └── .gitkeep
│ ├── public/
│ │ ├── 404.html
│ │ ├── 422.html
│ │ ├── 500.html
│ │ └── robots.txt
│ ├── script/
│ │ └── rails
│ ├── test/
│ │ ├── fixtures/
│ │ │ └── .gitkeep
│ │ ├── functional/
│ │ │ └── .gitkeep
│ │ ├── integration/
│ │ │ └── .gitkeep
│ │ ├── performance/
│ │ │ └── browsing_test.rb
│ │ ├── test_helper.rb
│ │ └── unit/
│ │ └── .gitkeep
│ └── vendor/
│ ├── assets/
│ │ └── stylesheets/
│ │ └── .gitkeep
│ └── plugins/
│ └── .gitkeep
├── lib/
│ ├── analytical/
│ │ ├── api.rb
│ │ ├── bot_detector.rb
│ │ ├── command_store.rb
│ │ ├── modules/
│ │ │ ├── adroll.rb
│ │ │ ├── adwords.rb
│ │ │ ├── base.rb
│ │ │ ├── chartbeat.rb
│ │ │ ├── click_tale.rb
│ │ │ ├── clicky.rb
│ │ │ ├── comscore.rb
│ │ │ ├── console.rb
│ │ │ ├── crazy_egg.rb
│ │ │ ├── gauges.rb
│ │ │ ├── google.rb
│ │ │ ├── google_optimizer.rb
│ │ │ ├── google_universal.rb
│ │ │ ├── hubspot.rb
│ │ │ ├── kiss_metrics.rb
│ │ │ ├── loopfuse.rb
│ │ │ ├── microsoft_ads.rb
│ │ │ ├── mixpanel.rb
│ │ │ ├── mouseflow.rb
│ │ │ ├── optimizely.rb
│ │ │ ├── performancing.rb
│ │ │ ├── quantcast.rb
│ │ │ ├── reinvigorate.rb
│ │ │ └── segment_io.rb
│ │ ├── rails/
│ │ │ └── engine.rb
│ │ └── session_command_store.rb
│ └── analytical.rb
├── rails/
│ └── init.rb
└── spec/
├── analytical/
│ ├── api_spec.rb
│ ├── bot_detector_spec.rb
│ ├── command_store_spec.rb
│ ├── modules/
│ │ ├── adroll_spec.rb
│ │ ├── adwords_spec.rb
│ │ ├── base_spec.rb
│ │ ├── chartbeat_spec.rb
│ │ ├── clicky_spec.rb
│ │ ├── comscore_spec.rb
│ │ ├── gauges_spec.rb
│ │ ├── google_spec.rb
│ │ ├── google_universal_spec.rb
│ │ ├── kiss_metrics_spec.rb
│ │ ├── mixpanel_spec.rb
│ │ ├── optimizely_spec.rb
│ │ ├── quantcast.rb
│ │ ├── reinvigorate_spec.rb
│ │ └── segment_io_spec.rb
│ └── session_command_store_spec.rb
├── analytical_spec.rb
├── config/
│ └── analytical.yml
├── spec.opts
└── spec_helper.rb
SYMBOL INDEX (468 symbols across 61 files)
FILE: example/rails2.3/app/controllers/application_controller.rb
class ApplicationController (line 1) | class ApplicationController < ActionController::Base
FILE: example/rails2.3/app/controllers/page_controller.rb
class PageController (line 1) | class PageController < ApplicationController
method index (line 2) | def index
method test_a (line 5) | def test_a
method test_b (line 8) | def test_b
method test_c (line 13) | def test_c
FILE: example/rails2.3/app/helpers/application_helper.rb
type ApplicationHelper (line 2) | module ApplicationHelper
FILE: example/rails2.3/config/boot.rb
type Rails (line 6) | module Rails
function boot! (line 8) | def boot!
function booted? (line 15) | def booted?
function pick_boot (line 19) | def pick_boot
function vendor_rails? (line 23) | def vendor_rails?
function preinitialize (line 27) | def preinitialize
function preinitializer_path (line 31) | def preinitializer_path
class Boot (line 36) | class Boot
method run (line 37) | def run
class VendorBoot (line 43) | class VendorBoot < Boot
method load_initializer (line 44) | def load_initializer
class GemBoot (line 51) | class GemBoot < Boot
method load_initializer (line 52) | def load_initializer
method load_rails_gem (line 58) | def load_rails_gem
method rubygems_version (line 74) | def rubygems_version
method gem_version (line 78) | def gem_version
method load_rubygems (line 88) | def load_rubygems
method parse_gem_version (line 101) | def parse_gem_version(text)
method read_environment_rb (line 106) | def read_environment_rb
FILE: example/rails2.3/public/javascripts/controls.js
function addText (line 561) | function addText(mode, condition) {
function fallback (line 857) | function fallback(name, expr) {
FILE: example/rails2.3/public/javascripts/effects.js
function codeForEvent (line 231) | function codeForEvent(options,eventName){
function dispatch (line 248) | function dispatch(effect, eventName) {
function parseColor (line 952) | function parseColor(color){
FILE: example/rails2.3/public/javascripts/prototype.js
function klass (line 50) | function klass() {
function $A (line 812) | function $A(iterable) {
function $w (line 945) | function $w(string) {
function $H (line 993) | function $H(object) {
function toQueryPair (line 999) | function toQueryPair(key, value) {
function $ (line 1513) | function $(element) {
function stripAlpha (line 2289) | function stripAlpha(filter){
function extend (line 2627) | function extend(tagName) {
function copy (line 2634) | function copy(methods, destination, onlyIfAbsent) {
function findDOMClass (line 2644) | function findDOMClass(tagName) {
function $$ (line 3443) | function $$() {
function getEventID (line 3935) | function getEventID(element) {
function getDOMEventName (line 3941) | function getDOMEventName(eventName) {
function getCacheForID (line 3946) | function getCacheForID(id) {
function getWrappersForEventName (line 3950) | function getWrappersForEventName(id, eventName) {
function createWrapper (line 3955) | function createWrapper(element, eventName, handler) {
function findWrapper (line 3974) | function findWrapper(id, eventName, handler) {
function destroyWrapper (line 3979) | function destroyWrapper(id, eventName, handler) {
function destroyCache (line 3985) | function destroyCache() {
function fireContentLoadedEvent (line 4102) | function fireContentLoadedEvent() {
function iter (line 4251) | function iter(name) {
FILE: example/rails2.3/test/performance/browsing_test.rb
class BrowsingTest (line 5) | class BrowsingTest < ActionController::PerformanceTest
method test_homepage (line 6) | def test_homepage
FILE: example/rails2.3/test/test_helper.rb
class ActiveSupport::TestCase (line 5) | class ActiveSupport::TestCase
FILE: example/rails3.1/app/controllers/application_controller.rb
class ApplicationController (line 1) | class ApplicationController < ActionController::Base
FILE: example/rails3.1/app/controllers/page_controller.rb
class PageController (line 1) | class PageController < ApplicationController
method index (line 2) | def index
method test_a (line 5) | def test_a
method test_b (line 8) | def test_b
method test_c (line 13) | def test_c
FILE: example/rails3.1/app/helpers/application_helper.rb
type ApplicationHelper (line 1) | module ApplicationHelper
FILE: example/rails3.1/config/application.rb
type Example (line 12) | module Example
class Application (line 13) | class Application < Rails::Application
FILE: example/rails3.1/test/performance/browsing_test.rb
class BrowsingTest (line 4) | class BrowsingTest < ActionDispatch::PerformanceTest
method test_homepage (line 9) | def test_homepage
FILE: example/rails3.1/test/test_helper.rb
class ActiveSupport::TestCase (line 5) | class ActiveSupport::TestCase
FILE: example/rails3/app/controllers/application_controller.rb
class ApplicationController (line 1) | class ApplicationController < ActionController::Base
FILE: example/rails3/app/controllers/page_controller.rb
class PageController (line 1) | class PageController < ApplicationController
method index (line 2) | def index
method test_a (line 5) | def test_a
method test_b (line 8) | def test_b
method test_c (line 13) | def test_c
FILE: example/rails3/app/helpers/application_helper.rb
type ApplicationHelper (line 1) | module ApplicationHelper
FILE: example/rails3/app/helpers/page_helper.rb
type PageHelper (line 1) | module PageHelper
FILE: example/rails3/config/application.rb
type Example (line 9) | module Example
class Application (line 10) | class Application < Rails::Application
FILE: example/rails3/public/javascripts/controls.js
function addText (line 563) | function addText(mode, condition) {
function fallback (line 859) | function fallback(name, expr) {
FILE: example/rails3/public/javascripts/effects.js
function dispatch (line 243) | function dispatch(effect, eventName) {
function parseColor (line 947) | function parseColor(color){
FILE: example/rails3/public/javascripts/prototype.js
function subclass (line 82) | function subclass() {}
function create (line 83) | function create() {
function addMethods (line 112) | function addMethods(source) {
function extend (line 152) | function extend(destination, source) {
function inspect (line 158) | function inspect(object) {
function toJSON (line 169) | function toJSON(object) {
function toQueryString (line 192) | function toQueryString(object) {
function toHTML (line 196) | function toHTML(object) {
function keys (line 200) | function keys(object) {
function values (line 207) | function values(object) {
function clone (line 214) | function clone(object) {
function isElement (line 218) | function isElement(object) {
function isArray (line 222) | function isArray(object) {
function isHash (line 227) | function isHash(object) {
function isFunction (line 231) | function isFunction(object) {
function isString (line 235) | function isString(object) {
function isNumber (line 239) | function isNumber(object) {
function isUndefined (line 243) | function isUndefined(object) {
function update (line 268) | function update(array, args) {
function merge (line 274) | function merge(array, args) {
function argumentNames (line 279) | function argumentNames() {
function bind (line 286) | function bind(context) {
function bindAsEventListener (line 295) | function bindAsEventListener(context) {
function curry (line 303) | function curry() {
function delay (line 312) | function delay(timeout) {
function defer (line 320) | function defer() {
function wrap (line 325) | function wrap(wrapper) {
function methodize (line 333) | function methodize() {
function prepareReplacement (line 422) | function prepareReplacement(replacement) {
function gsub (line 428) | function gsub(pattern, replacement) {
function sub (line 452) | function sub(pattern, replacement, count) {
function scan (line 462) | function scan(pattern, iterator) {
function truncate (line 467) | function truncate(length, truncation) {
function strip (line 474) | function strip() {
function stripTags (line 478) | function stripTags() {
function stripScripts (line 482) | function stripScripts() {
function extractScripts (line 486) | function extractScripts() {
function evalScripts (line 494) | function evalScripts() {
function escapeHTML (line 498) | function escapeHTML() {
function unescapeHTML (line 502) | function unescapeHTML() {
function toQueryParams (line 507) | function toQueryParams(separator) {
function toArray (line 527) | function toArray() {
function succ (line 531) | function succ() {
function times (line 536) | function times(count) {
function camelize (line 540) | function camelize() {
function capitalize (line 554) | function capitalize() {
function underscore (line 558) | function underscore() {
function dasherize (line 566) | function dasherize() {
function inspect (line 570) | function inspect(useDoubleQuotes) {
function toJSON (line 581) | function toJSON() {
function unfilterJSON (line 585) | function unfilterJSON(filter) {
function isJSON (line 589) | function isJSON() {
function evalJSON (line 596) | function evalJSON(sanitize) {
function include (line 604) | function include(pattern) {
function startsWith (line 608) | function startsWith(pattern) {
function endsWith (line 612) | function endsWith(pattern) {
function empty (line 617) | function empty() {
function blank (line 621) | function blank() {
function interpolate (line 625) | function interpolate(object, pattern) {
function each (line 702) | function each(iterator, context) {
function eachSlice (line 714) | function eachSlice(number, iterator, context) {
function all (line 722) | function all(iterator, context) {
function any (line 732) | function any(iterator, context) {
function collect (line 742) | function collect(iterator, context) {
function detect (line 751) | function detect(iterator, context) {
function findAll (line 762) | function findAll(iterator, context) {
function grep (line 771) | function grep(filter, iterator, context) {
function include (line 785) | function include(object) {
function inGroupsOf (line 799) | function inGroupsOf(number, fillWith) {
function inject (line 807) | function inject(memo, iterator, context) {
function invoke (line 814) | function invoke(method) {
function max (line 821) | function max(iterator, context) {
function min (line 832) | function min(iterator, context) {
function partition (line 843) | function partition(iterator, context) {
function pluck (line 853) | function pluck(property) {
function reject (line 861) | function reject(iterator, context) {
function sortBy (line 870) | function sortBy(iterator, context) {
function toArray (line 882) | function toArray() {
function zip (line 886) | function zip() {
function size (line 897) | function size() {
function inspect (line 901) | function inspect() {
function $A (line 946) | function $A(iterable) {
function $w (line 954) | function $w(string) {
function each (line 968) | function each(iterator) {
function clear (line 974) | function clear() {
function first (line 979) | function first() {
function last (line 983) | function last() {
function compact (line 987) | function compact() {
function flatten (line 993) | function flatten() {
function without (line 1002) | function without() {
function reverse (line 1009) | function reverse(inline) {
function uniq (line 1013) | function uniq(sorted) {
function intersect (line 1021) | function intersect(array) {
function clone (line 1028) | function clone() {
function size (line 1032) | function size() {
function inspect (line 1036) | function inspect() {
function toJSON (line 1040) | function toJSON() {
function indexOf (line 1049) | function indexOf(item, i) {
function lastIndexOf (line 1058) | function lastIndexOf(item, i) {
function concat (line 1064) | function concat() {
function $H (line 1110) | function $H(object) {
function initialize (line 1115) | function initialize(object) {
function _each (line 1119) | function _each(iterator) {
function set (line 1128) | function set(key, value) {
function get (line 1132) | function get(key) {
function unset (line 1137) | function unset(key) {
function toObject (line 1143) | function toObject() {
function keys (line 1147) | function keys() {
function values (line 1151) | function values() {
function index (line 1155) | function index(value) {
function merge (line 1162) | function merge(object) {
function update (line 1166) | function update(object) {
function toQueryPair (line 1173) | function toQueryPair(key, value) {
function toQueryString (line 1178) | function toQueryString() {
function inspect (line 1190) | function inspect() {
function toJSON (line 1196) | function toJSON() {
function clone (line 1200) | function clone() {
function toColorPart (line 1226) | function toColorPart() {
function succ (line 1230) | function succ() {
function times (line 1234) | function times(iterator, context) {
function toPaddedString (line 1239) | function toPaddedString(length, radix) {
function toJSON (line 1244) | function toJSON() {
function abs (line 1248) | function abs() {
function round (line 1252) | function round() {
function ceil (line 1256) | function ceil() {
function floor (line 1260) | function floor() {
function $R (line 1277) | function $R(start, end, exclusive) {
function initialize (line 1282) | function initialize(start, end, exclusive) {
function _each (line 1288) | function _each(iterator) {
function include (line 1296) | function include(value) {
function $ (line 1709) | function $(element) {
function update (line 1861) | function update(element, content) {
function stripAlpha (line 2557) | function stripAlpha(filter){
function _descendants (line 2721) | function _descendants(element) {
function checkDeficiency (line 2884) | function checkDeficiency(tagName) {
function extendElementWith (line 2900) | function extendElementWith(element, methods) {
function extend (line 2986) | function extend(tagName) {
function copy (line 2993) | function copy(methods, destination, onlyIfAbsent) {
function findDOMClass (line 3003) | function findDOMClass(tagName) {
function getRootElement (line 3069) | function getRootElement() {
function define (line 3079) | function define(D) {
function $$ (line 3913) | function $$() {
function isLeftClick (line 4309) | function isLeftClick(event) { return _isButton(event, 0) }
function isMiddleClick (line 4311) | function isMiddleClick(event) { return _isButton(event, 1) }
function isRightClick (line 4313) | function isRightClick(event) { return _isButton(event, 2) }
function element (line 4315) | function element(event) {
function findElement (line 4334) | function findElement(event, expression) {
function pointer (line 4341) | function pointer(event) {
function pointerX (line 4345) | function pointerX(event) {
function pointerY (line 4354) | function pointerY(event) {
function stop (line 4364) | function stop(event) {
function _relatedTarget (line 4394) | function _relatedTarget(event) {
function _createResponder (line 4432) | function _createResponder(element, eventName, handler) {
function _destroyCache (line 4491) | function _destroyCache() {
function observe (line 4516) | function observe(element, eventName, handler) {
function stopObserving (line 4542) | function stopObserving(element, eventName, handler) {
function fire (line 4597) | function fire(element, eventName, memo, bubble) {
function fireContentLoadedEvent (line 4663) | function fireContentLoadedEvent() {
function checkReadyState (line 4670) | function checkReadyState() {
function pollDoScroll (line 4677) | function pollDoScroll() {
function iter (line 4807) | function iter(name) {
FILE: example/rails3/public/javascripts/rails.js
function handleRemote (line 2) | function handleRemote(element) {
function handleMethod (line 35) | function handleMethod(element) {
FILE: example/rails3/test/functional/page_controller_test.rb
class PageControllerTest (line 3) | class PageControllerTest < ActionController::TestCase
FILE: example/rails3/test/performance/browsing_test.rb
class BrowsingTest (line 5) | class BrowsingTest < ActionDispatch::PerformanceTest
method test_homepage (line 6) | def test_homepage
FILE: example/rails3/test/test_helper.rb
class ActiveSupport::TestCase (line 5) | class ActiveSupport::TestCase
FILE: example/rails3/test/unit/helpers/page_helper_test.rb
class PageHelperTest (line 3) | class PageHelperTest < ActionView::TestCase
FILE: lib/analytical.rb
type Analytical (line 7) | module Analytical
function analytical (line 9) | def analytical(options={})
type InstanceMethods (line 32) | module InstanceMethods
function analytical (line 33) | def analytical
type HelperMethods (line 62) | module HelperMethods
function analytical (line 63) | def analytical
FILE: lib/analytical/api.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class DummyModule (line 3) | class DummyModule
method method_missing (line 5) | def method_missing(method, *args, &block); nil; end
class Api (line 9) | class Api
method initialize (line 12) | def initialize(options={})
method get_mod (line 24) | def get_mod(name)
method method_missing (line 37) | def method_missing(method, *args, &block)
class ImmediateDelegateHelper (line 52) | class ImmediateDelegateHelper
method initialize (line 53) | def initialize(_parent)
method method_missing (line 56) | def method_missing(method, *args, &block)
method now (line 66) | def now
method head_prepend_javascript (line 73) | def head_prepend_javascript
method head_append_javascript (line 77) | def head_append_javascript
method body_prepend_javascript (line 97) | def body_prepend_javascript
method body_append_javascript (line 100) | def body_append_javascript
method process_command (line 106) | def process_command(command, *args)
method tracking_javascript (line 112) | def tracking_javascript(location)
method init_javascript (line 125) | def init_javascript(location)
method available_modules (line 131) | def available_modules
FILE: lib/analytical/bot_detector.rb
type Analytical (line 1) | module Analytical
type BotDetector (line 2) | module BotDetector
function analytical_is_robot? (line 4) | def analytical_is_robot?(user_agent, whitelist = [])
FILE: lib/analytical/command_store.rb
type Analytical (line 1) | module Analytical
class CommandStore (line 2) | class CommandStore
method initialize (line 5) | def initialize(initial_list=nil)
method flush (line 9) | def flush
method method_missing (line 14) | def method_missing(method, *args, &block)
FILE: lib/analytical/modules/adroll.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Adroll (line 3) | class Adroll
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/adwords.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Adwords (line 3) | class Adwords
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method event (line 48) | def event(name, *args)
FILE: lib/analytical/modules/base.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
type Base (line 3) | module Base
function initialize (line 7) | def initialize(_options={})
function protocol (line 14) | def protocol
function queue (line 44) | def queue(*args)
function process_queued_commands (line 52) | def process_queued_commands
function init_location? (line 60) | def init_location?(location)
function init_location (line 68) | def init_location(location, &block)
FILE: lib/analytical/modules/chartbeat.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Chartbeat (line 3) | class Chartbeat
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/click_tale.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class ClickTale (line 3) | class ClickTale
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/clicky.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Clicky (line 3) | class Clicky
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method track (line 42) | def track(*args)
method identify (line 46) | def identify(id, *args)
FILE: lib/analytical/modules/comscore.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Comscore (line 3) | class Comscore
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/console.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Console (line 3) | class Console
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method track (line 25) | def track(*args)
method identify (line 31) | def identify(id, *args)
method event (line 39) | def event(name, *args)
method set (line 47) | def set(data)
method alias_identity (line 54) | def alias_identity(old_identity,new_identity)
method escape (line 72) | def escape(js)
method check_for_console (line 76) | def check_for_console(data)
FILE: lib/analytical/modules/crazy_egg.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class CrazyEgg (line 3) | class CrazyEgg
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/gauges.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Gauges (line 3) | class Gauges
method initialize (line 6) | def initialize(options={})
method track (line 11) | def track(*args)
method init_javascript (line 15) | def init_javascript(location)
FILE: lib/analytical/modules/google.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Google (line 3) | class Google
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method track (line 34) | def track(*args)
method event (line 38) | def event(name, *args)
method custom_event (line 45) | def custom_event(category, action, opt_label=nil, opt_value=nil)
method set (line 64) | def set(data)
method add_trans (line 87) | def add_trans(order_id, affiliation=nil, total=nil, tax=nil, shipp...
method add_item (line 108) | def add_item(order_id, sku, name, category, price, quantity)
method track_trans (line 116) | def track_trans
FILE: lib/analytical/modules/google_optimizer.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class GoogleOptimizer (line 3) | class GoogleOptimizer
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method conversion (line 43) | def conversion(*args)
FILE: lib/analytical/modules/google_universal.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class GoogleUniversal (line 3) | class GoogleUniversal
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method event (line 30) | def event(name, *args)
FILE: lib/analytical/modules/hubspot.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Hubspot (line 3) | class Hubspot
method initialize (line 6) | def initialize(options={})
method init_javascript (line 12) | def init_javascript(location)
method check_hub_id (line 31) | def check_hub_id
FILE: lib/analytical/modules/kiss_metrics.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class KissMetrics (line 3) | class KissMetrics
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method identify (line 30) | def identify(id, *args)
method event (line 36) | def event(name, *args)
method set (line 41) | def set(data)
method alias_identity (line 46) | def alias_identity(old_identity, new_identity)
method check_js_url_key (line 52) | def check_js_url_key
FILE: lib/analytical/modules/loopfuse.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Loopfuse (line 3) | class Loopfuse
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/microsoft_ads.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class MicrosoftAds (line 3) | class MicrosoftAds
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method event (line 35) | def event(name, *args)
FILE: lib/analytical/modules/mixpanel.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Mixpanel (line 3) | class Mixpanel
method initialize (line 6) | def initialize(options={})
method queue (line 12) | def queue(*args)
method init_javascript (line 29) | def init_javascript(location)
method track (line 72) | def track(*args)
method set (line 86) | def set(properties)
method identify (line 90) | def identify(id, *args)
method alias_identity (line 101) | def alias_identity(_, new_identity)
method event (line 105) | def event(name, attributes = {})
method person (line 109) | def person(attributes = {})
method revenue (line 113) | def revenue(charge, attributes = {})
FILE: lib/analytical/modules/mouseflow.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Mouseflow (line 3) | class Mouseflow
method initialize (line 6) | def initialize(options={})
method init_javascript (line 12) | def init_javascript(location)
method check_js_url (line 31) | def check_js_url
FILE: lib/analytical/modules/optimizely.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Optimizely (line 3) | class Optimizely
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/performancing.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Performancing (line 3) | class Performancing
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/quantcast.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Quantcast (line 3) | class Quantcast
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
FILE: lib/analytical/modules/reinvigorate.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class Reinvigorate (line 3) | class Reinvigorate
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method identify (line 24) | def identify(id, *args)
method context (line 29) | def context(data)
method track (line 40) | def track(data, *args)
FILE: lib/analytical/modules/segment_io.rb
type Analytical (line 1) | module Analytical
type Modules (line 2) | module Modules
class SegmentIo (line 3) | class SegmentIo
method initialize (line 6) | def initialize(options={})
method init_javascript (line 11) | def init_javascript(location)
method track (line 23) | def track(*args)
method identify (line 31) | def identify(id, attributes = {})
method event (line 35) | def event(name, attributes = {})
FILE: lib/analytical/rails/engine.rb
type Analytical (line 2) | module Analytical
type Rails (line 3) | module Rails
class Engine (line 4) | class Engine < ::Rails::Engine
FILE: lib/analytical/session_command_store.rb
type Analytical (line 1) | module Analytical
class SessionCommandStore (line 2) | class SessionCommandStore
method initialize (line 5) | def initialize(session, module_key, initial_list=nil)
method assign (line 12) | def assign(v)
method commands (line 16) | def commands
method commands= (line 19) | def commands=(v)
method flush (line 23) | def flush
method method_missing (line 28) | def method_missing(method, *args, &block)
method ensure_session_setup! (line 34) | def ensure_session_setup!(initial_list=nil)
FILE: spec/analytical/bot_detector_spec.rb
class DummyForBotDetector (line 4) | class DummyForBotDetector
FILE: spec/analytical/modules/base_spec.rb
class BaseApiDummy (line 5) | class BaseApiDummy
FILE: spec/analytical_spec.rb
class DummyForInit (line 6) | class DummyForInit
method helper_method (line 16) | def self.helper_method(*a); end
method request (line 17) | def request
method analytical_modules (line 43) | def analytical_modules
class DummyForInit (line 42) | class DummyForInit
method helper_method (line 16) | def self.helper_method(*a); end
method request (line 17) | def request
method analytical_modules (line 43) | def analytical_modules
Condensed preview — 213 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (738K chars).
[
{
"path": ".document",
"chars": 60,
"preview": "README.rdoc\nlib/**/*.rb\nbin/*\nfeatures/**/*.feature\nLICENSE\n"
},
{
"path": ".gitignore",
"chars": 178,
"preview": "## MAC OS\n.DS_Store\n\n## TEXTMATE\n*.tmproj\ntmtags\n\n## EMACS\n*~\n\\#*\n.\\#*\n\n## VIM\n*.swp\n\n## PROJECT::GENERAL\ncoverage\nrdoc\n"
},
{
"path": ".rspec",
"chars": 10,
"preview": "--colour\n\n"
},
{
"path": ".rvmrc",
"chars": 2513,
"preview": "#!/usr/bin/env bash\n\n# This is an RVM Project .rvmrc file, used to automatically load the ruby\n# development environment"
},
{
"path": "CHANGELOG.md",
"chars": 949,
"preview": "# Analytical Changelog\n\n## 3.0.12\n\n* Fixed version checking so it works with Rails 3.2\n* Fixed example configuration in "
},
{
"path": "Gemfile",
"chars": 259,
"preview": "source :rubygems\n\ngroup :development, :test do\n gem 'rails', '3.0.9'\n gem 'activesupport'\n gem 'activemodel'\n gem 'r"
},
{
"path": "Guardfile",
"chars": 299,
"preview": "# A sample Guardfile\n# More info at http://github.com/guard/guard#readme\n\nguard 'rspec', :version => 1 do\n watch(/^spec"
},
{
"path": "LICENSE",
"chars": 1056,
"preview": "Copyright (c) 2009 Joshua Krall\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this so"
},
{
"path": "README.rdoc",
"chars": 7327,
"preview": "= Analytical\n\nGem for managing multiple analytics services in your rails app.\n\n{<img src=\"https://secure.travis-ci.org/j"
},
{
"path": "Rakefile",
"chars": 1254,
"preview": "require 'rubygems'\nrequire 'rake'\n\nbegin\n require 'jeweler'\n Jeweler::Tasks.new do |gem|\n gem.name = \"analytical\"\n "
},
{
"path": "VERSION",
"chars": 6,
"preview": "3.0.12"
},
{
"path": "analytical.gemspec",
"chars": 4488,
"preview": "# Generated by jeweler\n# DO NOT EDIT THIS FILE DIRECTLY\n# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspe"
},
{
"path": "app/views/application/_analytical_javascript.html.erb",
"chars": 353,
"preview": "<script type=\"text/javascript\">\nvar Analytical = {\n track: function(page) {\n<%= raw analytical.now.track('__PAGE__').gs"
},
{
"path": "example/.gitignore",
"chars": 40,
"preview": ".bundle\ndb/*.sqlite3\nlog/*.log\ntmp/**/*\n"
},
{
"path": "example/rails2.3/Gemfile",
"chars": 570,
"preview": "source 'http://rubygems.org'\n\ngem 'rails', '~> 2.3.0'\n\n# Bundle edge Rails instead:\n# gem 'rails', :git => 'git://github"
},
{
"path": "example/rails2.3/README",
"chars": 10011,
"preview": "== Welcome to Rails\n\nRails is a web-application framework that includes everything needed to create \ndatabase-backed web"
},
{
"path": "example/rails2.3/Rakefile",
"chars": 307,
"preview": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they wil"
},
{
"path": "example/rails2.3/app/controllers/application_controller.rb",
"chars": 214,
"preview": "class ApplicationController < ActionController::Base\n helper :all\n protect_from_forgery\n\n analytical :modules=>[:cons"
},
{
"path": "example/rails2.3/app/controllers/page_controller.rb",
"chars": 302,
"preview": "class PageController < ApplicationController\n def index\n end\n\n def test_a\n end\n\n def test_b\n analytical.clicky.t"
},
{
"path": "example/rails2.3/app/helpers/application_helper.rb",
"chars": 115,
"preview": "# Methods added to this helper will be available to all templates in the application.\nmodule ApplicationHelper\nend\n"
},
{
"path": "example/rails2.3/app/views/layouts/application.html.erb",
"chars": 360,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>Example</title>\n <%= stylesheet_link_tag :all %>\n <%= javascript_include_tag :d"
},
{
"path": "example/rails2.3/app/views/page/index.html.erb",
"chars": 154,
"preview": "<h1>Page#index</h1>\n<p>\n\t<%= link_to 'A', '/page/test_a' %><br />\n\t<%= link_to 'B', '/page/test_b' %><br />\n\t<%= link_to"
},
{
"path": "example/rails2.3/app/views/page/test_a.html.erb",
"chars": 379,
"preview": "<% analytical.track 'track in view A' %>\n<% analytical.event 'Something Important', {:some=>'data'} %>\n<h1>Page#test_a</"
},
{
"path": "example/rails2.3/app/views/page/test_b.html.erb",
"chars": 267,
"preview": "<h1>Page#test_b</h1>\n<p>\n\t<%= link_to 'A', '/page/test_a' %><br />\n\t<%= link_to 'C', '/page/test_c' %><br />\n\t<%= link_t"
},
{
"path": "example/rails2.3/config/boot.rb",
"chars": 2895,
"preview": "# Don't change this file!\n# Configure your app in config/environment.rb and config/environments/*.rb\n\nRAILS_ROOT = \"#{Fi"
},
{
"path": "example/rails2.3/config/database.yml",
"chars": 538,
"preview": "# SQLite version 3.x\n# gem install sqlite3-ruby (not necessary on OS X Leopard)\ndevelopment:\n adapter: sqlite3\n data"
},
{
"path": "example/rails2.3/config/environment.rb",
"chars": 1980,
"preview": "# Be sure to restart your server when you modify this file\n\n# Specifies gem version of Rails to use when vendor/rails is"
},
{
"path": "example/rails2.3/config/environments/development.rb",
"chars": 747,
"preview": "# Settings specified here will take precedence over those in config/environment.rb\n\n# In the development environment you"
},
{
"path": "example/rails2.3/config/environments/production.rb",
"chars": 1011,
"preview": "# Settings specified here will take precedence over those in config/environment.rb\n\n# The production environment is mean"
},
{
"path": "example/rails2.3/config/environments/test.rb",
"chars": 1311,
"preview": "# Settings specified here will take precedence over those in config/environment.rb\n\n# The test environment is used exclu"
},
{
"path": "example/rails2.3/config/initializers/backtrace_silencers.rb",
"chars": 404,
"preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
},
{
"path": "example/rails2.3/config/initializers/cookie_verification_secret.rb",
"chars": 505,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying the integrity of signed coo"
},
{
"path": "example/rails2.3/config/initializers/inflections.rb",
"chars": 377,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format \n# (a"
},
{
"path": "example/rails2.3/config/initializers/mime_types.rb",
"chars": 205,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::"
},
{
"path": "example/rails2.3/config/initializers/new_rails_defaults.rb",
"chars": 833,
"preview": "# Be sure to restart your server when you modify this file.\n\n# These settings change the behavior of Rails 2 apps and wi"
},
{
"path": "example/rails2.3/config/initializers/session_store.rb",
"chars": 800,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying cookie session data integri"
},
{
"path": "example/rails2.3/config/locales/en.yml",
"chars": 212,
"preview": "# Sample localization file for English. Add more files in this directory for other locales.\n# See http://github.com/sven"
},
{
"path": "example/rails2.3/config/routes.rb",
"chars": 1906,
"preview": "ActionController::Routing::Routes.draw do |map|\n # The priority is based upon order of creation: first created -> highe"
},
{
"path": "example/rails2.3/db/development.sqlite3",
"chars": 0,
"preview": ""
},
{
"path": "example/rails2.3/db/seeds.rb",
"chars": 356,
"preview": "# This file should contain all the record creation needed to seed the database with its default values.\n# The data can t"
},
{
"path": "example/rails2.3/doc/README_FOR_APP",
"chars": 211,
"preview": "Use this README file to introduce your application and point to useful places in the API for learning more.\nRun \"rake do"
},
{
"path": "example/rails2.3/public/404.html",
"chars": 947,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transition"
},
{
"path": "example/rails2.3/public/422.html",
"chars": 930,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transition"
},
{
"path": "example/rails2.3/public/500.html",
"chars": 948,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transition"
},
{
"path": "example/rails2.3/public/javascripts/application.js",
"chars": 148,
"preview": "// Place your application-specific JavaScript functions and classes here\n// This file is automatically included by javas"
},
{
"path": "example/rails2.3/public/javascripts/controls.js",
"chars": 34716,
"preview": "// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)\n// (c) 2005-2008 Ivan Kr"
},
{
"path": "example/rails2.3/public/javascripts/dragdrop.js",
"chars": 31103,
"preview": "// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)\n// (c) 2005-2008 Sammi W"
},
{
"path": "example/rails2.3/public/javascripts/effects.js",
"chars": 38675,
"preview": "// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)\n// Contributors:\n// Justin Palmer"
},
{
"path": "example/rails2.3/public/javascripts/prototype.js",
"chars": 129738,
"preview": "/* Prototype JavaScript framework, version 1.6.0.3\n * (c) 2005-2008 Sam Stephenson\n *\n * Prototype is freely distribu"
},
{
"path": "example/rails2.3/public/robots.txt",
"chars": 204,
"preview": "# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file\n#\n# To ban all spide"
},
{
"path": "example/rails2.3/script/about",
"chars": 159,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\n$LOAD_PATH.unshift \"#{RAILTIES_PATH}/builti"
},
{
"path": "example/rails2.3/script/console",
"chars": 104,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/console'\n"
},
{
"path": "example/rails2.3/script/dbconsole",
"chars": 106,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/dbconsole'\n"
},
{
"path": "example/rails2.3/script/destroy",
"chars": 104,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/destroy'\n"
},
{
"path": "example/rails2.3/script/generate",
"chars": 105,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/generate'\n"
},
{
"path": "example/rails2.3/script/performance/benchmarker",
"chars": 123,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../../config/boot', __FILE__)\nrequire 'commands/performance/benchmarke"
},
{
"path": "example/rails2.3/script/performance/profiler",
"chars": 120,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../../config/boot', __FILE__)\nrequire 'commands/performance/profiler'\n"
},
{
"path": "example/rails2.3/script/plugin",
"chars": 103,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/plugin'\n"
},
{
"path": "example/rails2.3/script/runner",
"chars": 103,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/runner'\n"
},
{
"path": "example/rails2.3/script/server",
"chars": 103,
"preview": "#!/usr/bin/env ruby\nrequire File.expand_path('../../config/boot', __FILE__)\nrequire 'commands/server'\n"
},
{
"path": "example/rails2.3/test/performance/browsing_test.rb",
"chars": 225,
"preview": "require 'test_helper'\nrequire 'performance_test_help'\n\n# Profiling results for each test method are written to tmp/perfo"
},
{
"path": "example/rails2.3/test/test_helper.rb",
"chars": 1800,
"preview": "ENV[\"RAILS_ENV\"] = \"test\"\nrequire File.expand_path(File.dirname(__FILE__) + \"/../config/environment\")\nrequire 'test_help"
},
{
"path": "example/rails3/Gemfile",
"chars": 570,
"preview": "source 'http://rubygems.org'\n\ngem 'rails', '~> 3.0.0'\n\n# Bundle edge Rails instead:\n# gem 'rails', :git => 'git://github"
},
{
"path": "example/rails3/README",
"chars": 10008,
"preview": "== Welcome to Rails\n\nRails is a web-application framework that includes everything needed to create \ndatabase-backed web"
},
{
"path": "example/rails3/Rakefile",
"chars": 314,
"preview": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they wil"
},
{
"path": "example/rails3/app/controllers/application_controller.rb",
"chars": 223,
"preview": "class ApplicationController < ActionController::Base\n protect_from_forgery\n layout 'application'\n\n analytical :module"
},
{
"path": "example/rails3/app/controllers/page_controller.rb",
"chars": 302,
"preview": "class PageController < ApplicationController\n def index\n end\n\n def test_a\n end\n\n def test_b\n analytical.clicky.t"
},
{
"path": "example/rails3/app/helpers/application_helper.rb",
"chars": 29,
"preview": "module ApplicationHelper\nend\n"
},
{
"path": "example/rails3/app/helpers/page_helper.rb",
"chars": 22,
"preview": "module PageHelper\nend\n"
},
{
"path": "example/rails3/app/views/layouts/application.html.erb",
"chars": 395,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>Example</title>\n <%= stylesheet_link_tag :all %>\n <%= javascript_include_tag :d"
},
{
"path": "example/rails3/app/views/page/index.html.erb",
"chars": 154,
"preview": "<h1>Page#index</h1>\n<p>\n\t<%= link_to 'A', '/page/test_a' %><br />\n\t<%= link_to 'B', '/page/test_b' %><br />\n\t<%= link_to"
},
{
"path": "example/rails3/app/views/page/test_a.html.erb",
"chars": 379,
"preview": "<% analytical.track 'track in view A' %>\n<% analytical.event 'Something Important', {:some=>'data'} %>\n<h1>Page#test_a</"
},
{
"path": "example/rails3/app/views/page/test_b.html.erb",
"chars": 267,
"preview": "<h1>Page#test_b</h1>\n<p>\n\t<%= link_to 'A', '/page/test_a' %><br />\n\t<%= link_to 'C', '/page/test_c' %><br />\n\t<%= link_t"
},
{
"path": "example/rails3/config/analytical.yml",
"chars": 555,
"preview": "google:\n key: google_12345\nclicky:\n key: clicky_12345\nkiss_metrics:\n js_url_key: //doug1izaerwt3.cloudfront.net/kiss_"
},
{
"path": "example/rails3/config/application.rb",
"chars": 2013,
"preview": "require File.expand_path('../boot', __FILE__)\n\nrequire 'rails/all'\n\n# If you have a Gemfile, require the gems listed the"
},
{
"path": "example/rails3/config/boot.rb",
"chars": 156,
"preview": "require 'rubygems'\n# Set up gems listed in the Gemfile.\nif File.exist?(File.expand_path('../../Gemfile', __FILE__))\n re"
},
{
"path": "example/rails3/config/database.yml",
"chars": 538,
"preview": "# SQLite version 3.x\n# gem install sqlite3-ruby (not necessary on OS X Leopard)\ndevelopment:\n adapter: sqlite3\n data"
},
{
"path": "example/rails3/config/environment.rb",
"chars": 195,
"preview": "# Load the rails application\nrequire File.expand_path('../application', __FILE__)\n\n# Initialize the rails application\nEx"
},
{
"path": "example/rails3/config/environments/development.rb",
"chars": 820,
"preview": "Example::Application.configure do\n # Settings specified here will take precedence over those in config/environment.rb\n\n"
},
{
"path": "example/rails3/config/environments/production.rb",
"chars": 1479,
"preview": "Example::Application.configure do\n # Settings specified here will take precedence over those in config/environment.rb\n\n"
},
{
"path": "example/rails3/config/environments/test.rb",
"chars": 1420,
"preview": "Example::Application.configure do\n # Settings specified here will take precedence over those in config/environment.rb\n\n"
},
{
"path": "example/rails3/config/initializers/backtrace_silencers.rb",
"chars": 402,
"preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
},
{
"path": "example/rails3/config/initializers/inflections.rb",
"chars": 377,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format \n# (a"
},
{
"path": "example/rails3/config/initializers/mime_types.rb",
"chars": 205,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::"
},
{
"path": "example/rails3/config/initializers/secret_token.rb",
"chars": 496,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying the integrity of signed coo"
},
{
"path": "example/rails3/config/initializers/session_store.rb",
"chars": 401,
"preview": "# Be sure to restart your server when you modify this file.\n\nRails.application.config.session_store :cookie_store, :key "
},
{
"path": "example/rails3/config/locales/en.yml",
"chars": 213,
"preview": "# Sample localization file for English. Add more files in this directory for other locales.\n# See http://github.com/sven"
},
{
"path": "example/rails3/config/routes.rb",
"chars": 1867,
"preview": "Example::Application.routes.draw do |map|\n get \"page/index\"\n get \"page/test_a\"\n get \"page/test_b\"\n get \"page/test_c\""
},
{
"path": "example/rails3/config.ru",
"chars": 157,
"preview": "# This file is used by Rack-based servers to start the application.\n\nrequire ::File.expand_path('../config/environment',"
},
{
"path": "example/rails3/db/development.sqlite3",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3/db/production.sqlite3",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3/db/seeds.rb",
"chars": 353,
"preview": "# This file should contain all the record creation needed to seed the database with its default values.\n# The data can t"
},
{
"path": "example/rails3/doc/README_FOR_APP",
"chars": 211,
"preview": "Use this README file to introduce your application and point to useful places in the API for learning more.\nRun \"rake do"
},
{
"path": "example/rails3/lib/tasks/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3/public/404.html",
"chars": 728,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>The page you were looking for doesn't exist (404)</title>\n <style type=\"text/css"
},
{
"path": "example/rails3/public/422.html",
"chars": 711,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>The change you wanted was rejected (422)</title>\n <style type=\"text/css\">\n bo"
},
{
"path": "example/rails3/public/500.html",
"chars": 728,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>We're sorry, but something went wrong (500)</title>\n <style type=\"text/css\">\n "
},
{
"path": "example/rails3/public/javascripts/application.js",
"chars": 148,
"preview": "// Place your application-specific JavaScript functions and classes here\n// This file is automatically included by javas"
},
{
"path": "example/rails3/public/javascripts/controls.js",
"chars": 34787,
"preview": "// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009\n\n// Copyright (c) 2005-2009 Thomas Fuchs (http://s"
},
{
"path": "example/rails3/public/javascripts/dragdrop.js",
"chars": 31056,
"preview": "// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009\n\n// Copyright (c) 2005-2009 Thomas Fuchs (http://s"
},
{
"path": "example/rails3/public/javascripts/effects.js",
"chars": 38471,
"preview": "// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009\n\n// Copyright (c) 2005-2009 Thomas Fuchs (http://sc"
},
{
"path": "example/rails3/public/javascripts/prototype.js",
"chars": 139854,
"preview": "/* Prototype JavaScript framework, version 1.6.1\n * (c) 2005-2009 Sam Stephenson\n *\n * Prototype is freely distributa"
},
{
"path": "example/rails3/public/javascripts/rails.js",
"chars": 3811,
"preview": "document.observe(\"dom:loaded\", function() {\n function handleRemote(element) {\n var method, url, params;\n\n if (ele"
},
{
"path": "example/rails3/public/robots.txt",
"chars": 204,
"preview": "# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file\n#\n# To ban all spide"
},
{
"path": "example/rails3/public/stylesheets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3/script/rails",
"chars": 387,
"preview": "#!/usr/bin/env ruby\n# This command will automatically be run when you run \"rails\" with Rails 3 gems installed from the r"
},
{
"path": "example/rails3/test/functional/page_controller_test.rb",
"chars": 325,
"preview": "require 'test_helper'\n\nclass PageControllerTest < ActionController::TestCase\n test \"should get index\" do\n get :index"
},
{
"path": "example/rails3/test/performance/browsing_test.rb",
"chars": 229,
"preview": "require 'test_helper'\nrequire 'rails/performance_test_help'\n\n# Profiling results for each test method are written to tmp"
},
{
"path": "example/rails3/test/test_helper.rb",
"chars": 454,
"preview": "ENV[\"RAILS_ENV\"] = \"test\"\nrequire File.expand_path('../../config/environment', __FILE__)\nrequire 'rails/test_help'\n\nclas"
},
{
"path": "example/rails3/test/unit/helpers/page_helper_test.rb",
"chars": 71,
"preview": "require 'test_helper'\n\nclass PageHelperTest < ActionView::TestCase\nend\n"
},
{
"path": "example/rails3/vendor/plugins/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/Gemfile",
"chars": 551,
"preview": "source 'http://rubygems.org'\n\ngem 'rails', '3.1.0'\n\n# Bundle edge Rails instead:\n# gem 'rails', :git => 'git://githu"
},
{
"path": "example/rails3.1/README",
"chars": 9208,
"preview": "== Welcome to Rails\n\nRails is a web-application framework that includes everything needed to create\ndatabase-backed web "
},
{
"path": "example/rails3.1/Rakefile",
"chars": 272,
"preview": "#!/usr/bin/env rake\n# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistran"
},
{
"path": "example/rails3.1/app/assets/javascripts/application.js",
"chars": 463,
"preview": "// This is a manifest file that'll be compiled into including all the files listed below.\n// Add new JavaScript/Coffee c"
},
{
"path": "example/rails3.1/app/assets/stylesheets/application.css",
"chars": 350,
"preview": "/*\n * This is a manifest file that'll automatically include all the stylesheets available in this directory\n * and any s"
},
{
"path": "example/rails3.1/app/controllers/application_controller.rb",
"chars": 200,
"preview": "class ApplicationController < ActionController::Base\n protect_from_forgery\n\n analytical :modules=>[:console, :google, "
},
{
"path": "example/rails3.1/app/controllers/page_controller.rb",
"chars": 302,
"preview": "class PageController < ApplicationController\n def index\n end\n\n def test_a\n end\n\n def test_b\n analytical.clicky.t"
},
{
"path": "example/rails3.1/app/helpers/application_helper.rb",
"chars": 29,
"preview": "module ApplicationHelper\nend\n"
},
{
"path": "example/rails3.1/app/mailers/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/app/models/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/app/views/layouts/application.html.erb",
"chars": 395,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>Example</title>\n <%= stylesheet_link_tag :all %>\n <%= javascript_include_tag :d"
},
{
"path": "example/rails3.1/app/views/page/index.html.erb",
"chars": 154,
"preview": "<h1>Page#index</h1>\n<p>\n\t<%= link_to 'A', '/page/test_a' %><br />\n\t<%= link_to 'B', '/page/test_b' %><br />\n\t<%= link_to"
},
{
"path": "example/rails3.1/app/views/page/test_a.html.erb",
"chars": 379,
"preview": "<% analytical.track 'track in view A' %>\n<% analytical.event 'Something Important', {:some=>'data'} %>\n<h1>Page#test_a</"
},
{
"path": "example/rails3.1/app/views/page/test_b.html.erb",
"chars": 267,
"preview": "<h1>Page#test_b</h1>\n<p>\n\t<%= link_to 'A', '/page/test_a' %><br />\n\t<%= link_to 'C', '/page/test_c' %><br />\n\t<%= link_t"
},
{
"path": "example/rails3.1/config/application.rb",
"chars": 2044,
"preview": "require File.expand_path('../boot', __FILE__)\n\nrequire 'rails/all'\n\nif defined?(Bundler)\n # If you precompile assets be"
},
{
"path": "example/rails3.1/config/boot.rb",
"chars": 191,
"preview": "require 'rubygems'\n\n# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __F"
},
{
"path": "example/rails3.1/config/database.yml",
"chars": 576,
"preview": "# SQLite version 3.x\n# gem install sqlite3\n#\n# Ensure the SQLite 3 gem is defined in your Gemfile\n# gem 'sqlite3'\n"
},
{
"path": "example/rails3.1/config/environment.rb",
"chars": 151,
"preview": "# Load the rails application\nrequire File.expand_path('../application', __FILE__)\n\n# Initialize the rails application\nEx"
},
{
"path": "example/rails3.1/config/environments/development.rb",
"chars": 1072,
"preview": "Example::Application.configure do\n # Settings specified here will take precedence over those in config/application.rb\n\n"
},
{
"path": "example/rails3.1/config/environments/production.rb",
"chars": 2155,
"preview": "Example::Application.configure do\n # Settings specified here will take precedence over those in config/application.rb\n\n"
},
{
"path": "example/rails3.1/config/environments/test.rb",
"chars": 1812,
"preview": "Example::Application.configure do\n # Settings specified here will take precedence over those in config/application.rb\n\n"
},
{
"path": "example/rails3.1/config/initializers/backtrace_silencers.rb",
"chars": 404,
"preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
},
{
"path": "example/rails3.1/config/initializers/inflections.rb",
"chars": 376,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format\n# (al"
},
{
"path": "example/rails3.1/config/initializers/mime_types.rb",
"chars": 205,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::"
},
{
"path": "example/rails3.1/config/initializers/secret_token.rb",
"chars": 498,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying the integrity of signed coo"
},
{
"path": "example/rails3.1/config/initializers/session_store.rb",
"chars": 416,
"preview": "# Be sure to restart your server when you modify this file.\n\nExample::Application.config.session_store :cookie_store, :k"
},
{
"path": "example/rails3.1/config/initializers/wrap_parameters.rb",
"chars": 468,
"preview": "# Be sure to restart your server when you modify this file.\n#\n# This file contains settings for ActionController::Params"
},
{
"path": "example/rails3.1/config/locales/en.yml",
"chars": 214,
"preview": "# Sample localization file for English. Add more files in this directory for other locales.\n# See https://github.com/sve"
},
{
"path": "example/rails3.1/config/routes.rb",
"chars": 2003,
"preview": "Example::Application.routes.draw do\n get \"page/index\"\n get \"page/test_a\"\n get \"page/test_b\"\n get \"page/test_c\"\n\n # "
},
{
"path": "example/rails3.1/config.ru",
"chars": 157,
"preview": "# This file is used by Rack-based servers to start the application.\n\nrequire ::File.expand_path('../config/environment',"
},
{
"path": "example/rails3.1/db/development.sqlite3",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/db/seeds.rb",
"chars": 355,
"preview": "# This file should contain all the record creation needed to seed the database with its default values.\n# The data can t"
},
{
"path": "example/rails3.1/doc/README_FOR_APP",
"chars": 211,
"preview": "Use this README file to introduce your application and point to useful places in the API for learning more.\nRun \"rake do"
},
{
"path": "example/rails3.1/lib/assets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/lib/tasks/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/public/404.html",
"chars": 728,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>The page you were looking for doesn't exist (404)</title>\n <style type=\"text/css"
},
{
"path": "example/rails3.1/public/422.html",
"chars": 711,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>The change you wanted was rejected (422)</title>\n <style type=\"text/css\">\n bo"
},
{
"path": "example/rails3.1/public/500.html",
"chars": 728,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>We're sorry, but something went wrong (500)</title>\n <style type=\"text/css\">\n "
},
{
"path": "example/rails3.1/public/robots.txt",
"chars": 204,
"preview": "# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file\n#\n# To ban all spide"
},
{
"path": "example/rails3.1/script/rails",
"chars": 295,
"preview": "#!/usr/bin/env ruby\n# This command will automatically be run when you run \"rails\" with Rails 3 gems installed from the r"
},
{
"path": "example/rails3.1/test/fixtures/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/test/functional/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/test/integration/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/test/performance/browsing_test.rb",
"chars": 370,
"preview": "require 'test_helper'\nrequire 'rails/performance_test_help'\n\nclass BrowsingTest < ActionDispatch::PerformanceTest\n # Re"
},
{
"path": "example/rails3.1/test/test_helper.rb",
"chars": 454,
"preview": "ENV[\"RAILS_ENV\"] = \"test\"\nrequire File.expand_path('../../config/environment', __FILE__)\nrequire 'rails/test_help'\n\nclas"
},
{
"path": "example/rails3.1/test/unit/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/vendor/assets/stylesheets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "example/rails3.1/vendor/plugins/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "lib/analytical/api.rb",
"chars": 4429,
"preview": "module Analytical\n module Modules\n class DummyModule\n include Analytical::Modules::Base\n def method_missin"
},
{
"path": "lib/analytical/bot_detector.rb",
"chars": 1592,
"preview": "module Analytical\n module BotDetector\n\n def analytical_is_robot?(user_agent, whitelist = [])\n whitelist = Array"
},
{
"path": "lib/analytical/command_store.rb",
"chars": 357,
"preview": "module Analytical\n class CommandStore\n attr_accessor :commands\n\n def initialize(initial_list=nil)\n @commands"
},
{
"path": "lib/analytical/modules/adroll.rb",
"chars": 1220,
"preview": "module Analytical\n module Modules\n class Adroll\n include Analytical::Modules::Base\n\n def initialize(option"
},
{
"path": "lib/analytical/modules/adwords.rb",
"chars": 2523,
"preview": "module Analytical\n module Modules\n class Adwords\n include Analytical::Modules::Base\n\n def initialize(optio"
},
{
"path": "lib/analytical/modules/base.rb",
"chars": 2889,
"preview": "module Analytical\n module Modules\n module Base\n attr_reader :tracking_command_location, :options, :initialized\n"
},
{
"path": "lib/analytical/modules/chartbeat.rb",
"chars": 1738,
"preview": "module Analytical\n module Modules\n class Chartbeat\n include Analytical::Modules::Base\n\n def initialize(opt"
},
{
"path": "lib/analytical/modules/click_tale.rb",
"chars": 1584,
"preview": "module Analytical\n module Modules\n class ClickTale\n include Analytical::Modules::Base\n\n def initialize(opt"
},
{
"path": "lib/analytical/modules/clicky.rb",
"chars": 1731,
"preview": "module Analytical\n module Modules\n class Clicky\n include Analytical::Modules::Base\n\n def initialize(option"
},
{
"path": "lib/analytical/modules/comscore.rb",
"chars": 846,
"preview": "module Analytical\n module Modules\n class Comscore\n include Analytical::Modules::Base\n\n def initialize(opti"
},
{
"path": "lib/analytical/modules/console.rb",
"chars": 2022,
"preview": "module Analytical\n module Modules\n class Console\n include Analytical::Modules::Base\n\n def initialize(optio"
},
{
"path": "lib/analytical/modules/crazy_egg.rb",
"chars": 619,
"preview": "module Analytical\n module Modules\n class CrazyEgg\n include Analytical::Modules::Base\n\n def initialize(opti"
},
{
"path": "lib/analytical/modules/gauges.rb",
"chars": 1030,
"preview": "module Analytical\n module Modules\n class Gauges\n include Analytical::Modules::Base\n\n def initialize(option"
},
{
"path": "lib/analytical/modules/google.rb",
"chars": 5686,
"preview": "module Analytical\n module Modules\n class Google\n include Analytical::Modules::Base\n\n def initialize(option"
},
{
"path": "lib/analytical/modules/google_optimizer.rb",
"chars": 2522,
"preview": "module Analytical\n module Modules\n class GoogleOptimizer\n include Analytical::Modules::Base\n\n def initiali"
},
{
"path": "lib/analytical/modules/google_universal.rb",
"chars": 1188,
"preview": "module Analytical\n module Modules\n class GoogleUniversal\n include Analytical::Modules::Base\n\n def initiali"
},
{
"path": "lib/analytical/modules/hubspot.rb",
"chars": 1131,
"preview": "module Analytical\n module Modules\n class Hubspot\n include Analytical::Modules::Base\n\n def initialize(optio"
},
{
"path": "lib/analytical/modules/kiss_metrics.rb",
"chars": 1681,
"preview": "module Analytical\n module Modules\n class KissMetrics\n include Analytical::Modules::Base\n\n def initialize(o"
},
{
"path": "lib/analytical/modules/loopfuse.rb",
"chars": 880,
"preview": "module Analytical\n module Modules\n class Loopfuse\n include Analytical::Modules::Base\n\n def initialize(opti"
},
{
"path": "lib/analytical/modules/microsoft_ads.rb",
"chars": 1899,
"preview": "module Analytical\n module Modules\n class MicrosoftAds\n include Analytical::Modules::Base\n\n def initialize("
},
{
"path": "lib/analytical/modules/mixpanel.rb",
"chars": 5169,
"preview": "module Analytical\n module Modules\n class Mixpanel\n include Analytical::Modules::Base\n\n def initialize(opti"
},
{
"path": "lib/analytical/modules/mouseflow.rb",
"chars": 1037,
"preview": "module Analytical\n module Modules\n class Mouseflow\n include Analytical::Modules::Base\n\n def initialize(opt"
},
{
"path": "lib/analytical/modules/optimizely.rb",
"chars": 623,
"preview": "module Analytical\n module Modules\n class Optimizely\n include Analytical::Modules::Base\n\n def initialize(op"
},
{
"path": "lib/analytical/modules/performancing.rb",
"chars": 1078,
"preview": "module Analytical\n module Modules\n class Performancing\n include Analytical::Modules::Base\n\n def initialize"
},
{
"path": "lib/analytical/modules/quantcast.rb",
"chars": 1545,
"preview": "module Analytical\n module Modules\n class Quantcast\n include Analytical::Modules::Base\n\n def initialize(opt"
},
{
"path": "lib/analytical/modules/reinvigorate.rb",
"chars": 1262,
"preview": "module Analytical\n module Modules\n class Reinvigorate\n include Analytical::Modules::Base\n\n def initialize("
},
{
"path": "lib/analytical/modules/segment_io.rb",
"chars": 1721,
"preview": "module Analytical\n module Modules\n class SegmentIo\n include Analytical::Modules::Base\n\n def initialize(opt"
},
{
"path": "lib/analytical/rails/engine.rb",
"chars": 150,
"preview": "if defined?(::Rails::Engine)\n module Analytical\n module Rails\n class Engine < ::Rails::Engine\n # auto wi"
},
{
"path": "lib/analytical/session_command_store.rb",
"chars": 802,
"preview": "module Analytical\n class SessionCommandStore\n attr_reader :session, :module_key\n\n def initialize(session, module_"
},
{
"path": "lib/analytical.rb",
"chars": 2719,
"preview": "require File.dirname(__FILE__)+'/analytical/rails/engine'\nrequire File.dirname(__FILE__)+'/analytical/modules/base'\nDir."
},
{
"path": "rails/init.rb",
"chars": 21,
"preview": "require 'analytical'\n"
},
{
"path": "spec/analytical/api_spec.rb",
"chars": 7786,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')\n\ndescribe \"Analytical::Api\" do\n\n describe 'on init"
},
{
"path": "spec/analytical/bot_detector_spec.rb",
"chars": 822,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')\n\ndescribe \"Analytical::BotDetector\" do\n class Dumm"
},
{
"path": "spec/analytical/command_store_spec.rb",
"chars": 941,
"preview": "require 'spec_helper'\n\ndescribe Analytical::CommandStore do\n \n describe 'when behaving exactly like an array' do\n i"
},
{
"path": "spec/analytical/modules/adroll_spec.rb",
"chars": 1082,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe \"Analytical::Modules::Adroll\" do\n bef"
},
{
"path": "spec/analytical/modules/adwords_spec.rb",
"chars": 3055,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe \"Analytical::Modules::Adwords\" do\n be"
},
{
"path": "spec/analytical/modules/base_spec.rb",
"chars": 4534,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe Analytical::Modules::Base do\n\n class "
},
{
"path": "spec/analytical/modules/chartbeat_spec.rb",
"chars": 1272,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe \"Analytical::Modules::Chartbeat\" do\n "
},
{
"path": "spec/analytical/modules/clicky_spec.rb",
"chars": 1895,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe \"Analytical::Modules::Clicky\" do\n bef"
},
{
"path": "spec/analytical/modules/comscore_spec.rb",
"chars": 1074,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe \"Analytical::Modules::Comscore\" do\n b"
},
{
"path": "spec/analytical/modules/gauges_spec.rb",
"chars": 1388,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')\n\ndescribe \"Analytical::Modules::Gauges\" do\n bef"
}
]
// ... and 13 more files (download for full content)
About this extraction
This page contains the full source code of the jkrall/analytical GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 213 files (682.5 KB), approximately 179.2k tokens, and a symbol index with 468 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.