diff options
Diffstat (limited to 'vendor/plugins')
125 files changed, 4 insertions, 12475 deletions
diff --git a/vendor/plugins/active_record_base_without_table/lib/active_record/base_without_table.rb b/vendor/plugins/active_record_base_without_table/lib/active_record/base_without_table.rb index 12cb05e02..14e9f935d 100644 --- a/vendor/plugins/active_record_base_without_table/lib/active_record/base_without_table.rb +++ b/vendor/plugins/active_record_base_without_table/lib/active_record/base_without_table.rb @@ -13,7 +13,8 @@ module ActiveRecord def column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
- reset_column_information
+ # FIXME: Disabled temporarily during Rails 3 upgrade
+ # reset_column_information
end
# Do not reset @columns
diff --git a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb index 374fcd65b..e03c5e4aa 100644 --- a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb +++ b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb @@ -92,7 +92,7 @@ module ActsAsXapian raise "Set RAILS_ENV, so acts_as_xapian can find the right Xapian database" if not environment # check for a config file - config_file = RAILS_ROOT + "/config/xapian.yml" + config_file = Rails.root.to_s + "/config/xapian.yml" @@config = File.exists?(config_file) ? YAML.load_file(config_file)[environment] : {} # figure out where the DBs should go @@ -758,7 +758,7 @@ module ActsAsXapian else values = [] for locale in self.translations.map{|x| x.locale} - self.class.with_locale(locale) do + I18n.with_locale(locale) do values << single_xapian_value(field, type=type) end end diff --git a/vendor/plugins/globalize2/LICENSE b/vendor/plugins/globalize2/LICENSE deleted file mode 100644 index 94a6b8160..000000000 --- a/vendor/plugins/globalize2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2008, 2009 Joshua Harvey - -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.
\ No newline at end of file diff --git a/vendor/plugins/globalize2/README.textile b/vendor/plugins/globalize2/README.textile deleted file mode 100644 index e47e9bf37..000000000 --- a/vendor/plugins/globalize2/README.textile +++ /dev/null @@ -1,86 +0,0 @@ -h1. Globalize2 - -Globalize2 is the successor of Globalize for Rails. - -It is compatible with and builds on the new "I18n api in Ruby on Rails":http://guides.rubyonrails.org/i18n.html. and adds model translations to ActiveRecord. - -Globalize2 is much more lightweight and compatible than its predecessor was. Model translations in Globalize2 use default ActiveRecord features and do not limit any ActiveRecord functionality any more. - -h2. Requirements - -ActiveRecord -I18n - -(or Rails > 2.2) - -h2. Installation - -To install Globalize2 with its default setup just use: - -<pre><code> -script/plugin install git://github.com/joshmh/globalize2.git -</code></pre> - -h2. Model translations - -Model translations allow you to translate your models' attribute values. E.g. - -<pre><code> -class Post < ActiveRecord::Base - translates :title, :text -end -</code></pre> - -Allows you to values for the attributes :title and :text per locale: - -<pre><code> -I18n.locale = :en -post.title # => Globalize2 rocks! - -I18n.locale = :he -post.title # => גלובאלייז2 שולט! -</code></pre> - -In order to make this work, you'll need to add the appropriate translation tables. Globalize2 comes with a handy helper method to help you do this. It's called @create_translation_table!@. Here's an example: - -<pre><code> -class CreatePosts < ActiveRecord::Migration - def self.up - create_table :posts do |t| - t.timestamps - end - Post.create_translation_table! :title => :string, :text => :text - end - def self.down - drop_table :posts - Post.drop_translation_table! - end -end -</code></pre> - -Note that the ActiveRecord model @Post@ must already exist and have a @translates@ directive listing the translated fields. - -h2. Migration from Globalize - -See this script by Tomasz Stachewicz: http://gist.github.com/120867 - -h2. Changes since Globalize2 v0.1.0 - -* The association globalize_translations has been renamed to translations. - -h2. Alternative Solutions - -* "Veger's fork":http://github.com/veger/globalize2 - uses default AR schema for the default locale, delegates to the translations table for other locales only -* "TranslatableColumns":http://github.com/iain/translatable_columns - have multiple languages of the same attribute in a model (Iain Hecker) -* "localized_record":http://github.com/glennpow/localized_record - allows records to have localized attributes without any modifications to the database (Glenn Powell) -* "model_translations":http://github.com/janne/model_translations - Minimal implementation of Globalize2 style model translations (Jan Andersson) - -h2. Related solutions - -* "globalize2_versioning":http://github.com/joshmh/globalize2_versioning - acts_as_versioned style versioning for Globalize2 (Joshua Harvey) -* "i18n_multi_locales_validations":http://github.com/ZenCocoon/i18n_multi_locales_validations - multi-locales attributes validations to validates attributes from Globalize2 translations models (Sébastien Grosjean) -* "Globalize2 Demo App":http://github.com/svenfuchs/globalize2-demo - demo application for Globalize2 (Sven Fuchs)</li> -* "migrate_from_globalize1":http://gist.github.com/120867 - migrate model translations from Globalize1 to Globalize2 (Tomasz Stachewicz)</li> -* "easy_globalize2_accessors":http://github.com/astropanic/easy_globalize2_accessors - easily access (read and write) globalize2-translated fields (astropanic, Tomasz Stachewicz)</li> -* "globalize2-easy-translate":http://github.com/bsamman/globalize2-easy-translate - adds methods to easily access or set translated attributes to your model (bsamman)</li> -* "batch_translations":http://github.com/alvarezrilla/batch_translations - allow saving multiple Globalize2 translations in the same request (Jose Alvarez Rilla)</li> diff --git a/vendor/plugins/globalize2/Rakefile b/vendor/plugins/globalize2/Rakefile deleted file mode 100644 index bc35dada4..000000000 --- a/vendor/plugins/globalize2/Rakefile +++ /dev/null @@ -1,39 +0,0 @@ -require 'rake' -require 'rake/testtask' -require 'rake/rdoctask' - -desc 'Default: run unit tests.' -task :default => :test - -desc 'Test the globalize2 plugin.' -Rake::TestTask.new(:test) do |t| - t.libs << 'lib' - t.pattern = 'test/**/*_test.rb' - t.verbose = true -end - -desc 'Generate documentation for the globalize2 plugin.' -Rake::RDocTask.new(:rdoc) do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = 'Globalize2' - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.rdoc_files.include('README') - rdoc.rdoc_files.include('lib/**/*.rb') -end - -begin - require 'jeweler' - Jeweler::Tasks.new do |s| - s.name = "globalize2" - s.summary = "Rails I18n: de-facto standard library for ActiveRecord data translation" - s.description = "Rails I18n: de-facto standard library for ActiveRecord data translation" - s.email = "joshmh@gmail.com" - s.homepage = "http://github.com/joshmh/globalize2" - # s.rubyforge_project = '' - s.authors = ["Sven Fuchs, Joshua Harvey, Clemens Kofler, John-Paul Bader"] - # s.add_development_dependency '' - end - Jeweler::GemcutterTasks.new -rescue LoadError - puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" -end diff --git a/vendor/plugins/globalize2/VERSION b/vendor/plugins/globalize2/VERSION deleted file mode 100644 index 0c62199f1..000000000 --- a/vendor/plugins/globalize2/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.2.1 diff --git a/vendor/plugins/globalize2/generators/db_backend.rb b/vendor/plugins/globalize2/generators/db_backend.rb deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/plugins/globalize2/generators/db_backend.rb +++ /dev/null diff --git a/vendor/plugins/globalize2/generators/templates/db_backend_migration.rb b/vendor/plugins/globalize2/generators/templates/db_backend_migration.rb deleted file mode 100644 index 0f0261113..000000000 --- a/vendor/plugins/globalize2/generators/templates/db_backend_migration.rb +++ /dev/null @@ -1,25 +0,0 @@ -class ActsAsTaggableMigration < ActiveRecord::Migration - def self.up - create_table :globalize_translations do |t| - t.string :locale, :null => false - t.string :key, :null => false - t.string :translation - t.timestamps - end - -# TODO: FINISH DOING MIGRATION -- stopped in the middle - - create_table :globalize_translations_map do |t| - t.string :key, :null => false - t.integer :translation_id, :null => false - end - - add_index :taggings, :tag_id - add_index :taggings, [:taggable_id, :taggable_type] - end - - def self.down - drop_table :globalize_translations - drop_table :tags - end -end diff --git a/vendor/plugins/globalize2/globalize2.gemspec b/vendor/plugins/globalize2/globalize2.gemspec deleted file mode 100644 index 89021115e..000000000 --- a/vendor/plugins/globalize2/globalize2.gemspec +++ /dev/null @@ -1,81 +0,0 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command -# -*- encoding: utf-8 -*- - -Gem::Specification.new do |s| - s.name = %q{globalize2} - s.version = "0.2.0" - - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Sven Fuchs, Joshua Harvey, Clemens Kofler, John-Paul Bader"] - s.date = %q{2010-04-22} - s.description = %q{Rails I18n: de-facto standard library for ActiveRecord data translation} - s.email = %q{joshmh@gmail.com} - s.extra_rdoc_files = [ - "LICENSE", - "README.textile" - ] - s.files = [ - ".gitignore", - "LICENSE", - "README.textile", - "Rakefile", - "VERSION", - "generators/db_backend.rb", - "generators/templates/db_backend_migration.rb", - "globalize2.gemspec", - "init.rb", - "lib/globalize.rb", - "lib/globalize/active_record.rb", - "lib/globalize/active_record/adapter.rb", - "lib/globalize/active_record/attributes.rb", - "lib/globalize/active_record/migration.rb", - "lib/i18n/missing_translations_log_handler.rb", - "lib/i18n/missing_translations_raise_handler.rb", - "test/active_record/fallbacks_test.rb", - "test/active_record/migration_test.rb", - "test/active_record/sti_translated_test.rb", - "test/active_record/translates_test.rb", - "test/active_record/translation_class_test.rb", - "test/active_record/validation_tests.rb", - "test/active_record_test.rb", - "test/all.rb", - "test/data/models.rb", - "test/data/no_globalize_schema.rb", - "test/data/schema.rb", - "test/i18n/missing_translations_test.rb", - "test/test_helper.rb" - ] - s.homepage = %q{http://github.com/joshmh/globalize2} - s.rdoc_options = ["--charset=UTF-8"] - s.require_paths = ["lib"] - s.rubygems_version = %q{1.3.6} - s.summary = %q{Rails I18n: de-facto standard library for ActiveRecord data translation} - s.test_files = [ - "test/active_record/fallbacks_test.rb", - "test/active_record/migration_test.rb", - "test/active_record/sti_translated_test.rb", - "test/active_record/translates_test.rb", - "test/active_record/translation_class_test.rb", - "test/active_record/validation_tests.rb", - "test/active_record_test.rb", - "test/all.rb", - "test/data/models.rb", - "test/data/no_globalize_schema.rb", - "test/data/schema.rb", - "test/i18n/missing_translations_test.rb", - "test/test_helper.rb" - ] - - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 - - if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then - else - end - else - end -end - diff --git a/vendor/plugins/globalize2/init.rb b/vendor/plugins/globalize2/init.rb deleted file mode 100644 index a4089251b..000000000 --- a/vendor/plugins/globalize2/init.rb +++ /dev/null @@ -1 +0,0 @@ -require 'globalize' diff --git a/vendor/plugins/globalize2/lib/globalize.rb b/vendor/plugins/globalize2/lib/globalize.rb deleted file mode 100644 index 67c1878ec..000000000 --- a/vendor/plugins/globalize2/lib/globalize.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Globalize - autoload :ActiveRecord, 'globalize/active_record' - - class << self - def fallbacks? - I18n.respond_to?(:fallbacks) - end - - def fallbacks(locale) - fallbacks? ? I18n.fallbacks[locale] : [locale.to_sym] - end - end -end - -ActiveRecord::Base.send(:include, Globalize::ActiveRecord) diff --git a/vendor/plugins/globalize2/lib/globalize/active_record.rb b/vendor/plugins/globalize2/lib/globalize/active_record.rb deleted file mode 100644 index 3095bfe28..000000000 --- a/vendor/plugins/globalize2/lib/globalize/active_record.rb +++ /dev/null @@ -1,238 +0,0 @@ -module Globalize - class MigrationError < StandardError; end - class MigrationMissingTranslatedField < MigrationError; end - class BadMigrationFieldType < MigrationError; end - - module ActiveRecord - autoload :Adapter, 'globalize/active_record/adapter' - autoload :Attributes, 'globalize/active_record/attributes' - autoload :Migration, 'globalize/active_record/migration' - - def self.included(base) - base.extend ActMacro - end - - class << self - def build_translation_class(target, options) - options[:table_name] ||= "#{target.table_name.singularize}_translations" - - klass = target.const_defined?(:Translation) ? - target.const_get(:Translation) : - target.const_set(:Translation, Class.new(::ActiveRecord::Base)) - - klass.class_eval do - set_table_name(options[:table_name]) - belongs_to target.name.underscore.gsub('/', '_') - def locale; read_attribute(:locale).to_sym; end - def locale=(locale); write_attribute(:locale, locale.to_s); end - end - - klass - end - end - - module ActMacro - def locale - (defined?(@@locale) && @@locale) - end - - def locale=(locale) - @@locale = locale - end - - def translates(*attr_names) - return if translates? - options = attr_names.extract_options! - - class_inheritable_accessor :translation_class, :translated_attribute_names - class_inheritable_writer :required_attributes - self.translation_class = ActiveRecord.build_translation_class(self, options) - self.translated_attribute_names = attr_names.map(&:to_sym) - - include InstanceMethods - extend ClassMethods, Migration - - after_save :save_translations! - ActiveSupport::Deprecation.silence do - # Silence the warning that :class_name is deprecated and will be - # removed in Rails 3, since it clutters up e.g. test output, and - # there is nothing obvious that we can replace it with in Rails 2. - - has_many :translations, :class_name => translation_class.name, - :foreign_key => class_name.foreign_key, - :dependent => :delete_all, - :extend => HasManyExtensions - end - - named_scope :with_translations, lambda { |locale| - conditions = required_attributes.map do |attribute| - "#{quoted_translation_table_name}.#{attribute} IS NOT NULL" - end - conditions << "#{quoted_translation_table_name}.locale = ?" - { :include => :translations, :conditions => [conditions.join(' AND '), locale] } - } - - attr_names.each { |attr_name| translated_attr_accessor(attr_name) } - end - - def translates? - included_modules.include?(InstanceMethods) - end - end - - module HasManyExtensions - def by_locale(locale) - first(:conditions => { :locale => locale.to_s }) - end - - def by_locales(locales) - all(:conditions => { :locale => locales.map(&:to_s) }) - end - end - - module ClassMethods - delegate :set_translation_table_name, :to => :translation_class - - def with_locale(locale) - begin - previous_locale, self.locale = self.locale, locale - result = yield - ensure - self.locale = previous_locale - end - result - end - - def translation_table_name - translation_class.table_name - end - - def quoted_translation_table_name - translation_class.quoted_table_name - end - - def required_attributes - @required_attributes ||= reflect_on_all_validations.select do |validation| - validation.macro == :validates_presence_of && translated_attribute_names.include?(validation.name) - end.map(&:name) - end - - def respond_to?(method, *args, &block) - method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) || super - end - - def method_missing(method, *args) - if method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) - find_first_by_translated_attr_and_locales($1, args.first) - elsif method.to_s =~ /^find_all_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) - find_all_by_translated_attr_and_locales($1, args.first) - else - super - end - end - - protected - - def find_first_by_translated_attr_and_locales(name, value) - query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)" - locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s) - find( - :first, - :joins => :translations, - :conditions => [query, value, locales], - :readonly => false - ) - end - - def find_all_by_translated_attr_and_locales(name, value) - query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)" - locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s) - find( - :all, - :joins => :translations, - :conditions => [query, value, locales], - :readonly => false - ) - end - - def translated_attr_accessor(name) - define_method "#{name}=", lambda { |value| - globalize.write(self.class.locale || I18n.locale, name, value) - self[name] = value - } - define_method name, lambda { |*args| - globalize.fetch(args.first || self.class.locale || I18n.locale, name) - } - alias_method "#{name}_before_type_cast", name - end - - def translated_attr_name(name) - "#{translation_class.table_name}.#{name}" - end - end - - module InstanceMethods - def globalize - @globalize ||= Adapter.new self - end - - def attributes - self.attribute_names.inject({}) do |attrs, name| - attrs[name] = read_attribute(name) || - (globalize.fetch(I18n.locale, name) rescue nil) - attrs - end - end - - def attributes=(attributes, *args) - if attributes.respond_to?(:delete) && locale = attributes.delete(:locale) - self.class.with_locale(locale) { super } - else - super - end - end - - def attribute_names - translated_attribute_names.map(&:to_s) + super - end - - def available_locales - translations.scoped(:select => 'DISTINCT locale').map(&:locale) - end - - def translated_locales - translations.map(&:locale) - end - - def translated_attributes - translated_attribute_names.inject({}) do |attributes, name| - attributes.merge(name => send(name)) - end - end - - def set_translations(options) - options.keys.each do |locale| - translation = translations.find_by_locale(locale.to_s) || - translations.build(:locale => locale.to_s) - translation.update_attributes!(options[locale]) - end - end - - def reload(options = nil) - translated_attribute_names.each { |name| @attributes.delete(name.to_s) } - globalize.reset - super(options) - end - - protected - - def save_translations! - globalize.save_translations! - end - end - end -end - -def globalize_write(name, value) - globalize.write(self.class.locale || I18n.locale, name, value) -end diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb b/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb deleted file mode 100644 index 12f89ec01..000000000 --- a/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb +++ /dev/null @@ -1,80 +0,0 @@ -module Globalize - module ActiveRecord - class Adapter - # The cache caches attributes that already were looked up for read access. - # The stash keeps track of new or changed values that need to be saved. - attr_reader :record, :cache, :stash - - def initialize(record) - @record = record - @cache = Attributes.new - @stash = Attributes.new - end - - def fetch(locale, attr_name) - cache.contains?(locale, attr_name) ? - cache.read(locale, attr_name) : - cache.write(locale, attr_name, fetch_attribute(locale, attr_name)) - end - - def write(locale, attr_name, value) - stash.write(locale, attr_name, value) - cache.write(locale, attr_name, value) - end - - def save_translations! - stash.each do |locale, attrs| - translation = record.translations.find_or_initialize_by_locale(locale.to_s) - attrs.each { |attr_name, value| translation[attr_name] = value } - translation.save! - end - stash.clear - end - - def reset - cache.clear - # stash.clear - end - - protected - - def fetch_translation(locale) - locale = locale.to_sym - record.translations.loaded? ? record.translations.detect { |t| t.locale == locale } : - record.translations.by_locale(locale) - end - - def fetch_translations(locale) - # only query if not already included with :include => translations - record.translations.loaded? ? record.translations : - record.translations.by_locales(Globalize.fallbacks(locale)) - end - - def fetch_attribute(locale, attr_name) - translations = fetch_translations(locale) - value, requested_locale = nil, locale - - Globalize.fallbacks(locale).each do |fallback| - translation = translations.detect { |t| t.locale == fallback } - value = translation && translation.send(attr_name) - locale = fallback && break if value - end - - set_metadata(value, :locale => locale, :requested_locale => requested_locale) - value - end - - def set_metadata(object, metadata) - if object.respond_to?(:translation_metadata) - object.translation_metadata.merge!(meta_data) - end - end - - def translation_metadata_accessor(object) - return if obj.respond_to?(:translation_metadata) - class << object; attr_accessor :translation_metadata end - object.translation_metadata ||= {} - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb b/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb deleted file mode 100644 index 7bd923ce2..000000000 --- a/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb +++ /dev/null @@ -1,25 +0,0 @@ -# Helper class for storing values per locale. Used by Globalize::Adapter -# to stash and cache attribute values. -module Globalize - module ActiveRecord - class Attributes < Hash - def [](locale) - locale = locale.to_sym - self[locale] = {} unless has_key?(locale) - self.fetch(locale) - end - - def contains?(locale, attr_name) - self[locale].has_key?(attr_name) - end - - def read(locale, attr_name) - self[locale][attr_name] - end - - def write(locale, attr_name, value) - self[locale][attr_name] = value - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb b/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb deleted file mode 100644 index fa63aed8c..000000000 --- a/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb +++ /dev/null @@ -1,44 +0,0 @@ -module Globalize - module ActiveRecord - module Migration - def create_translation_table!(fields) - translated_attribute_names.each do |f| - raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f] - end - - fields.each do |name, type| - if translated_attribute_names.include?(name) && ![:string, :text].include?(type) - raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text" - end - end - - self.connection.create_table(translation_table_name) do |t| - t.references table_name.sub(/^#{table_name_prefix}/, "").singularize - t.string :locale - fields.each do |name, type| - t.column name, type - end - t.timestamps - end - - self.connection.add_index( - translation_table_name, - "#{table_name.sub(/^#{table_name_prefix}/, "").singularize}_id", - :name => translation_index_name - ) - end - - def translation_index_name - require 'digest/sha1' - # FIXME what's the max size of an index name? - index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id" - index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}" - end - - def drop_translation_table! - self.connection.remove_index(translation_table_name, :name => translation_index_name) rescue nil - self.connection.drop_table(translation_table_name) - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb b/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb deleted file mode 100644 index 24c10890a..000000000 --- a/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb +++ /dev/null @@ -1,41 +0,0 @@ -# A simple exception handler that behaves like the default exception handler -# but additionally logs missing translations to a given log. -# -# Useful for identifying missing translations during testing. -# -# E.g. -# -# require 'globalize/i18n/missing_translations_log_handler' -# I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER -# I18n.exception_handler = :missing_translations_log_handler -# -# To set up a different log file: -# -# logger = Logger.new("#{RAILS_ROOT}/log/missing_translations.log") -# I18n.missing_translations_logger = logger - -module I18n - @@missing_translations_logger = nil - - class << self - def missing_translations_logger - @@missing_translations_logger ||= begin - require 'logger' unless defined?(Logger) - Logger.new(STDOUT) - end - end - - def missing_translations_logger=(logger) - @@missing_translations_logger = logger - end - - def missing_translations_log_handler(exception, locale, key, options) - if MissingTranslationData === exception - missing_translations_logger.warn(exception.message) - return exception.message - else - raise exception - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb b/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb deleted file mode 100644 index 18237b151..000000000 --- a/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb +++ /dev/null @@ -1,25 +0,0 @@ -# A simple exception handler that behaves like the default exception handler -# but also raises on missing translations. -# -# Useful for identifying missing translations during testing. -# -# E.g. -# -# require 'globalize/i18n/missing_translations_raise_handler' -# I18n.exception_handler = :missing_translations_raise_handler -module I18n - class << self - def missing_translations_raise_handler(exception, locale, key, options) - raise exception - end - end -end - -I18n.exception_handler = :missing_translations_raise_handler - -ActionView::Helpers::TranslationHelper.module_eval do - def translate(key, options = {}) - I18n.translate(key, options) - end - alias :t :translate -end diff --git a/vendor/plugins/globalize2/test/active_record/fallbacks_test.rb b/vendor/plugins/globalize2/test/active_record/fallbacks_test.rb deleted file mode 100644 index 449ec8b2b..000000000 --- a/vendor/plugins/globalize2/test/active_record/fallbacks_test.rb +++ /dev/null @@ -1,102 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../data/models') - -if I18n.respond_to?(:fallbacks) - class TranslatedTest < ActiveSupport::TestCase - def setup - I18n.locale = :'en-US' - I18n.fallbacks.clear - reset_db! - ActiveRecord::Base.locale = nil - end - - def teardown - I18n.fallbacks.clear - end - - test "keeping one field in new locale when other field is changed" do - I18n.fallbacks.map 'de-DE' => [ 'en-US' ] - post = Post.create :subject => 'foo' - I18n.locale = 'de-DE' - post.content = 'bar' - assert_equal 'foo', post.subject - end - - test "modifying non-required field in a new locale" do - I18n.fallbacks.map 'de-DE' => [ 'en-US' ] - post = Post.create :subject => 'foo' - I18n.locale = 'de-DE' - post.content = 'bar' - assert post.save - end - - test "resolves a simple fallback" do - I18n.locale = 'de-DE' - post = Post.create :subject => 'foo' - I18n.locale = 'de' - post.subject = 'baz' - post.content = 'bar' - post.save - I18n.locale = 'de-DE' - assert_equal 'foo', post.subject - assert_equal 'bar', post.content - end - - test "resolves a simple fallback without reloading" do - I18n.locale = 'de-DE' - post = Post.new :subject => 'foo' - I18n.locale = 'de' - post.subject = 'baz' - post.content = 'bar' - I18n.locale = 'de-DE' - assert_equal 'foo', post.subject - assert_equal 'bar', post.content - end - - test "resolves a complex fallback without reloading" do - I18n.fallbacks.map 'de' => %w(en he) - I18n.locale = 'de' - post = Post.new - I18n.locale = 'en' - post.subject = 'foo' - I18n.locale = 'he' - post.subject = 'baz' - post.content = 'bar' - I18n.locale = 'de' - assert_equal 'foo', post.subject - assert_equal 'bar', post.content - end - - test 'fallbacks with lots of locale switching' do - I18n.fallbacks.map :'de-DE' => [ :'en-US' ] - post = Post.create :subject => 'foo' - - I18n.locale = :'de-DE' - assert_equal 'foo', post.subject - - I18n.locale = :'en-US' - post.update_attribute :subject, 'bar' - - I18n.locale = :'de-DE' - assert_equal 'bar', post.subject - end - - test 'fallbacks with lots of locale switching' do - I18n.fallbacks.map :'de-DE' => [ :'en-US' ] - child = Child.create :content => 'foo' - - I18n.locale = :'de-DE' - assert_equal 'foo', child.content - - I18n.locale = :'en-US' - child.update_attribute :content, 'bar' - - I18n.locale = :'de-DE' - assert_equal 'bar', child.content - end - end -end - -# TODO should validate_presence_of take fallbacks into account? maybe we need -# an extra validation call, or more options for validate_presence_of. - diff --git a/vendor/plugins/globalize2/test/active_record/migration_test.rb b/vendor/plugins/globalize2/test/active_record/migration_test.rb deleted file mode 100644 index 359d811f0..000000000 --- a/vendor/plugins/globalize2/test/active_record/migration_test.rb +++ /dev/null @@ -1,118 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../data/models') - -class MigrationTest < ActiveSupport::TestCase - def setup - reset_db! - Post.drop_translation_table! - end - - test 'globalize table added' do - assert !Post.connection.table_exists?(:post_translations) - assert !Post.connection.index_exists?(:post_translations, :post_id) - - Post.create_translation_table!(:subject => :string, :content => :text) - assert Post.connection.table_exists?(:post_translations) - assert Post.connection.index_exists?(:post_translations, :post_id) - - columns = Post.connection.columns(:post_translations) - assert locale = columns.detect { |c| c.name == 'locale' } - assert_equal :string, locale.type - assert subject = columns.detect { |c| c.name == 'subject' } - assert_equal :string, subject.type - assert content = columns.detect { |c| c.name == 'content' } - assert_equal :text, content.type - assert post_id = columns.detect { |c| c.name == 'post_id' } - assert_equal :integer, post_id.type - assert created_at = columns.detect { |c| c.name == 'created_at' } - assert_equal :datetime, created_at.type - assert updated_at = columns.detect { |c| c.name == 'updated_at' } - assert_equal :datetime, updated_at.type - end - - test 'globalize table dropped' do - assert !Post.connection.table_exists?( :post_translations ) - assert !Post.connection.index_exists?( :post_translations, :post_id ) - Post.create_translation_table! :subject => :string, :content => :text - assert Post.connection.table_exists?( :post_translations ) - assert Post.connection.index_exists?( :post_translations, :post_id ) - Post.drop_translation_table! - assert !Post.connection.table_exists?( :post_translations ) - assert !Post.connection.index_exists?( :post_translations, :post_id ) - end - - test 'exception on missing field inputs' do - assert_raise Globalize::MigrationMissingTranslatedField do - Post.create_translation_table! :content => :text - end - end - - test 'exception on bad input type' do - assert_raise Globalize::BadMigrationFieldType do - Post.create_translation_table! :subject => :string, :content => :integer - end - end - - test "exception on bad input type isn't raised for untranslated fields" do - assert_nothing_raised do - Post.create_translation_table! :subject => :string, :content => :string, :views_count => :integer - end - end - - test 'create_translation_table! should not be called on non-translated models' do - assert_raise NoMethodError do - Blog.create_translation_table! :name => :string - end - end - - test 'drop_translation_table! should not be called on non-translated models' do - assert_raise NoMethodError do - Blog.drop_translation_table! - end - end - - test "translation_index_name returns a readable index name when it's not longer than 50 characters" do - assert_equal 'index_post_translations_on_post_id', Post.send(:translation_index_name) - end - - test "translation_index_name returns a hashed index name when it's longer than 50 characters" do - class UltraLongModelNameWithoutProper < ActiveRecord::Base - translates :foo - end - name = UltraLongModelNameWithoutProper.send(:translation_index_name) - assert_match /^index_[a-z0-9]{40}$/, name - end - - test 'globalize table added when table has long name' do - UltraLongModelNameWithoutProper.create_translation_table!( - :subject => :string, :content => :text - ) - - assert UltraLongModelNameWithoutProper.connection.table_exists?( - :ultra_long_model_name_without_proper_translations - ) - assert UltraLongModelNameWithoutProper.connection.index_exists?( - :ultra_long_model_name_without_proper_translations, - :name => UltraLongModelNameWithoutProper.send( - :translation_index_name - ) - ) - end - - test 'globalize table dropped when table has long name' do - UltraLongModelNameWithoutProper.drop_translation_table! - UltraLongModelNameWithoutProper.create_translation_table!( - :subject => :string, :content => :text - ) - UltraLongModelNameWithoutProper.drop_translation_table! - - assert !UltraLongModelNameWithoutProper.connection.table_exists?( - :ultra_long_model_name_without_proper_translations - ) - assert !UltraLongModelNameWithoutProper.connection.index_exists?( - :ultra_long_model_name_without_proper_translations, - :ultra_long_model_name_without_proper_id - ) - end - -end diff --git a/vendor/plugins/globalize2/test/active_record/sti_translated_test.rb b/vendor/plugins/globalize2/test/active_record/sti_translated_test.rb deleted file mode 100644 index f529b8d6e..000000000 --- a/vendor/plugins/globalize2/test/active_record/sti_translated_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../data/models') - -class StiTranslatedTest < ActiveSupport::TestCase - def setup - I18n.locale = :'en-US' - reset_db! - end - - test "works with simple dynamic finders" do - foo = Child.create :content => 'foo' - Child.create :content => 'bar' - child = Child.find_by_content('foo') - assert_equal foo, child - end - - test 'change attribute on globalized model' do - child = Child.create :content => 'foo' - assert_equal [], child.changed - child.content = 'bar' - assert_equal [ 'content' ], child.changed - child.content = 'baz' - assert_member 'content', child.changed - end - - test 'change attribute on globalized model after locale switching' do - child = Child.create :content => 'foo' - assert_equal [], child.changed - child.content = 'bar' - I18n.locale = :de - assert_equal [ 'content' ], child.changed - end - - test "saves all locales, even after locale switching" do - child = Child.new :content => 'foo' - I18n.locale = 'de-DE' - child.content = 'bar' - I18n.locale = 'he-IL' - child.content = 'baz' - child.save - I18n.locale = 'en-US' - child = Child.first - assert_equal 'foo', child.content - I18n.locale = 'de-DE' - assert_equal 'bar', child.content - I18n.locale = 'he-IL' - assert_equal 'baz', child.content - end -end diff --git a/vendor/plugins/globalize2/test/active_record/translates_test.rb b/vendor/plugins/globalize2/test/active_record/translates_test.rb deleted file mode 100644 index 1831063fb..000000000 --- a/vendor/plugins/globalize2/test/active_record/translates_test.rb +++ /dev/null @@ -1,96 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../data/models') - -class TranslatesTest < ActiveSupport::TestCase - def setup - I18n.locale = nil - ActiveRecord::Base.locale = nil - reset_db! - end - - test 'defines a :locale accessors on ActiveRecord::Base' do - ActiveRecord::Base.locale = :de - assert_equal :de, ActiveRecord::Base.locale - end - - test 'the :locale reader on ActiveRecord::Base does not default to I18n.locale (anymore)' do - I18n.locale = :en - assert_nil ActiveRecord::Base.locale - end - - test 'ActiveRecord::Base.with_locale temporarily sets the given locale and yields the block' do - I18n.locale = :en - post = Post.with_locale(:de) do - Post.create!(:subject => 'Titel', :content => 'Inhalt') - end - assert_nil Post.locale - assert_equal :en, I18n.locale - - I18n.locale = :de - assert_equal 'Titel', post.subject - end - - test 'translation_class returns the Translation class' do - assert_equal Post::Translation, Post.translation_class - end - - test 'defines a has_many association on the model class' do - assert_has_many Post, :translations - end - - test 'defines a scope for retrieving locales that have complete translations' do - post = Post.create!(:subject => 'subject', :content => 'content') - assert_equal [:en], post.translated_locales - end - - test 'sets the given attributes to translated_attribute_names' do - assert_equal [:subject, :content], Post.translated_attribute_names - end - - test 'defines accessors for the translated attributes' do - post = Post.new - assert post.respond_to?(:subject) - assert post.respond_to?(:subject=) - end - - test 'attribute reader without arguments will use the current locale on ActiveRecord::Base or I18n' do - post = Post.with_locale(:de) do - Post.create!(:subject => 'Titel', :content => 'Inhalt') - end - I18n.locale = :de - assert_equal 'Titel', post.subject - - I18n.locale = :en - ActiveRecord::Base.locale = :de - assert_equal 'Titel', post.subject - end - - test 'attribute reader when passed a locale will use the given locale' do - post = Post.with_locale(:de) do - Post.create!(:subject => 'Titel', :content => 'Inhalt') - end - assert_equal 'Titel', post.subject(:de) - end - - test 'attribute reader will use the current locale on ActiveRecord::Base or I18n' do - post = Post.with_locale(:en) do - Post.create!(:subject => 'title', :content => 'content') - end - I18n.locale = :de - post.subject = 'Titel' - assert_equal 'Titel', post.subject - - ActiveRecord::Base.locale = :en - post.subject = 'title' - assert_equal 'title', post.subject - end - - test "find_by_xx records have writable attributes" do - Post.create :subject => "change me" - p = Post.find_by_subject("change me") - p.subject = "changed" - assert_nothing_raised(ActiveRecord::ReadOnlyRecord) do - p.save - end - end -end diff --git a/vendor/plugins/globalize2/test/active_record/translation_class_test.rb b/vendor/plugins/globalize2/test/active_record/translation_class_test.rb deleted file mode 100644 index 1628416d7..000000000 --- a/vendor/plugins/globalize2/test/active_record/translation_class_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../data/models') - -class TranlationClassTest < ActiveSupport::TestCase - def setup - reset_db! - end - - test 'defines a Translation class nested in the model class' do - assert Post.const_defined?(:Translation) - end - - test 'defines a belongs_to association' do - assert_belongs_to Post::Translation, :post - end - - test 'defines a reader for :locale that always returns a symbol' do - post = Post::Translation.new - post.write_attribute('locale', 'de') - assert_equal :de, post.locale - end - - test 'defines a write for :locale that always writes a string' do - post = Post::Translation.new - post.locale = :de - assert_equal 'de', post.read_attribute('locale') - end -end - - diff --git a/vendor/plugins/globalize2/test/active_record/validation_tests.rb b/vendor/plugins/globalize2/test/active_record/validation_tests.rb deleted file mode 100644 index 0148fa384..000000000 --- a/vendor/plugins/globalize2/test/active_record/validation_tests.rb +++ /dev/null @@ -1,75 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require File.expand_path(File.dirname(__FILE__) + '/../data/models') - -class ValidationTest < ActiveSupport::TestCase - def setup - reset_db! - end - - def teardown - Validatee.instance_variable_set(:@validate_callbacks, CallbackChain.new) - end - - test "validates_presence_of" do - Validatee.class_eval { validates_presence_of :string } - assert !Validatee.new.valid? - assert Validatee.new(:string => 'foo').valid? - end - - test "validates_confirmation_of" do - Validatee.class_eval { validates_confirmation_of :string } - assert !Validatee.new(:string => 'foo', :string_confirmation => 'bar').valid? - assert Validatee.new(:string => 'foo', :string_confirmation => 'foo').valid? - end - - test "validates_acceptance_of" do - Validatee.class_eval { validates_acceptance_of :string, :accept => '1' } - assert !Validatee.new(:string => '0').valid? - assert Validatee.new(:string => '1').valid? - end - - test "validates_length_of (:is)" do - Validatee.class_eval { validates_length_of :string, :is => 1 } - assert !Validatee.new(:string => 'aa').valid? - assert Validatee.new(:string => 'a').valid? - end - - test "validates_format_of" do - Validatee.class_eval { validates_format_of :string, :with => /^\d+$/ } - assert !Validatee.new(:string => 'a').valid? - assert Validatee.new(:string => '1').valid? - end - - test "validates_inclusion_of" do - Validatee.class_eval { validates_inclusion_of :string, :in => %(a) } - assert !Validatee.new(:string => 'b').valid? - assert Validatee.new(:string => 'a').valid? - end - - test "validates_exclusion_of" do - Validatee.class_eval { validates_exclusion_of :string, :in => %(b) } - assert !Validatee.new(:string => 'b').valid? - assert Validatee.new(:string => 'a').valid? - end - - test "validates_numericality_of" do - Validatee.class_eval { validates_numericality_of :string } - assert !Validatee.new(:string => 'a').valid? - assert Validatee.new(:string => '1').valid? - end - - # This doesn't pass and Rails' validates_uniqueness_of implementation doesn't - # seem to be extensible easily. One can work around that by either defining - # a custom validation on the Validatee model itself, or by using validates_uniqueness_of - # on Validatee::Translation. - # - # test "validates_uniqueness_of" do - # Validatee.class_eval { validates_uniqueness_of :string } - # Validatee.create!(:string => 'a') - # assert !Validatee.new(:string => 'a').valid? - # assert Validatee.new(:string => 'b').valid? - # end - - # test "validates_associated" do - # end -end
\ No newline at end of file diff --git a/vendor/plugins/globalize2/test/active_record_test.rb b/vendor/plugins/globalize2/test/active_record_test.rb deleted file mode 100644 index 38e247e17..000000000 --- a/vendor/plugins/globalize2/test/active_record_test.rb +++ /dev/null @@ -1,467 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/test_helper') -require File.expand_path(File.dirname(__FILE__) + '/data/models') - -# Higher level tests. - -class ActiveRecordTest < ActiveSupport::TestCase - def setup - I18n.locale = :en - reset_db! - ActiveRecord::Base.locale = nil - end - - def assert_translated(locale, record, names, expected) - I18n.locale = locale - assert_equal Array(expected), Array(names).map { |name| record.send(name) } - end - - test "a translated record has translations" do - assert_equal [], Post.new.translations - end - - test "saves a translated version of the record for each locale" do - post = Post.create(:subject => 'title') - I18n.locale = :de - post.update_attributes(:subject => 'Titel') - - assert_equal 2, post.translations.size - assert_equal %w(de en), post.translations.map(&:locale).map(&:to_s).sort - assert_equal %w(Titel title), post.translations.map(&:subject).sort - end - - test "a translated record has German translations" do - I18n.locale = :de - post = Post.create(:subject => 'foo') - assert_equal 1, post.translations.size - assert_equal [:de], post.translations.map { |t| t.locale } - end - - test "modifiying translated fields while switching locales" do - post = Post.create(:subject => 'title', :content => 'content') - assert_equal %w(title content), [post.subject, post.content] - - I18n.locale = :de - post.subject, post.content = 'Titel', 'Inhalt' - - assert_translated(:de, post, [:subject, :content], %w(Titel Inhalt)) - assert_translated(:en, post, [:subject, :content], %w(title content)) - assert_translated(:de, post, [:subject, :content], %w(Titel Inhalt)) - - post.save - post.reload - - assert_translated(:en, post, [:subject, :content], %w(title content)) - assert_translated(:de, post, [:subject, :content], %w(Titel Inhalt)) - end - - test "attribute writers do return their argument" do - value = Post.new.subject = 'foo' - assert_equal 'foo', value - end - - test "update_attribute succeeds with valid values" do - post = Post.create(:subject => 'foo', :content => 'bar') - post.update_attribute(:subject, 'baz') - assert_equal 'baz', Post.first.subject - end - - test "update_attributes fails with invalid values" do - post = Post.create(:subject => 'foo', :content => 'bar') - assert !post.update_attributes(:subject => '') - assert_not_nil post.reload.attributes['subject'] - assert_equal 'foo', post.subject - end - - test "passing the locale to create uses the given locale" do - post = Post.create(:subject => 'Titel', :content => 'Inhalt', :locale => :de) - assert_equal :en, I18n.locale - assert_nil ActiveRecord::Base.locale - - I18n.locale = :de - assert_equal 'Titel', post.subject - end - - test "passing the locale to attributes= uses the given locale" do - post = Post.create(:subject => 'title', :content => 'content') - post.update_attributes(:subject => 'Titel', :content => 'Inhalt', :locale => :de) - post.reload - - assert_equal :en, I18n.locale - assert_nil ActiveRecord::Base.locale - - assert_equal 'title', post.subject - I18n.locale = :de - assert_equal 'Titel', post.subject - end - - test 'reload works' do - post = Post.create(:subject => 'foo', :content => 'bar') - post.subject = 'baz' - post.reload - assert_equal 'foo', post.subject - end - - test "returns nil if no translations are found (unsaved record)" do - post = Post.new(:subject => 'foo') - assert_equal 'foo', post.subject - assert_nil post.content - end - - test "returns nil if no translations are found (saved record)" do - post = Post.create(:subject => 'foo') - post.reload - assert_equal 'foo', post.subject - assert_nil post.content - end - - test "finds a German post" do - post = Post.create(:subject => 'foo (en)', :content => 'bar') - I18n.locale = :de - post = Post.first - post.subject = 'baz (de)' - post.save - assert_equal 'baz (de)', Post.first.subject - I18n.locale = :en - assert_equal 'foo (en)', Post.first.subject - end - - test "saves an English post and loads correctly" do - post = Post.create(:subject => 'foo', :content => 'bar') - assert post.save - post = Post.first - assert_equal 'foo', post.subject - assert_equal 'bar', post.content - end - - test "returns the value for the correct locale, after locale switching" do - post = Post.create(:subject => 'foo') - I18n.locale = :de - post.subject = 'bar' - post.save - I18n.locale = :en - post = Post.first - assert_equal 'foo', post.subject - I18n.locale = :de - assert_equal 'bar', post.subject - end - - test "returns the value for the correct locale, after locale switching, without saving" do - post = Post.create :subject => 'foo' - I18n.locale = :de - post.subject = 'bar' - I18n.locale = :en - assert_equal 'foo', post.subject - I18n.locale = :de - assert_equal 'bar', post.subject - end - - test "saves all locales, even after locale switching" do - post = Post.new :subject => 'foo' - I18n.locale = :de - post.subject = 'bar' - I18n.locale = :he - post.subject = 'baz' - post.save - I18n.locale = :en - post = Post.first - assert_equal 'foo', post.subject - I18n.locale = :de - assert_equal 'bar', post.subject - I18n.locale = :he - assert_equal 'baz', post.subject - end - - test "works with associations" do - blog = Blog.create - post1 = blog.posts.create(:subject => 'foo') - - I18n.locale = :de - post2 = blog.posts.create(:subject => 'bar') - assert_equal 2, blog.posts.size - - I18n.locale = :en - assert_equal 'foo', blog.posts.first.subject - assert_nil blog.posts.last.subject - - I18n.locale = :de - assert_equal 'bar', blog.posts.last.subject - end - - test "works with simple dynamic finders" do - foo = Post.create(:subject => 'foo') - Post.create(:subject => 'bar') - post = Post.find_by_subject('foo') - assert_equal foo, post - end - - test 'change attribute on globalized model' do - post = Post.create(:subject => 'foo', :content => 'bar') - assert_equal [], post.changed - post.subject = 'baz' - assert_equal ['subject'], post.changed - post.content = 'quux' - assert_member 'subject', post.changed - assert_member 'content', post.changed - end - - test 'change attribute on globalized model after locale switching' do - post = Post.create(:subject => 'foo', :content => 'bar') - assert_equal [], post.changed - post.subject = 'baz' - I18n.locale = :de - assert_equal ['subject'], post.changed - end - - test 'complex writing and stashing' do - post = Post.create(:subject => 'foo', :content => 'bar') - post.subject = nil - assert_nil post.subject - assert !post.valid? - post.subject = 'stashed_foo' - assert_equal 'stashed_foo', post.subject - end - - test 'translated class locale setting' do - assert ActiveRecord::Base.respond_to?(:locale) - assert_equal :en, I18n.locale - assert_nil ActiveRecord::Base.locale - - I18n.locale = :de - assert_equal :de, I18n.locale - assert_nil ActiveRecord::Base.locale - - ActiveRecord::Base.locale = :es - assert_equal :de, I18n.locale - assert_equal :es, ActiveRecord::Base.locale - - I18n.locale = :fr - assert_equal :fr, I18n.locale - assert_equal :es, ActiveRecord::Base.locale - end - - test "untranslated class responds to locale" do - assert Blog.respond_to?(:locale) - end - - test "to ensure locales in different classes are the same" do - ActiveRecord::Base.locale = :de - assert_equal :de, ActiveRecord::Base.locale - assert_equal :de, Parent.locale - - Parent.locale = :es - assert_equal :es, ActiveRecord::Base.locale - assert_equal :es, Parent.locale - end - - test "attribute saving goes by content locale and not global locale" do - ActiveRecord::Base.locale = :de - assert_equal :en, I18n.locale - Post.create :subject => 'foo' - assert_equal :de, Post.first.translations.first.locale - end - - test "attribute loading goes by content locale and not global locale" do - post = Post.create(:subject => 'foo') - assert_nil ActiveRecord::Base.locale - - ActiveRecord::Base.locale = :de - assert_equal :en, I18n.locale - post.update_attribute(:subject, 'foo [de]') - assert_equal 'foo [de]', Post.first.subject - - ActiveRecord::Base.locale = :en - assert_equal 'foo', Post.first.subject - end - - test "access content locale before setting" do - Globalize::ActiveRecord::ActMacro.class_eval "remove_class_variable(:@@locale)" - assert_nothing_raised { ActiveRecord::Base.locale } - end - - test "available_locales" do - Post.locale = :de - post = Post.create(:subject => 'foo') - Post.locale = :es - post.update_attribute(:subject, 'bar') - Post.locale = :fr - post.update_attribute(:subject, 'baz') - assert_equal [:de, :es, :fr], post.available_locales - assert_equal [:de, :es, :fr], Post.first.available_locales - end - - test "saving record correctly after post-save reload" do - reloader = Reloader.create(:content => 'foo') - assert_equal 'foo', reloader.content - end - - test "including translations" do - I18n.locale = :de - Post.create(:subject => "Foo1", :content => "Bar1") - Post.create(:subject => "Foo2", :content => "Bar2") - - class << Post - def translations_included - self.all(:include => :translations) - end - end - - default = Post.all.map { |x| [x.subject, x.content] } - with_include = Post.translations_included.map { |x| [x.subject, x.content] } - assert_equal default, with_include - end - - test "setting multiple translations at once with options hash" do - Post.locale = :de - post = Post.create(:subject => "foo1", :content => "foo1") - Post.locale = :en - post.update_attributes(:subject => "bar1", :content => "bar1") - - options = { :de => {:subject => "foo2", :content => "foo2"}, - :en => {:subject => "bar2", :content => "bar2"} } - post.set_translations options - post.reload - - assert ["bar2", "bar2"], [post.subject, post.content] - Post.locale = :de - assert ["foo2", "foo2"], [post.subject, post.content] - end - - test "setting only one translation with set_translations" do - Post.locale = :de - post = Post.create(:subject => "foo1", :content => "foo1") - Post.locale = :en - post.update_attributes(:subject => "bar1", :content => "bar1") - - options = { :en => { :subject => "bar2", :content => "bar2" } } - post.set_translations options - post.reload - - assert ["bar2", "bar2"], [post.subject, post.content] - Post.locale = :de - assert ["foo1", "foo1"], [post.subject, post.content] - end - - test "setting only selected attributes with set_translations" do - Post.locale = :de - post = Post.create(:subject => "foo1", :content => "foo1") - Post.locale = :en - post.update_attributes(:subject => "bar1", :content => "bar1") - - options = { :de => { :content => "foo2" }, :en => { :subject => "bar2" } } - post.set_translations options - post.reload - - assert ["bar2", "bar1"], [post.subject, post.content] - Post.locale = :de - assert ["foo1", "foo2"], [post.subject, post.content] - end - - test "setting invalid attributes raises ArgumentError" do - Post.locale = :de - post = Post.create(:subject => "foo1", :content => "foo1") - Post.locale = :en - post.update_attributes(:subject => "bar1", :content => "bar1") - - options = { :de => {:fake => "foo2"} } - exception = assert_raise(ActiveRecord::UnknownAttributeError) do - post.set_translations options - end - assert_equal "unknown attribute: fake", exception.message - end - - test "reload accepting find options" do - p = Post.create(:subject => "Foo", :content => "Bar") - assert p.reload(:readonly => true, :lock => true) - assert_raise(ArgumentError) { p.reload(:foo => :bar) } - end - - test "dependent destroy of translation" do - p = Post.create(:subject => "Foo", :content => "Bar") - assert_equal 1, PostTranslation.count - p.destroy - assert_equal 0, PostTranslation.count - end - - test "translating subclass of untranslated comment model" do - translated_comment = TranslatedComment.create(:post => @post) - assert_nothing_raised { translated_comment.translations } - end - - test "modifiying translated comments works as expected" do - I18n.locale = :en - translated_comment = TranslatedComment.create(:post => @post, :content => 'foo') - assert_equal 'foo', translated_comment.content - - I18n.locale = :de - translated_comment.content = 'bar' - assert translated_comment.save - assert_equal 'bar', translated_comment.content - - I18n.locale = :en - assert_equal 'foo', translated_comment.content - - assert_equal 2, translated_comment.translations.size - end - - test "can create a proxy class for a namespaced model" do - assert_nothing_raised do - module Foo - module Bar - class Baz < ActiveRecord::Base - translates :bumm - end - end - end - end - end - - test "attribute translated before type cast" do - Post.locale = :en - post = Post.create(:subject => 'foo', :content => 'bar') - Post.locale = :de - post.update_attribute(:subject, "German foo") - assert_equal 'German foo', post.subject_before_type_cast - Post.locale = :en - assert_equal 'foo', post.subject_before_type_cast - end - - test "don't override existing translation class" do - assert PostTranslation.new.respond_to?(:existing_method) - end - - test "has_many and named scopes work with globalize" do - blog = Blog.create - assert_nothing_raised { blog.posts.foobar } - end - - test "required_attribuets don't include non-translated attributes" do - validations = [ - stub(:name => :name, :macro => :validates_presence_of), - stub(:name => :email, :macro => :validates_presence_of) - ] - User.expects(:reflect_on_all_validations => validations) - assert_equal [:name], User.required_attributes - end - - test "attribute_names returns translated and regular attribute names" do - Post.create :subject => "foo", :content => "bar" - assert_equal Post.last.attribute_names.sort, %w[blog_id content id subject] - end - - test "attributes returns translated and regular attributes" do - Post.create :subject => "foo", :content => "bar" - assert_equal Post.last.attributes.keys.sort, %w[blog_id content id subject] - end - - test "to_xml includes translated fields" do - Post.create :subject => "foo", :content => "bar" - assert Post.last.to_xml =~ /subject/ - assert Post.last.to_xml =~ /content/ - end -end - -# TODO error checking for fields that exist in main table, don't exist in -# proxy table, aren't strings or text -# -# TODO allow finding by translated attributes in conditions? -# TODO generate advanced dynamic finders? diff --git a/vendor/plugins/globalize2/test/all.rb b/vendor/plugins/globalize2/test/all.rb deleted file mode 100644 index ff467a176..000000000 --- a/vendor/plugins/globalize2/test/all.rb +++ /dev/null @@ -1,2 +0,0 @@ -files = Dir[File.dirname(__FILE__) + '/**/*_test.rb'] -files.each { |file| require file }
\ No newline at end of file diff --git a/vendor/plugins/globalize2/test/data/models.rb b/vendor/plugins/globalize2/test/data/models.rb deleted file mode 100644 index 5408d6e23..000000000 --- a/vendor/plugins/globalize2/test/data/models.rb +++ /dev/null @@ -1,56 +0,0 @@ -#require 'ruby2ruby' -#require 'parse_tree' -#require 'parse_tree_extensions' -#require 'pp' - -class PostTranslation < ActiveRecord::Base - def existing_method ; end -end - -class Post < ActiveRecord::Base - translates :subject, :content - validates_presence_of :subject - named_scope :foobar, :conditions => { :title => "foobar" } -end - -class Blog < ActiveRecord::Base - has_many :posts, :order => 'id ASC' -end - -class Parent < ActiveRecord::Base - translates :content -end - -class Child < Parent -end - -class Comment < ActiveRecord::Base - validates_presence_of :content - belongs_to :post -end - -class TranslatedComment < Comment - translates :content -end - -class UltraLongModelNameWithoutProper < ActiveRecord::Base - translates :subject, :content - validates_presence_of :subject -end - -class Reloader < Parent - after_create :do_reload - - def do_reload - reload - end -end - -class Validatee < ActiveRecord::Base - translates :string -end - -class User < ActiveRecord::Base - translates :name - validates_presence_of :name, :email -end diff --git a/vendor/plugins/globalize2/test/data/no_globalize_schema.rb b/vendor/plugins/globalize2/test/data/no_globalize_schema.rb deleted file mode 100644 index 379455ddb..000000000 --- a/vendor/plugins/globalize2/test/data/no_globalize_schema.rb +++ /dev/null @@ -1,11 +0,0 @@ -# This schema creates tables without columns for the translated fields -ActiveRecord::Schema.define do - create_table :blogs, :force => true do |t| - t.string :name - end - - create_table :posts, :force => true do |t| - t.references :blog - end -end - diff --git a/vendor/plugins/globalize2/test/data/schema.rb b/vendor/plugins/globalize2/test/data/schema.rb deleted file mode 100644 index 910dd0855..000000000 --- a/vendor/plugins/globalize2/test/data/schema.rb +++ /dev/null @@ -1,55 +0,0 @@ -ActiveRecord::Schema.define do - create_table :blogs, :force => true do |t| - t.string :description - end - - create_table :posts, :force => true do |t| - t.references :blog - end - - create_table :post_translations, :force => true do |t| - t.string :locale - t.references :post - t.string :subject - t.text :content - end - - create_table :parents, :force => true do |t| - end - - create_table :parent_translations, :force => true do |t| - t.string :locale - t.references :parent - t.text :content - t.string :type - end - - create_table :comments, :force => true do |t| - t.references :post - end - - create_table :comment_translations, :force => true do |t| - t.string :locale - t.references :comment - t.string :subject - t.text :content - end - - create_table :validatees, :force => true do |t| - end - - create_table :validatee_translations, :force => true do |t| - t.string :locale - t.references :validatee - t.string :string - end - - create_table :users, :force => true do |t| - t.string :email - end - - create_table :users_translations, :force => true do |t| - t.references :user - t.string :name - end -end diff --git a/vendor/plugins/globalize2/test/i18n/missing_translations_test.rb b/vendor/plugins/globalize2/test/i18n/missing_translations_test.rb deleted file mode 100644 index 5d0ecd6fc..000000000 --- a/vendor/plugins/globalize2/test/i18n/missing_translations_test.rb +++ /dev/null @@ -1,36 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' -require 'i18n/missing_translations_log_handler' - -class MissingTranslationsTest < ActiveSupport::TestCase - test "defines I18n.missing_translations_logger accessor" do - assert I18n.respond_to?(:missing_translations_logger) - end - - test "defines I18n.missing_translations_logger= writer" do - assert I18n.respond_to?(:missing_translations_logger=) - end -end - -class TestLogger < String - def warn(msg) self.concat msg; end -end - -class LogMissingTranslationsTest < ActiveSupport::TestCase - def setup - @locale, @key, @options = :en, :foo, {} - @exception = I18n::MissingTranslationData.new(@locale, @key, @options) - - @logger = TestLogger.new - I18n.missing_translations_logger = @logger - end - - test "still returns the exception message for MissingTranslationData exceptions" do - result = I18n.send(:missing_translations_log_handler, @exception, @locale, @key, @options) - assert_equal 'translation missing: en, foo', result - end - - test "logs the missing translation to I18n.missing_translations_logger" do - I18n.send(:missing_translations_log_handler, @exception, @locale, @key, @options) - assert_equal 'translation missing: en, foo', @logger - end -end diff --git a/vendor/plugins/globalize2/test/test_helper.rb b/vendor/plugins/globalize2/test/test_helper.rb deleted file mode 100644 index 99a5d3950..000000000 --- a/vendor/plugins/globalize2/test/test_helper.rb +++ /dev/null @@ -1,76 +0,0 @@ -$LOAD_PATH << File.expand_path( File.dirname(__FILE__) + '/../lib' ) - -require 'rubygems' -require 'test/unit' -require 'active_record' -require 'active_support' -require 'active_support/test_case' -require 'mocha' -require 'globalize' -# require 'validation_reflection' - -config = { :adapter => 'sqlite3', :database => ':memory:' } -ActiveRecord::Base.establish_connection(config) - -class ActiveSupport::TestCase - def reset_db!(schema_path = nil) - schema_path ||= File.expand_path(File.dirname(__FILE__) + '/data/schema.rb') - ActiveRecord::Migration.verbose = false - ActiveRecord::Base.silence { load(schema_path) } - end - - def assert_member(item, array) - assert_block "Item #{item} is not in array #{array}" do - array.member?(item) - end - end - - def assert_belongs_to(model, associated) - assert model.reflect_on_all_associations(:belongs_to).detect { |association| - association.name.to_s == associated.to_s - } - end - - def assert_has_many(model, associated) - assert model.reflect_on_all_associations(:has_many).detect { |association| - association.name.to_s == associated.to_s - } - end -end - -module ActiveRecord - module ConnectionAdapters - class AbstractAdapter - def index_exists?(table_name, column_name) - indexes(table_name).any? { |index| index.name == index_name(table_name, column_name) } - end - end - end -end - -# module ActiveRecord -# class BaseWithoutTable < Base -# self.abstract_class = true -# -# def create_or_update -# errors.empty? -# end -# -# class << self -# def columns() -# @columns ||= [] -# end -# -# def column(name, sql_type = nil, default = nil, null = true) -# columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null) -# reset_column_information -# end -# -# # Do not reset @columns -# def reset_column_information -# read_methods.each { |name| undef_method(name) } -# @column_names = @columns_hash = @content_columns = @dynamic_methods_hash = @read_methods = nil -# end -# end -# end -# end
\ No newline at end of file diff --git a/vendor/plugins/interlock/.gitignore b/vendor/plugins/interlock/.gitignore deleted file mode 100644 index 2cb5972a2..000000000 --- a/vendor/plugins/interlock/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# MacOSX temp files -.DS_Store - -# Vim swap files -*.swp - -# test throwaway files -test/integration/app/db/schema.rb -test/integration/app/log/ - diff --git a/vendor/plugins/interlock/CHANGELOG b/vendor/plugins/interlock/CHANGELOG deleted file mode 100644 index 939594153..000000000 --- a/vendor/plugins/interlock/CHANGELOG +++ /dev/null @@ -1,10 +0,0 @@ - -v1.4. Rails 2.1 compatibility. Store dependency trees per object, when possible. Use shorter namespaces for Memcached. - -v1.3. Add basic finder memoization. - -v1.2. Add compatibility with Memcached client. - -v1.1. Add :perform => false option. Cache :content_for. Test nested view_cache blocks. Don't assign conventional dependency when called from the view, because we don't know what the controller might have already specified. - -v1.0. First release. diff --git a/vendor/plugins/interlock/LICENSE b/vendor/plugins/interlock/LICENSE deleted file mode 100644 index 90eec26be..000000000 --- a/vendor/plugins/interlock/LICENSE +++ /dev/null @@ -1,184 +0,0 @@ -Academic Free License (AFL) v. 3.0 - -This Academic Free License (the "License") applies to any original work -of authorship (the "Original Work") whose owner (the "Licensor") has -placed the following licensing notice adjacent to the copyright notice -for the Original Work: - -Licensed under the Academic Free License version 3.0 - -1) Grant of Copyright License. Licensor grants You a worldwide, -royalty-free, non-exclusive, sublicensable license, for the duration of -the copyright, to do the following: - -a) to reproduce the Original Work in copies, either alone or as part of -a collective work; - -b) to translate, adapt, alter, transform, modify, or arrange the -Original Work, thereby creating derivative works ("Derivative Works") -based upon the Original Work; - -c) to distribute or communicate copies of the Original Work and -Derivative Works to the public, under any license of your choice that -does not contradict the terms and conditions, including Licensor's -reserved rights and remedies, in this Academic Free License; - -d) to perform the Original Work publicly; and - -e) to display the Original Work publicly. - -2) Grant of Patent License. Licensor grants You a worldwide, -royalty-free, non-exclusive, sublicensable license, under patent claims -owned or controlled by the Licensor that are embodied in the Original -Work as furnished by the Licensor, for the duration of the patents, to -make, use, sell, offer for sale, have made, and import the Original Work -and Derivative Works. - -3) Grant of Source Code License. The term "Source Code" means the -preferred form of the Original Work for making modifications to it and -all available documentation describing how to modify the Original Work. -Licensor agrees to provide a machine-readable copy of the Source Code of -the Original Work along with each copy of the Original Work that -Licensor distributes. Licensor reserves the right to satisfy this -obligation by placing a machine-readable copy of the Source Code in an -information repository reasonably calculated to permit inexpensive and -convenient access by You for as long as Licensor continues to distribute -the Original Work. - -4) Exclusions From License Grant. Neither the names of Licensor, nor the -names of any contributors to the Original Work, nor any of their -trademarks or service marks, may be used to endorse or promote products -derived from this Original Work without express prior permission of the -Licensor. Except as expressly stated herein, nothing in this License -grants any license to Licensor's trademarks, copyrights, patents, trade -secrets or any other intellectual property. No patent license is granted -to make, use, sell, offer for sale, have made, or import embodiments of -any patent claims other than the licensed claims defined in Section 2. -No license is granted to the trademarks of Licensor even if such marks -are included in the Original Work. Nothing in this License shall be -interpreted to prohibit Licensor from licensing under terms different -from this License any Original Work that Licensor otherwise would have a -right to license. - -5) External Deployment. The term "External Deployment" means the use, -distribution, or communication of the Original Work or Derivative Works -in any way such that the Original Work or Derivative Works may be used -by anyone other than You, whether those works are distributed or -communicated to those persons or made available as an application -intended for use over a network. As an express condition for the grants -of license hereunder, You must treat any External Deployment by You of -the Original Work or a Derivative Work as a distribution under section -1(c). - -6) Attribution Rights. You must retain, in the Source Code of any -Derivative Works that You create, all copyright, patent, or trademark -notices from the Source Code of the Original Work, as well as any -notices of licensing and any descriptive text identified therein as an -"Attribution Notice." You must cause the Source Code for any Derivative -Works that You create to carry a prominent Attribution Notice reasonably -calculated to inform recipients that You have modified the Original -Work. - -7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants -that the copyright in and to the Original Work and the patent rights -granted herein by Licensor are owned by the Licensor or are sublicensed -to You under the terms of this License with the permission of the -contributor(s) of those copyrights and patent rights. Except as -expressly stated in the immediately preceding sentence, the Original -Work is provided under this License on an "AS IS" BASIS and WITHOUT -WARRANTY, either express or implied, including, without limitation, the -warranties of non-infringement, merchantability or fitness for a -particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL -WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential -part of this License. No license to the Original Work is granted by this -License except under this disclaimer. - -8) Limitation of Liability. Under no circumstances and under no legal -theory, whether in tort (including negligence), contract, or otherwise, -shall the Licensor be liable to anyone for any indirect, special, -incidental, or consequential damages of any character arising as a -result of this License or the use of the Original Work including, -without limitation, damages for loss of goodwill, work stoppage, -computer failure or malfunction, or any and all other commercial damages -or losses. This limitation of liability shall not apply to the extent -applicable law prohibits such limitation. - -9) Acceptance and Termination. If, at any time, You expressly assented -to this License, that assent indicates your clear and irrevocable -acceptance of this License and all of its terms and conditions. If You -distribute or communicate copies of the Original Work or a Derivative -Work, You must make a reasonable effort under the circumstances to -obtain the express assent of recipients to the terms of this License. -This License conditions your rights to undertake the activities listed -in Section 1, including your right to create Derivative Works based upon -the Original Work, and doing so without honoring these terms and -conditions is prohibited by copyright law and international treaty. -Nothing in this License is intended to affect copyright exceptions and -limitations (including "fair use" or "fair dealing"). This License shall -terminate immediately and You may no longer exercise any of the rights -granted to You by this License upon your failure to honor the conditions -in Section 1(c). - -10) Termination for Patent Action. This License shall terminate -automatically and You may no longer exercise any of the rights granted -to You by this License as of the date You commence an action, including -a cross-claim or counterclaim, against Licensor or any licensee alleging -that the Original Work infringes a patent. This termination provision -shall not apply for an action alleging patent infringement by -combinations of the Original Work with other software or hardware. - -11) Jurisdiction, Venue and Governing Law. Any action or suit relating -to this License may be brought only in the courts of a jurisdiction -wherein the Licensor resides or in which Licensor conducts its primary -business, and under the laws of that jurisdiction excluding its -conflict-of-law provisions. The application of the United Nations -Convention on Contracts for the International Sale of Goods is expressly -excluded. Any use of the Original Work outside the scope of this License -or after its termination shall be subject to the requirements and -penalties of copyright or patent law in the appropriate jurisdiction. -This section shall survive the termination of this License. - -12) Attorneys' Fees. In any action to enforce the terms of this License -or seeking damages relating thereto, the prevailing party shall be -entitled to recover its costs and expenses, including, without -limitation, reasonable attorneys' fees and costs incurred in connection -with such action, including any appeal of such action. This section -shall survive the termination of this License. - -13) Miscellaneous. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. - -14) Definition of "You" in This License. "You" throughout this License, -whether in upper or lower case, means an individual or a legal entity -exercising rights under, and complying with all of the terms of, this -License. For legal entities, "You" includes any entity that controls, is -controlled by, or is under common control with you. For purposes of this -definition, "control" means (i) the power, direct or indirect, to cause -the direction or management of such entity, whether by contract or -otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -15) Right to Use. You may use the Original Work in all ways not -otherwise restricted or conditioned by this License or by law, and -Licensor promises not to interfere with or be responsible for such uses -by You. - -16) Modification of This License. This License is Copyright (c) 2005 -Lawrence Rosen. Permission is granted to copy, distribute, or -communicate this License without modification. Nothing in this License -permits You to modify this License as applied to the Original Work or to -Derivative Works. However, You may modify the text of this License and -copy, distribute or communicate your modified version (the "Modified -License") and apply it to other original works of authorship subject to -the following conditions: (i) You may not indicate in any way that your -Modified License is the "Academic Free License" or "AFL" and you may not -use those names in the name of your Modified License; (ii) You must -replace the notice specified in the first paragraph above with the -notice "Licensed under <insert your license name here>" or with a notice -of your own that is not confusingly similar to the notice in this -License; and (iii) You may not claim that your original works are open -source software unless your Modified License has been approved by Open -Source Initiative (OSI) and You comply with its license review and -certification process. - diff --git a/vendor/plugins/interlock/Manifest b/vendor/plugins/interlock/Manifest deleted file mode 100644 index 79ce97764..000000000 --- a/vendor/plugins/interlock/Manifest +++ /dev/null @@ -1,85 +0,0 @@ -CHANGELOG -examples/memcached.yml -init.rb -lib/interlock/action_controller.rb -lib/interlock/action_view.rb -lib/interlock/active_record.rb -lib/interlock/config.rb -lib/interlock/core_extensions.rb -lib/interlock/finders.rb -lib/interlock/interlock.rb -lib/interlock/lock.rb -lib/interlock/pass_through_store.rb -lib/interlock.rb -LICENSE -Manifest -README -tasks/interlock.rake -test/integration/app/app/controllers/application.rb -test/integration/app/app/controllers/eval_controller.rb -test/integration/app/app/controllers/items_controller.rb -test/integration/app/app/helpers/application_helper.rb -test/integration/app/app/helpers/eval_helper.rb -test/integration/app/app/helpers/items_helper.rb -test/integration/app/app/models/item.rb -test/integration/app/app/views/items/detail.rhtml -test/integration/app/app/views/items/list.rhtml -test/integration/app/app/views/items/recent.rhtml -test/integration/app/app/views/items/show.rhtml -test/integration/app/app/views/layouts/application.html.erb -test/integration/app/app/views/shared/_related.rhtml -test/integration/app/config/boot.rb -test/integration/app/config/database.yml -test/integration/app/config/environment.rb -test/integration/app/config/environments/development.rb -test/integration/app/config/environments/production.rb -test/integration/app/config/environments/test.rb -test/integration/app/config/initializers/inflections.rb -test/integration/app/config/initializers/mime_types.rb -test/integration/app/config/memcached.yml -test/integration/app/config/routes.rb -test/integration/app/db/migrate/001_create_items.rb -test/integration/app/doc/README_FOR_APP -test/integration/app/public/404.html -test/integration/app/public/422.html -test/integration/app/public/500.html -test/integration/app/public/dispatch.cgi -test/integration/app/public/dispatch.fcgi -test/integration/app/public/dispatch.rb -test/integration/app/public/favicon.ico -test/integration/app/public/images/rails.png -test/integration/app/public/index.html -test/integration/app/public/javascripts/application.js -test/integration/app/public/javascripts/controls.js -test/integration/app/public/javascripts/dragdrop.js -test/integration/app/public/javascripts/effects.js -test/integration/app/public/javascripts/prototype.js -test/integration/app/public/robots.txt -test/integration/app/Rakefile -test/integration/app/README -test/integration/app/script/about -test/integration/app/script/console -test/integration/app/script/destroy -test/integration/app/script/generate -test/integration/app/script/performance/benchmarker -test/integration/app/script/performance/profiler -test/integration/app/script/performance/request -test/integration/app/script/plugin -test/integration/app/script/process/inspector -test/integration/app/script/process/reaper -test/integration/app/script/process/spawner -test/integration/app/script/runner -test/integration/app/script/server -test/integration/app/test/fixtures/items.yml -test/integration/app/test/functional/eval_controller_test.rb -test/integration/app/test/functional/items_controller_test.rb -test/integration/app/test/test_helper.rb -test/integration/app/test/unit/item_test.rb -test/integration/server_test.rb -test/setup.rb -test/teardown.rb -test/test_helper.rb -test/unit/finder_test.rb -test/unit/interlock_test.rb -test/unit/lock_test.rb -TODO diff --git a/vendor/plugins/interlock/README b/vendor/plugins/interlock/README deleted file mode 100644 index ca15b35d2..000000000 --- a/vendor/plugins/interlock/README +++ /dev/null @@ -1,130 +0,0 @@ - -Interlock - -A Rails plugin for maintainable and high-efficiency caching. - -== License - -Copyright 2007, 2008 Cloudburst, LLC. Licensed under the AFL 3. See the included LICENSE file. Portions copyright 2006 Chris Wanstrath and used with permission. - -The public certificate for the gem is here[http://blog.evanweaver.com/files/evan_weaver-original-public_cert.pem]. - -If you use this software, please {make a donation}[http://blog.evanweaver.com/donate/], or {recommend Evan}[http://www.workingwithrails.com/person/7739-evan-weaver] at Working with Rails. - -== Requirements - -* memcached (http://www.danga.com/memcached) -* memcache-client gem -* Rails 2.1 - -== Features - -Interlock is an intelligent fragment cache for Rails. - -It works by making your view fragments and associated controller blocks march along together. If a fragment is fresh, the controller behavior won't run. This eliminates duplicate effort from your request cycle. Your controller blocks run so infrequently that you can use regular ActiveRecord finders and not worry about object caching at all. - -Invalidations are automatically tracked based on the model lifecyle, and you can scope any block to an arbitrary level. Interlock also caches <tt>content_for</tt> calls, unlike regular Rails, and can optionally cache simple finders. - -Interlock uses a tiered caching layer so that multiple lookups of a key only hit memcached once per request. - -== Installation - -First, compile and install memcached itself. Get a memcached server running. - -You also need either <tt>memcache-client</tt> or {memcached}[http://blog.evanweaver.com/files/doc/fauna/memcached]: - sudo gem install memcache-client - -Then, install the plugin: - script/plugin install git://github.com/fauna/interlock.git - -Lastly, configure your Rails app for memcached by creating a <tt>config/memcached.yml</tt> file. The format is compatible with Cache_fu: - - defaults: - namespace: myapp - sessions: false - client: memcache-client - development: - servers: - - 127.0.0.1:11211 # Default host and port - production: - servers: - - 10.12.128.1:11211 - - 10.12.128.2:11211 - -Now you're ready to go. - -Note that if you have the {memcached}[http://blog.evanweaver.com/files/doc/fauna/memcached] client, you can use <tt>client: memcached</tt> for better performance. - -== Usage - -Interlock provides two similar caching methods: <tt>behavior_cache</tt> for controllers and <tt>view_cache</tt> for views. They both accept an optional list or hash of model dependencies, and an optional <tt>:tag</tt> keypair. <tt>view_cache</tt> also accepts a <tt>:ttl</tt> keypair. - -The simplest usage doesn't require any parameters. In the controller: - - class ItemsController < ActionController::Base - - def slow_action - behavior_cache do - @items = Item.find(:all, :conditions => "be slow") - end - end - - end - -Now, in the view, wrap the largest section of ERB you can find that uses data from <tt>@items</tt> in a <tt>view_cache</tt> block. No other part of the view can refer to <tt>@items</tt>, because <tt>@items</tt> won't get set unless the cache is stale. - - <% @title = "My Sweet Items" %> - - <% view_cache do %> - <% @items.each do |item| %> - <h1><%= item.name %></h1> - <% end %> - <% end %> - -You have to do them both. - -This automatically registers a caching dependency on Item for <tt>slow_action</tt>. The controller block won't run if the <tt>slow_action</tt> view fragment is fresh, and the view fragment will only get invalidated when an Item is changed. - -You can use multiple instance variables in one block, of course. Just make sure the <tt>behavior_cache</tt> provides whatever the <tt>view_cache</tt> uses. - -See ActionController::Base and ActionView::Helpers::CacheHelper for more details. - -== Caching finders - -Interlock 1.3 adds the ability to cache simple finder lookups. Add this line in <tt>config/memcached.yml</tt>: - - with_finders: true - -Now, whenever you call <b>find</b>, <b>find_by_id</b>, or <b>find_all_by_id</b> with a single id or an array of ids, the cache will be used. The cache key for each record invalidates when the record is saved or destroyed. Memcached's multiget mode is used for maximum performance. - -If you pass any parameters other than ids, or use dynamic finders, the cache will not be used. This means that <tt>:include</tt> works as expected and does not require complicated invalidation. - -See Interlock::Finders for more. - -== Notes - -You will not see any actual cache reuse in development mode unless you set <tt>config.action_controller.perform_caching = true</tt> in <tt>config/environments/development.rb</tt>. - -<b>If you have custom <tt>render</tt> calls in the controller, they must be outside the <tt>behavior_cache</tt> blocks.</b> No exceptions. For example: - - def profile - behavior_cache do - @items = Item.find(:all, :conditions => "be slow") - end - render :action => 'home' - end - -You can write custom invalidation rules if you really want to, but try hard to avoid it; it has a significant cost in long-term maintainability. - -Also, Interlock obeys the <tt>ENV['RAILS_ASSET_ID']</tt> setting, so if you need to blanket-invalidate all your caches, just change <tt>RAILS_ASSET_ID</tt> (for example, you could have it increment on every deploy). - -== Further resources - -* http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching/ -* http://www.socialtext.net/memcached/index.cgi?faq - -== Reporting problems - -The support forum is here[http://github.com/fauna/interlock/issues]. - -Patches and contributions are very welcome. Please note that contributors are required to assign copyright for their additions to Cloudburst, LLC. diff --git a/vendor/plugins/interlock/Rakefile b/vendor/plugins/interlock/Rakefile deleted file mode 100644 index d01b405c1..000000000 --- a/vendor/plugins/interlock/Rakefile +++ /dev/null @@ -1,34 +0,0 @@ - -require 'echoe' - -Echoe.new("interlock") do |p| - p.project = "fauna" - p.summary = "A Rails plugin for maintainable and high-efficiency caching." - p.url = "http://blog.evanweaver.com/files/doc/fauna/interlock/" - p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/" - p.test_pattern = ["test/integration/*.rb", "test/unit/*.rb"] - p.rdoc_pattern = ["README", "CHANGELOG", "TODO", "LICENSE", "lib/interlock/lock.rb", "lib/interlock/interlock.rb", "lib/interlock/action_controller.rb", "lib/interlock/active_record.rb", "lib/interlock/finders.rb", "lib/interlock/action_view.rb", "lib/interlock/config.rb"] - p.clean_pattern += ['test/integration/app/coverage', 'test/integration/app/db/schema.rb', - 'test/integration/app/vendor/plugins/interlock'] -end - -desc "Run all the tests in production and development mode both" -task "test_all" do - ['memcache-client', 'memcached'].each do |client| - ENV['CLIENT'] = client - ['false', 'true'].each do |finder| - ENV['FINDERS'] = finder - ['false', 'true'].each do |env| - ENV['PRODUCTION'] = env - mode = env == 'false' ? "Development" : "Production" - STDERR.puts "#{'='*80}\n#{mode} mode, #{client}, finders #{finder}\n#{'='*80}" - system("rake test:multi_rails:all") - end - end - end -end - -task "tail" do - log = "test/integration/app/log/development.log" - system("touch #{log} && tail -f #{log} | grep interlock") -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/TEST_HOWTO b/vendor/plugins/interlock/TEST_HOWTO deleted file mode 100644 index f52491fdd..000000000 --- a/vendor/plugins/interlock/TEST_HOWTO +++ /dev/null @@ -1,20 +0,0 @@ -Steps to run the tests. - - $ mkdir test/integration/app/log - $ RAILS_ENV=development; export RAILS_ENV - -If you don't run mysql as root, edit the user in test/integration/app/config/database.yml, -and grant him permissions to create new tables (/opt/local/lib/mysql5/bin/mysql -u root -p). - - $ sudo gem install multi_rails echoe - $ rake - -To run an individual suite, first run: - - $ ruby test/setup.rb - -Then: - - $ ruby test/unit/finder_test.rb - -etc. diff --git a/vendor/plugins/interlock/TODO b/vendor/plugins/interlock/TODO deleted file mode 100644 index 23250e15f..000000000 --- a/vendor/plugins/interlock/TODO +++ /dev/null @@ -1,11 +0,0 @@ - -Soon: - -* Throw a nice error message when the requested memcache client cannot be found -* Add anti-dogpiling logic - -Someday: - -* Add test coverage of STI child classes -* Figure out how to cache Builder blocks -* Figure out how to cache RJS diff --git a/vendor/plugins/interlock/examples/memcached.yml b/vendor/plugins/interlock/examples/memcached.yml deleted file mode 100644 index ce72bb1d6..000000000 --- a/vendor/plugins/interlock/examples/memcached.yml +++ /dev/null @@ -1,11 +0,0 @@ -defaults: - namespace: myapp - sessions: false - client: memcache-client -development: - servers: - - 127.0.0.1:11211 -production: - servers - - 10.12.128.1 - - 10.12.128.2 diff --git a/vendor/plugins/interlock/init.rb b/vendor/plugins/interlock/init.rb deleted file mode 100644 index dfd46ab31..000000000 --- a/vendor/plugins/interlock/init.rb +++ /dev/null @@ -1,2 +0,0 @@ - -require 'interlock' diff --git a/vendor/plugins/interlock/lib/interlock.rb b/vendor/plugins/interlock/lib/interlock.rb deleted file mode 100644 index e4cfb91c3..000000000 --- a/vendor/plugins/interlock/lib/interlock.rb +++ /dev/null @@ -1,28 +0,0 @@ - -module Interlock -end - -require 'interlock/core_extensions' -require 'interlock/config' -require 'interlock/interlock' -require 'interlock/lock' -require 'interlock/pass_through_store' -require 'interlock/action_controller' -require 'interlock/action_view' -require 'interlock/finders' -require 'interlock/active_record' - -begin - if defined?(JRUBY_VERSION) - require 'memcache-client' - else - require 'memcached' - end -rescue LoadError -end - -unless ActionController::Base.perform_caching - RAILS_DEFAULT_LOGGER.warn "** interlock warning; config.perform_caching == false" -end - -Interlock::Config.run! diff --git a/vendor/plugins/interlock/lib/interlock/action_controller.rb b/vendor/plugins/interlock/lib/interlock/action_controller.rb deleted file mode 100644 index 73ed81843..000000000 --- a/vendor/plugins/interlock/lib/interlock/action_controller.rb +++ /dev/null @@ -1,253 +0,0 @@ - -module ActionController #:nodoc: - class Base - - -=begin rdoc -Build the fragment key from a particular context. This must be deterministic and stateful except for the tag. We can't scope the key to arbitrary params because the view doesn't have access to which are relevant and which are not. - -Note that the tag can be pretty much any object. Define <tt>to_interlock_tag</tt> if you need custom tagging for some class. ActiveRecord::Base already has it defined appropriately. - -If you pass an Array of symbols as the tag, it will get value-mapped onto params and sorted. This makes granular scoping easier, although it doesn't sidestep the normal blanket invalidations. -=end - - def caching_key(ignore = nil, tag = nil) - ignore = Array(ignore) - ignore = Interlock::SCOPE_KEYS if ignore.include? :all - - if (Interlock::SCOPE_KEYS - ignore).empty? and !tag - raise Interlock::UsageError, "You must specify a :tag if you are ignoring the entire default scope." - end - - if tag.is_a? Array and tag.all? {|x| x.is_a? Symbol} - tag = tag.sort_by do |key| - key.to_s - end.map do |key| - params[key].to_interlock_tag - end.join(";") - end - - Interlock.caching_key( - ignore.include?(:controller) ? 'any' : controller_name, - ignore.include?(:action) ? 'any' : action_name, - ignore.include?(:id) ? 'all' : params[:id], - tag - ) - end - - -=begin rdoc - -<tt>behavior_cache</tt> marks a controller block for caching. It accepts a list of class dependencies for invalidation, as well as as <tt>:tag</tt> and <tt>:ignore</tt> keys for explicit fragment scoping. It does not accept a <tt>:ttl</tt> key. - -Please note that the behavior of nested <tt>behavior_cache</tt> blocks is undefined. - -== Declaring dependencies - -You can declare non-default invalidation dependencies by passing models to <tt>behavior_cache</tt> (you can also pass them to <tt>view_cache</tt>, but you should only do that if you are caching a fragment without an associated behavior block in the controller). - -<b>No dependencies (cache never invalidates):</b> - behavior_cache nil do - end - -<b>Invalidate on any Media change:</b> - behavior_cache Media do - end - -<b>Invalidate on any Media or Item change:</b> - behavior_cache Media, Item do - end - -<b>Invalidate on Item changes if the Item <tt>id</tt> matches the current <tt>params[:id]</tt> value:</b> - behavior_cache Item => :id do - end - -You do not have to pass the same dependencies to <tt>behavior_cache</tt> and <tt>view_cache</tt> even for the same action. The set union of both dependency lists will be used. - -== Narrowing scope and caching multiple blocks - -Sometimes you need to cache multiple blocks in a controller, or otherwise get a more fine-grained scope. Interlock provides the <tt>:tag</tt> key for this purpose. <tt>:tag</tt> accepts either an array of symbols, which are mapped to <tt>params</tt> values, or an arbitrary object, which is converted to a string identifier. <b>Your corresponding behavior caches and view caches must have identical <tt>:tag</tt> values for the interlocking to take effect.</b> - -Note that <tt>:tag</tt> can be used to scope caches. You can simultaneously cache different versions of the same block, differentiating based on params or other logic. This is great for caching per-user, for example: - - def profile - @user = current_user - behavior_cache :tag => @user do - @items = @user.items - end - end - -In the view, use the same <tt>:tag</tt> value (<tt>@user</tt>). Note that <tt>@user</tt> must be set outside of the behavior block in the controller, because its contents are used to decide whether to run the block in the first place. - -This way each user will see only their own cache. Pretty neat. - -== Broadening scope - -Sometimes the default scope (<tt>controller</tt>, <tt>action</tt>, <tt>params[:id]</tt>) is too narrow. For example, you might share a partial across actions, and set up its data via a filter. By default, Interlock will cache a separate version of it for each action. To avoid this, you can use the <tt>:ignore</tt> key, which lets you list parts of the default scope to ignore: - - before_filter :recent - - private - - def recent - behavior_cache :ignore => :action do - @recent = Item.find(:all, :limit => 5, :order => 'updated_at DESC') - end - end - -Valid values for <tt>:ignore</tt> are <tt>:controller</tt>, <tt>:action</tt>, <tt>:id</tt>, and <tt>:all</tt>. You can pass an array of multiple values. <b>Just like with <tt>:tag</tt>, your corresponding behavior caches and view caches must have identical <tt>:ignore</tt> values.</b> Note that cache blocks with <tt>:ignore</tt> values still obey the regular invalidation rules. - -A good way to get started is to just use the default scope. Then <tt>grep</tt> in the production log for <tt>interlock</tt> and see what keys are being set and read. If you see lots of different keys go by for data that you know is the same, then set some <tt>:ignore</tt> values. - -== Skipping caching - -You can pass <tt>:perform => false</tt> to disable caching, for example, in a preview action. Note that <tt>:perform</tt> only responds to <tt>false</tt>, not <tt>nil</tt>. This allows for handier view reuse because you can set <tt>:perform</tt> to an instance variable and it will still cache if the instance variable is not set: - - def preview - @perform = false - behavior_cache :perform => @perform do - end - render :action => 'show' - end - -And in the <tt>show.html.erb</tt> view: - - <% view_cache :perform => @perform do %> - <% end %> - -=end - - def behavior_cache(*args) - conventional_class = begin; controller_name.classify.constantize; rescue NameError; end - options, dependencies = Interlock.extract_options_and_dependencies(args, conventional_class) - - raise Interlock::UsageError, ":ttl has no effect in a behavior_cache block" if options[:ttl] - - Interlock.say "key", "yo: #{options.inspect} -- #{dependencies.inspect}" - - key = caching_key(options.value_for_indifferent_key(:ignore), options.value_for_indifferent_key(:tag)) - - if options[:perform] == false || Interlock.config[:disabled] - Interlock.say key, "is not cached" - yield - else - Interlock.register_dependencies(dependencies, key) - - # See if the fragment exists, and run the block if it doesn't. - unless read_fragment(key, :assign_content_for => false) - Interlock.say key, "is running the controller block" - yield - end - end - end - - #:stopdoc: - alias :caching :behavior_cache # Deprecated - #:startdoc: - - private - - # - # Callback to reset the local cache. - # - def clear_interlock_local_cache - Interlock.local_cache = ::ActiveSupport::Cache::MemoryStore.new - Interlock.log "** cleared interlock local cache" - end - - # Should be registered first in the chain - prepend_before_filter :clear_interlock_local_cache - - end - - module Caching #:nodoc: - module Fragments - - # - # Replaces Rail's write_fragment method. Avoids extra checks for regex keys - # which are unsupported, adds more detailed logging information, stores writes - # in the local process cache too to avoid duplicate memcached requests, and - # includes the content_for cache in the fragment. - # - def write_fragment(key, block_content, options = nil) - return unless perform_caching - - content = [block_content, @template.cached_content_for] - - cache_store.write(key, content, options) - Interlock.local_cache.write(key, content, options) - - Interlock.say key, "wrote" - - block_content - end - - # - # Replaces Rail's read_fragment method. Avoids checks for regex keys, - # which are unsupported, adds more detailed logging information, checks - # the local process cache before hitting memcached, and restores the - # content_for cache. Hits on memcached are also stored back locally to - # avoid duplicate requests. - # - def read_fragment(key, options = nil) - return unless perform_caching - - begin - if content = Interlock.local_cache.read(key, options) - # Interlock.say key, "read from local cache" - elsif content = cache_store.read(key, options) - raise Interlock::FragmentConsistencyError, "#{key} expected Array but got #{content.class}" unless content.is_a? Array - Interlock.say key, "read from memcached" - Interlock.local_cache.write(key, content, options) - else - # Not found - return nil - end - - raise Interlock::FragmentConsistencyError, "#{key}::content expected String but got #{content.first.class}" unless content.first.is_a? String - - options ||= {} - # Note that 'nil' is considered true for :assign_content_for - if options[:assign_content_for] != false and content.last - # Extract content_for variables - content.last.each do |name, value| - raise Interlock::FragmentConsistencyError, "#{key}::content_for(:#{name}) expected String but got #{value.class}" unless value.is_a? String - # We'll just call the helper because that will handle nested view_caches properly. - @template.send(:content_for, name, value) - end - end - - content.first - rescue Interlock::FragmentConsistencyError => e - # Delete the bogus key - Interlock.invalidate(key) - # Reraise the error - raise e - end - end - - end - - # With Rails 2.1 action caching, we need to slip in our :expire param into the ActionCacheFilter options, so that when we - # write_fragment we can pass that in and allow shane's #{key}_expiry to take effect - # (see def write in interlock/config.rb) - module Actions - - module ClassMethods - def caches_action(*actions) - return unless cache_configured? - options = actions.extract_options! - around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path), :expire => options.delete(:expire)), {:only => actions}.merge(options)) - end - end - - class ActionCacheFilter #:nodoc: - def after(controller) - return if controller.rendered_action_cache || !caching_allowed(controller) - controller.write_fragment(controller.action_cache_path.path, controller.response.body, :expire => @options[:expire]) # pass in our :expire - end - end - end - - end -end diff --git a/vendor/plugins/interlock/lib/interlock/action_view.rb b/vendor/plugins/interlock/lib/interlock/action_view.rb deleted file mode 100644 index 12497b2ef..000000000 --- a/vendor/plugins/interlock/lib/interlock/action_view.rb +++ /dev/null @@ -1,98 +0,0 @@ - -module ActionView #:nodoc: - class Base #:nodoc: - attr_accessor :cached_content_for - end - - module Helpers #:nodoc: - module CacheHelper - -=begin rdoc - -<tt>view_cache</tt> marks a corresponding view block for caching. It accepts <tt>:tag</tt> and <tt>:ignore</tt> keys for explicit scoping, as well as a <tt>:ttl</tt> key and a <tt>:perform</tt> key. - -You can specify dependencies in <tt>view_cache</tt> if you really want to. Note that unlike <tt>behavior_cache</tt>, <tt>view_cache</tt> doesn't set up any default dependencies. - -Nested <tt>view_cache</tt> blocks work fine. You would only need to nest if you had a slowly invalidating block contained in a more quickly invalidating block; otherwise there's no benefit. - -Finally, caching <tt>content_for</tt> within a <tt>view_cache</tt> works, unlike regular Rails. It even works in nested caches. - -== Setting a TTL - -Use the <tt>:ttl</tt> key to specify a maximum time-to-live, in seconds: - - <% view_cache :ttl => 5.minutes do %> - <% end %> - -Note that the cached item is not guaranteed to live this long. An invalidation rule could trigger first, or memcached could eject the item early due to the LRU. - -== View caching without action caching - -It's fine to use a <tt>view_cache</tt> block without a <tt>behavior_cache</tt> block. For example, to mimic regular fragment cache behavior, but take advantage of memcached's <tt>:ttl</tt> support, call: - - <% view_cache :ignore => :all, :tag => 'sidebar', :ttl => 5.minutes do %> - <% end %> - -== Dependencies, scoping, and other options - -See ActionController::Base for explanations of the rest of the options. The <tt>view_cache</tt> and <tt>behavior_cache</tt> APIs are identical except for setting the <tt>:ttl</tt>, which can only be done in the view, and the default dependency, which is only set by <tt>behavior_cache</tt>. - -=end - def view_cache(*args, &block) - # conventional_class = begin; controller.controller_name.classify.constantize; rescue NameError; end - options, dependencies = Interlock.extract_options_and_dependencies(args, nil) - - key = controller.caching_key(options.value_for_indifferent_key(:ignore), options.value_for_indifferent_key(:tag)) - - if options[:perform] == false || Interlock.config[:disabled] - # Interlock.say key, "is not cached" - block.call - else - Interlock.register_dependencies(dependencies, key) - - # Interlock.say key, "is rendering" - - @cached_content_for, previous_cached_content_for = {}, @cached_content_for - - cache key, :ttl => (options.value_for_indifferent_key(:ttl) or Interlock.config[:ttl]), &block - - # This is tricky. If we were already caching content_fors in a parent block, we need to - # append the content_fors set in the inner block to those already set in the outer block. - if previous_cached_content_for - @cached_content_for.each do |key, value| - previous_cached_content_for[key] = "#{previous_cached_content_for[key]}#{value}" - end - end - - # Restore the cache state - @cached_content_for = previous_cached_content_for - end - end - - #:stopdoc: - alias :caching :view_cache # Deprecated - #:startdoc: - - end - - - module CaptureHelper - # - # Override content_for so we can cache the instance variables it sets along with the fragment. - # - def content_for(name, content = nil, &block) - ivar = "@content_for_#{name}" - existing_content = instance_variable_get(ivar).to_s - this_content = (block_given? ? capture(&block) : content) - - # If we are in a view_cache block, cache what we added to this instance variable - if @cached_content_for - @cached_content_for[name] = "#{@cached_content_for[name]}#{this_content}" - end - - instance_variable_set(ivar, existing_content + this_content) - end - end - - end -end diff --git a/vendor/plugins/interlock/lib/interlock/active_record.rb b/vendor/plugins/interlock/lib/interlock/active_record.rb deleted file mode 100644 index 16a448aaa..000000000 --- a/vendor/plugins/interlock/lib/interlock/active_record.rb +++ /dev/null @@ -1,61 +0,0 @@ - -module ActiveRecord #:nodoc: - class Base - - @@nil_sentinel = :_nil - - class << self # Class methods - def update_counters_with_expiry(id, counters) - update_counters_without_expiry(id, counters) - find(id).expire_interlock_keys - end - alias_method_chain :update_counters, :expiry - end - - # - # Convert this record to a tag string. - # - def to_interlock_tag - "#{self.class.name}-#{self.id}".escape_tag_fragment - end - - # - # The expiry callback. - # - def expire_interlock_keys - return if Interlock.config[:disabled] or (defined? CGI::Session::ActiveRecordStore and is_a? CGI::Session::ActiveRecordStore::Session) - - # Fragments - self.expire_interlock_keys_for_dependency(Interlock.dependency_key(self.class.base_class, :all, nil)) - self.expire_interlock_keys_for_dependency(Interlock.dependency_key(self.class.base_class, :id, "::::#{to_param}:")) - - # Models - if Interlock.config[:with_finders] - key = self.class.base_class.caching_key(self.id) - Interlock.say key, 'invalidated with finders', 'model' - Interlock.invalidate key - end - end - - before_save :expire_interlock_keys - after_save :expire_interlock_keys - after_destroy :expire_interlock_keys - - # - # Reload. Expires the cache and force reload from db. - # - def reload_with_expiry(*args) - expire_interlock_keys - reload_without_expiry(*args) - end - alias_method_chain :reload, :expiry - - def expire_interlock_keys_for_dependency(dependency_key) - (CACHE.get(dependency_key) || {}).each do |key, scope| - Interlock.say key, "invalidated by rule #{self.class} -> #{scope.inspect}." - Interlock.invalidate key - end - end - - end -end diff --git a/vendor/plugins/interlock/lib/interlock/config.rb b/vendor/plugins/interlock/lib/interlock/config.rb deleted file mode 100644 index 956002dd5..000000000 --- a/vendor/plugins/interlock/lib/interlock/config.rb +++ /dev/null @@ -1,168 +0,0 @@ -#require 'ehcache' -module Interlock - - DEFAULTS = { - :ttl => 1.day, - :namespace => 'app', - :servers => ['127.0.0.1:11211'], - :client => 'memcache-client', - :with_finders => false - } - - CLIENT_KEYS =[ - :prefix_key, - :distribution, - :verify_key, - :tcp_nodelay, - :hash, - :hash_with_prefix_key, - :show_backtraces, - :default_ttl, - :ketama_weighted, - :retry_timeout, - :default_weight, - :buffer_requests, - :timeout, - :sort_hosts, - :cache_lookups, - :connect_timeout, - :no_block, - :failover, - :support_cas, - :namespace - ] - - mattr_accessor :config - @@config = DEFAULTS - - module Config - - CONFIG_FILE = "#{RAILS_ROOT}/config/memcached.yml" - - class << self - - # - # Load the configuration file, if available, and then set up the Memcached instance, - # Rails settings, and CACHE constants. Should be more or less compatible with - # Cache_fu. - # - def run! - if File.exist?(CONFIG_FILE) - template = ERB.new(File.open(CONFIG_FILE) {|f| f.read}) - config = YAML.load(template.result(binding)) - config.deep_symbolize_keys! - - Interlock.config.merge!(config[:defaults] || {}) - Interlock.config.merge!(config[RAILS_ENV.to_sym] || {}) - end - - install_memcached - install_fragments - - # Always install the finders. - install_finders if Interlock.config[:with_finders] - end - - # - # Configure memcached for this app. - # - def install_memcached - Interlock.config[:namespace] << "-#{RAILS_ENV}" - - unless defined? Object::CACHE - - # Give people a choice of client, even though I don't like conditional dependencies. - klass = case Interlock.config[:client] - when 'memcached' - begin - Memcached::Rails - rescue ArgumentError - raise ConfigurationError, "'memcached' client requested but not installed. Try 'sudo gem install memcached'." - end - - when 'memcache-client' - begin - if MemCache.constants.include?('SVNURL') - raise ConfigurationError, "You have the Ruby-MemCache gem installed. Please uninstall Ruby-MemCache, or otherwise guarantee that memcache-client will load instead." - end - MemCache - rescue ArgumentError - raise ConfigurationError, "'memcache-client' client requested but not installed. Try 'sudo gem install memcache-client'." - end - end - - Object.const_set('CACHE', - klass.new( - Interlock.config[:servers], - Interlock.config.slice(*CLIENT_KEYS) - ) - ) - - # Mark that we're the ones who did it. - class << CACHE - def installed_by_interlock; true; end - end - - else - begin - CACHE.installed_by_interlock - rescue NoMethodError - RAILS_DEFAULT_LOGGER.warn "** interlock: Object::CACHE already defined; will not install a new one" - # Mark that somebody else installed this CACHE. - class << CACHE - def installed_by_interlock; false; end - end - end - end - - # Add the fragment cache and lock APIs to the cache singleton. This happens no matter - # who installed the singleton. - class << CACHE - include Interlock::Lock - - def read(*args) - get args.first.to_s - end - - def write(name, content, options = {}) - set(name.to_s, - content, - options.is_a?(Hash) ? options[:ttl] : Interlock.config[:ttl] ) - end - end - end - - # - # Configure Rails to use the memcached store for fragments, and optionally, sessions. - # - def install_fragments - # Memcached fragment caching is mandatory - ActionView::Helpers::CacheHelper.class_eval do - def cache(name = {}, options = nil, &block) - # Things explode if options does not default to nil - RAILS_DEFAULT_LOGGER.debug "** fragment #{name} stored via obsolete cache() call" - @controller.fragment_for(output_buffer, name, options, &block) - end - end - ActionController::Base.cache_store = CACHE - - # Sessions are optional - if Interlock.config[:sessions] - # XXX Right now this requires memcache-client to be installed, due to a Rails problem. - # http://dev.rubyonrails.org/ticket/11290 - ActionController::Base.session_store = :mem_cache_store - ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update 'cache' => CACHE - end - end - - # - # Configure ActiveRecord#find caching. - # - def install_finders - RAILS_DEFAULT_LOGGER.warn "** using interlock finder caches" - ActiveRecord::Base.send(:include, Interlock::Finders) - end - - end - end -end diff --git a/vendor/plugins/interlock/lib/interlock/core_extensions.rb b/vendor/plugins/interlock/lib/interlock/core_extensions.rb deleted file mode 100644 index 863085846..000000000 --- a/vendor/plugins/interlock/lib/interlock/core_extensions.rb +++ /dev/null @@ -1,74 +0,0 @@ - -class Object - def to_interlock_tag - string = to_s - string = "empty_string" if string.empty? - string.escape_tag_fragment - end -end - -class NilClass - def to_interlock_tag - "untagged".escape_tag_fragment - end -end - -class Hash - alias :fetch_safely :[] - - def value_for_indifferent_key(key) - fetch_safely(key) or fetch_safely(key.to_s) or fetch_safely(key.to_sym) - end - - alias :v :value_for_indifferent_key - - def indifferentiate! - class << self - def [](key); value_for_indifferent_key(key); end - end - self - end - - def indifferentiate - self.dup.indifferentiate! - end - - def deep_symbolize_keys! - symbolize_keys! - values.each do |value| - value.deep_symbolize_keys! if value.is_a? Hash - end - end - - # Compatibility method for Rails 1.2.6. It's also faster. - unless Hash.instance_methods.include? "slice" - def slice(*keys) - hash = {} - keys.each do |key| - hash[key] = self[key] if self[key] - end - hash - end - end - -end - -class Array - # Compatibility method for Rails 1.2.6. - unless Array.instance_methods.include? "extract_options!" - def extract_options! - # Method added in Rails rev 7217 - last.is_a?(Hash) ? pop : {} - end - end -end - -class String - def field(i) - split(":")[i] - end - - def escape_tag_fragment - gsub(':', '-').gsub(/[^\w\d\-;]/, '_') - end -end diff --git a/vendor/plugins/interlock/lib/interlock/finders.rb b/vendor/plugins/interlock/lib/interlock/finders.rb deleted file mode 100644 index 4e75238ea..000000000 --- a/vendor/plugins/interlock/lib/interlock/finders.rb +++ /dev/null @@ -1,155 +0,0 @@ - -module Interlock - module Finders - def self.included(klass) - class << klass - alias_method :find_via_db, :find - remove_method :find - end - - klass.extend ClassMethods - end - - module ClassMethods - - # - # Cached find. - # - # Any other options besides ids short-circuit the cache. - # - def find(*args) - return find_via_db(*args) if args.last.is_a? Hash or args.first.is_a? Symbol - ids = args.flatten.compact.uniq - return find_via_db(ids) if ids.blank? - - records = find_via_cache(ids, true) - - if ids.length > 1 or args.first.is_a?(Array) - records - else - records.first - end - - end - - # - # Cached find_by_id. Short-circuiting works the same as find. - # - def find_by_id(*args) - return method_missing(:find_by_id, *args) if args.last.is_a? Hash - find_via_cache(args, false).first - end - - # - # Cached find_all_by_id. Ultrasphinx uses this. Short-circuiting works the same as find. - # - def find_all_by_id(*args) - return method_missing(:find_all_by_id, *args) if args.last.is_a? Hash - find_via_cache(args, false) - end - - # - # Build the model cache key for a particular id. - # - def caching_key(id) - Interlock.caching_key( - self.base_class.name, - "find", - id, - "default" - ) - end - - def finder_ttl - 0 - end - - private - - def find_via_cache(ids, should_raise) #:doc: - results = [] - - ordered_keys_to_ids = ids.flatten.map { |id| [caching_key(id), id.to_i] } - keys_to_ids = Hash[*ordered_keys_to_ids.flatten] - - records = {} - - if ActionController::Base.perform_caching - load_from_local_cache(records, keys_to_ids) - load_from_memcached(records, keys_to_ids) - end - - load_from_db(records, keys_to_ids) - - # Put them in order - - ordered_keys_to_ids.each do |key, | - record = records[key] - raise ActiveRecord::RecordNotFound, "Couldn't find #{self.name} with ID=#{keys_to_ids[key]}" if should_raise and !record - results << record - end - - # Don't return Nil objects, only the found records - results.compact - end - - def load_from_local_cache(current, keys_to_ids) #:doc: - # Load from the local cache - records = {} - keys_to_ids.each do |key, | - record = Interlock.local_cache.read(key, nil) - records[key] = record if record - end - current.merge!(records) - end - - def load_from_memcached(current, keys_to_ids) #:doc: - # Drop to memcached if necessary - if current.size < keys_to_ids.size - records = {} - missed = keys_to_ids.reject { |key, | current[key] } - - records = CACHE.get_multi(*missed.keys) - - # Set missed to the caches - records.each do |key, value| - Interlock.say key, "is loading from memcached", "model" - Interlock.local_cache.write(key, value, nil) - end - - current.merge!(records) - end - end - - def load_from_db(current, keys_to_ids) #:doc: - # Drop to db if necessary - if current.size < keys_to_ids.size - missed = keys_to_ids.reject { |key, | current[key] } - ids_to_keys = keys_to_ids.invert - - # Load from the db - ids_to_find = missed.values - if ids_to_find.length > 1 - records = send("find_all_by_#{primary_key}".to_sym, ids_to_find, {}) - else - records = [send("find_by_#{primary_key}".to_sym, ids_to_find.first, {})].compact # explicitly just look for one if that's all that's needed - end - - records = Hash[*(records.map do |record| - [ids_to_keys[record.id], record] - end.flatten)] - - # Set missed to the caches - records.each do |key, value| - Interlock.say key, "is loading from the db", "model" - Interlock.local_cache.write(key, value, nil) - CACHE.set key, value, value.class.finder_ttl unless Interlock.config[:disabled] - end - - current.merge!(records) - end - end - end - end # Finders -end # Interlock - diff --git a/vendor/plugins/interlock/lib/interlock/interlock.rb b/vendor/plugins/interlock/lib/interlock/interlock.rb deleted file mode 100644 index 29eaa8804..000000000 --- a/vendor/plugins/interlock/lib/interlock/interlock.rb +++ /dev/null @@ -1,155 +0,0 @@ - -module Interlock - - class InterlockError < StandardError #:nodoc: - end - class DependencyError < InterlockError #:nodoc: - end - class ConfigurationError < InterlockError #:nodoc: - end - class UsageError < InterlockError #:nodoc: - end - class LockAcquisitionError < InterlockError #:nodoc: - end - class FragmentConsistencyError < InterlockError #:nodoc: - end - - SCOPE_KEYS = [:controller, :action, :id] - - # Buried value extracted from memcache.rb in the memcache-client gem. - # If one tries to request a key that is too long, the client throws an error. - # In practice, it seems better to simply avoid ever setting such long keys, - # so we use this value to achieve such for keys generated by Interlock. - KEY_LENGTH_LIMIT = 250 - - # Similarly buried and useful: no whitespace allowed in keys. - ILLEGAL_KEY_CHARACTERS_PATTERN = /\s/ - - mattr_accessor :local_cache - - # Install the pass-through store. This is used in the console and test - # environment. In a server environment, the controller callbacks install - # the memory store before each request. - @@local_cache = Interlock::PassThroughStore.new - - class << self - # - # Extract the dependencies from the rest of the arguments and registers - # them with the appropriate models. - # - def extract_options_and_dependencies(dependencies, default = nil) - options = dependencies.extract_options! - - # Hook up the dependencies nested array. - dependencies.map! { |klass| [klass, :all] } - options.each do |klass, scope| - if klass.is_a? Class - # - # Beware! Scoping to :id means that a request's params[:id] must equal - # klass#id or the rule will not trigger. This is because params[:id] is the - # only record-specific scope include in the key. - # - # If you want fancier invalidation, think hard about whether it really - # matters. Over-invalidation is rarely a problem, but under-invalidation - # frequently is. - # - # "But I need it!" you say. All right, then start using key tags. - # - raise Interlock::DependencyError, "#{scope.inspect} is not a valid scope" unless [:all, :id].include?(scope) - dependencies << [klass, scope.to_sym] - end - end - - unless dependencies.any? - # Use the conventional controller/model association if none are provided - # Can be skipped by calling caching(nil) - dependencies = [[default, :all]] - end - - # Remove nils - dependencies.reject! {|klass, scope| klass.nil? } - - [options.indifferentiate, dependencies] - end - - # - # Add each key with scope to the appropriate dependencies array. - # - def register_dependencies(dependencies, key) - return if Interlock.config[:disabled] - - Array(dependencies).each do |klass, scope| - dep_key = dependency_key(klass, scope, key) - - # Get the value for this class/key out of the global store. - this = (CACHE.get(dep_key) || {})[key] - - # Make sure to not overwrite broader scopes. - unless this == :all or this == scope - # We need to write, so acquire the lock. - CACHE.lock(dep_key) do |hash| - Interlock.say key, "registered a dependency on #{klass} -> #{scope.inspect}." - (hash || {}).merge({key => scope}) - end - end - end - end - - def say(key, msg, type = "fragment") #:nodoc: - log "** #{type} #{key.inspect[1..-2]} #{msg}" - end - - def log(msg) - case Interlock.config[:log_level] - when 'debug', 'info', 'warn', 'error' - log_method = Interlock.config[:log_level] - else - log_method = :debug - end - - RAILS_DEFAULT_LOGGER.send( log_method, msg ) - end - - # - # Get the Memcached key for a class's dependency list. We store per-class - # to reduce lock contention. - # - def dependency_key(klass, scope, key) - id = (scope == :id ? ":#{key.field(4)}" : nil) - "interlock:#{ENV['RAILS_ASSET_ID']}:dependency:#{klass.name}#{id}" - end - - # - # Build a fragment key for an explicitly passed context. Shouldn't be called - # unless you need to write your own fine-grained invalidation rules. Make sure - # the default ones are really unacceptable before you go to the trouble of - # rolling your own. - # - def caching_key(controller, action, id, tag) - raise ArgumentError, 'Both controller and action must be specified' unless controller and action - - id = (id or 'all').to_interlock_tag - tag = tag.to_interlock_tag - - key = "interlock:#{ENV['RAILS_ASSET_ID']}:#{controller}:#{action}:#{id}:#{tag}" - - if key.length > KEY_LENGTH_LIMIT - old_key = key - key = key[0..KEY_LENGTH_LIMIT-1] - say old_key, "truncated to #{key}" - end - - key.gsub ILLEGAL_KEY_CHARACTERS_PATTERN, '' - end - - # - # Invalidate a particular key. - # - def invalidate(key) - # Console and tests do not install the local cache - Interlock.local_cache.delete(key) if Interlock.local_cache - ActionController::Base.cache_store.delete key - end - - end -end diff --git a/vendor/plugins/interlock/lib/interlock/lock.rb b/vendor/plugins/interlock/lib/interlock/lock.rb deleted file mode 100644 index 89479334c..000000000 --- a/vendor/plugins/interlock/lib/interlock/lock.rb +++ /dev/null @@ -1,44 +0,0 @@ - -module Interlock - module Lock - - # - # Try to acquire a global lock from memcached for a particular key. - # If successful, yield and set the key to the return value, then release - # the lock. - # - # Based on http://rubyurl.com/Sw7 , which I partially wrote. - # - - def lock(key, lock_expiry = 30, retries = 5) - retries.times do |count| - - # We have to be compatible with both client APIs. Eventually we can use Memcached#cas - # for this. - begin - response = CACHE.add("lock:#{key}", "Locked by #{Process.pid}", lock_expiry) - # Nil is a successful response for Memcached 0.11, and "STORED\r\n" for MemCache. - response = [true, nil, "STORED\r\n"].include?(response) - rescue Memcached::NotStored - # Do nothing - end - - if response - begin - value = yield(CACHE.get(key)) - CACHE.set(key, value) - return value - ensure - CACHE.delete("lock:#{key}") - end - else - # Wait - sleep((2**count) / 2.0) - end - end - - raise ::Interlock::LockAcquisitionError, "Couldn't acquire lock for #{key}" - end - - end -end diff --git a/vendor/plugins/interlock/lib/interlock/pass_through_store.rb b/vendor/plugins/interlock/lib/interlock/pass_through_store.rb deleted file mode 100644 index b3926ba01..000000000 --- a/vendor/plugins/interlock/lib/interlock/pass_through_store.rb +++ /dev/null @@ -1,19 +0,0 @@ - -module Interlock - # - # A stub class so that does not cache, for use in the test environment and the console - # when the MemoryStore is not available. - # - class PassThroughStore - - # Do nothing. - def nothing(*args) - nil - end - - alias :read :nothing - alias :write :nothing - alias :delete :nothing - - end -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/lib/tasks/interlock.rake b/vendor/plugins/interlock/lib/tasks/interlock.rake deleted file mode 100644 index a7089f112..000000000 --- a/vendor/plugins/interlock/lib/tasks/interlock.rake +++ /dev/null @@ -1,10 +0,0 @@ - -namespace :interlock do - desc "Watch the Rails log for Interlock-specific messages" - task :tail do - Dir.chdir RAILS_ROOT do - exec("tail -f log/#{RAILS_ENV}.log | grep interlock") - end - end -end -
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/README b/vendor/plugins/interlock/test/integration/app/README deleted file mode 100644 index a1db73c4b..000000000 --- a/vendor/plugins/interlock/test/integration/app/README +++ /dev/null @@ -1,203 +0,0 @@ -== Welcome to Rails - -Rails is a web-application and persistence framework that includes everything -needed to create database-backed web-applications according to the -Model-View-Control pattern of separation. 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 - (If you've downloaded Rails in a complete tgz or zip, this step is already done) -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 and lighttpd if they are installed, otherwise -Rails will use WEBrick, the webserver that ships with Ruby. When you run script/server, -Rails will check if Mongrel exists, then lighttpd and finally fall back to WEBrick. This ensures -that you can always get up and running quickly. - -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 - -If Mongrel is not installed, Rails will look for lighttpd. It's considerably faster than -Mongrel and WEBrick and also suited for production use, but requires additional -installation and currently only works well on OS X/Unix (Windows users are encouraged -to start with Mongrel). We recommend version 1.4.11 and higher. You can download it from -http://www.lighttpd.net. - -And finally, if neither Mongrel or lighttpd are installed, Rails will use the built-in Ruby -web server, WEBrick. WEBrick is a small Ruby web server suitable for development, but not -for production. - -But of course its also possible to run Rails on any platform that supports FCGI. -Apache, LiteSpeed, IIS are just a few. For more information on FCGI, -please visit: http://wiki.rubyonrails.com/rails/pages/FastCGI - - -== 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! 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> - - -== 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.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.erb. Inside default.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. - This directory is in the load path. diff --git a/vendor/plugins/interlock/test/integration/app/Rakefile b/vendor/plugins/interlock/test/integration/app/Rakefile deleted file mode 100644 index 3bb0e8592..000000000 --- a/vendor/plugins/interlock/test/integration/app/Rakefile +++ /dev/null @@ -1,10 +0,0 @@ -# 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' diff --git a/vendor/plugins/interlock/test/integration/app/app/controllers/application.rb b/vendor/plugins/interlock/test/integration/app/app/controllers/application.rb deleted file mode 100644 index ab63c229d..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/controllers/application.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Filters added to this controller apply to all controllers in the application. -# Likewise, all the methods added will be available for all controllers. - -class ApplicationController < ActionController::Base - # helper :all # include all helpers, all the time - - # See ActionController::RequestForgeryProtection for details - # Uncomment the :secret if you're not using the cookie session store - # protect_from_forgery # :secret => '491bb7f9ad07a91046fcc3756839524b' -end diff --git a/vendor/plugins/interlock/test/integration/app/app/controllers/eval_controller.rb b/vendor/plugins/interlock/test/integration/app/app/controllers/eval_controller.rb deleted file mode 100644 index 66a99bd08..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/controllers/eval_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -class EvalController < ApplicationController - - def index - render :text => eval(params['string']).inspect - end - -end diff --git a/vendor/plugins/interlock/test/integration/app/app/controllers/items_controller.rb b/vendor/plugins/interlock/test/integration/app/app/controllers/items_controller.rb deleted file mode 100644 index 203f9fc5a..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/controllers/items_controller.rb +++ /dev/null @@ -1,50 +0,0 @@ -class ItemsController < ApplicationController - - before_filter :related - - def index - behavior_cache do - @items = Item.find(:all) - end - render :action => 'list' - end - - def detail - # Nesting is theoretically useful when the outer view block invalidates faster than the inner one - behavior_cache :tag => :outer do - @items = Item.find(:all) - end - behavior_cache Item => :id, :tag => :inner do - @item = Item.find(params[:id]) - end - end - - def show - behavior_cache Item => :id do - @item = Item.find(params['id']) - end - end - - def recent - behavior_cache nil, :tag => [:seconds] do - @items = Item.find(:all, :conditions => ['updated_at >= ?', params['seconds'].to_i.ago]) - end - end - - def preview - @perform = false - behavior_cache Item => :id, :perform => @perform do - @item = Item.find(params['id']) - end - render :action => 'show' - end - - private - - def related - behavior_cache :ignore => :all, :tag => 'related' do - @related = "Delicious cake" - end - end - -end diff --git a/vendor/plugins/interlock/test/integration/app/app/helpers/application_helper.rb b/vendor/plugins/interlock/test/integration/app/app/helpers/application_helper.rb deleted file mode 100644 index 22a7940eb..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/helpers/application_helper.rb +++ /dev/null @@ -1,3 +0,0 @@ -# Methods added to this helper will be available to all templates in the application. -module ApplicationHelper -end diff --git a/vendor/plugins/interlock/test/integration/app/app/helpers/eval_helper.rb b/vendor/plugins/interlock/test/integration/app/app/helpers/eval_helper.rb deleted file mode 100644 index 1b2675d21..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/helpers/eval_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module EvalHelper -end diff --git a/vendor/plugins/interlock/test/integration/app/app/helpers/items_helper.rb b/vendor/plugins/interlock/test/integration/app/app/helpers/items_helper.rb deleted file mode 100644 index cff0c9fe2..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/helpers/items_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ItemsHelper -end diff --git a/vendor/plugins/interlock/test/integration/app/app/models/book.rb b/vendor/plugins/interlock/test/integration/app/app/models/book.rb deleted file mode 100644 index e09543723..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/models/book.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Book < ActiveRecord::Base - set_primary_key :guid -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/app/models/item.rb b/vendor/plugins/interlock/test/integration/app/app/models/item.rb deleted file mode 100644 index 89606ad1b..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/models/item.rb +++ /dev/null @@ -1,2 +0,0 @@ -class Item < ActiveRecord::Base -end diff --git a/vendor/plugins/interlock/test/integration/app/app/views/items/detail.rhtml b/vendor/plugins/interlock/test/integration/app/app/views/items/detail.rhtml deleted file mode 100644 index 44d108216..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/views/items/detail.rhtml +++ /dev/null @@ -1,20 +0,0 @@ - -<% view_cache :tag => :outer do %> - <div style="border: 1px solid black; padding: 5px;"> - <p>I invalidate quickly.</p> - <h1><%= @items.size %> total items</h1> - - <% content_for :title do %>Outer: <% end %> - - <% view_cache :tag => :inner do %> - <div style="margin: 20px; padding: 5px; border: 1px solid black;"> - <p>I invalidate slowly.</p> - <h2>Item <%= @item.id %> is <%= @item.name %>.</h2> - - <% content_for :title do %>Inner<% end %> - - </div> - <% end %> - - </div> -<% end %> diff --git a/vendor/plugins/interlock/test/integration/app/app/views/items/list.rhtml b/vendor/plugins/interlock/test/integration/app/app/views/items/list.rhtml deleted file mode 100644 index 9f1416ab6..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/views/items/list.rhtml +++ /dev/null @@ -1,16 +0,0 @@ - -<h1>List</h1> -<% view_cache do %> - - <% content_for :title do %> - <%= @items.size %> Items - <% end %> - - <% @items.each do |item| %> - <h3><%= item.name %></h3> - <p><%= item.description %></p> - <% end %> - -<% end %> - -<%= render :partial => 'shared/related' %> diff --git a/vendor/plugins/interlock/test/integration/app/app/views/items/recent.rhtml b/vendor/plugins/interlock/test/integration/app/app/views/items/recent.rhtml deleted file mode 100644 index 9b334d749..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/views/items/recent.rhtml +++ /dev/null @@ -1,14 +0,0 @@ - -<h1>Recent</h1> -<% view_cache :tag => [:seconds] do %> - <% if @items.any? %> - <% @items.each do |item| %> - <h3><%= item.name %></h3> - <p><%= item.description %></p> - <% end %> - <% else %> - <h3>Nothing found</h3> - <% end %> -<% end %> - -<%= render :partial => 'shared/related' %> diff --git a/vendor/plugins/interlock/test/integration/app/app/views/items/show.rhtml b/vendor/plugins/interlock/test/integration/app/app/views/items/show.rhtml deleted file mode 100644 index 1b004933e..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/views/items/show.rhtml +++ /dev/null @@ -1,8 +0,0 @@ - -<h1>Show</h1> -<% view_cache :perform => @perform do %> - <h3><%= @item.name %></h3> - <p><%= @item.description %></p> -<% end %> - -<%= render :partial => 'shared/related' %> diff --git a/vendor/plugins/interlock/test/integration/app/app/views/layouts/application.html.erb b/vendor/plugins/interlock/test/integration/app/app/views/layouts/application.html.erb deleted file mode 100644 index b053bd4e1..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/views/layouts/application.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<html> - <head> - <title>Interlock Test: <%= yield :title %></title> - </head> - <body> - <%= yield %> - </body> -</html> -
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/app/views/shared/_related.rhtml b/vendor/plugins/interlock/test/integration/app/app/views/shared/_related.rhtml deleted file mode 100644 index 1eea19356..000000000 --- a/vendor/plugins/interlock/test/integration/app/app/views/shared/_related.rhtml +++ /dev/null @@ -1,6 +0,0 @@ - -<% view_cache :ignore => :all, :tag => 'related' do %> - <hr> - <h3>Related</h3> - <p><i><%= @related %></i></p> -<% end %> diff --git a/vendor/plugins/interlock/test/integration/app/config/boot.rb b/vendor/plugins/interlock/test/integration/app/config/boot.rb deleted file mode 100644 index cb9a72dad..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/boot.rb +++ /dev/null @@ -1,110 +0,0 @@ -# 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.exists?(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" - 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 - STDERR.puts "Boot.rb loading version #{version}" - gem 'rails', version - else - STDERR.puts "Boot.rb loading latest available version" - gem 'rails' - end - rescue Gem::LoadError => load_error - $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 - end - - class << self - def rubygems_version - Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion - 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 - require 'rubygems' - - unless rubygems_version >= '0.9.4' - $stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.) - exit 1 - end - - rescue LoadError - $stderr.puts %(Rails requires RubyGems >= 0.9.4. 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! diff --git a/vendor/plugins/interlock/test/integration/app/config/database.yml b/vendor/plugins/interlock/test/integration/app/config/database.yml deleted file mode 100644 index c9d56622c..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/database.yml +++ /dev/null @@ -1,24 +0,0 @@ - -development: - adapter: mysql - encoding: utf8 - database: interlock_development - username: root - password: - socket: /tmp/mysql.sock - -test: - adapter: mysql - encoding: utf8 - database: interlock_test - username: root - password: - socket: /tmp/mysql.sock - -production: - adapter: mysql - encoding: utf8 - database: interlock_production - username: root - password: - socket: /tmp/mysql.sock diff --git a/vendor/plugins/interlock/test/integration/app/config/environment.rb b/vendor/plugins/interlock/test/integration/app/config/environment.rb deleted file mode 100644 index db5db62fe..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/environment.rb +++ /dev/null @@ -1,23 +0,0 @@ - -require File.join(File.dirname(__FILE__), 'boot') -require 'action_controller' - -Rails::Initializer.run do |config| - - if ActionController::Base.respond_to? 'session=' - config.action_controller.session = {:session_key => rand.to_s, :secret => '22cde4d5c1a61ba69a81795322cde4d5c1a61ba69a817953'} - end - - # config.to_prepare do - # RAILS_DEFAULT_LOGGER.info "** interlock dependencies:" - # Interlock.dependencies.each do |klass, list| - # RAILS_DEFAULT_LOGGER.info " #{klass}:" - # list.each do |key, scope| - # RAILS_DEFAULT_LOGGER.info " #{key} => #{scope.inspect}" - # end - # end - # end - -end - -ENV['RAILS_ASSET_ID'] = rand.to_s diff --git a/vendor/plugins/interlock/test/integration/app/config/environments/development.rb b/vendor/plugins/interlock/test/integration/app/config/environments/development.rb deleted file mode 100644 index 10840f89b..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/environments/development.rb +++ /dev/null @@ -1,9 +0,0 @@ - -production = (ENV['PRODUCTION'] == "true") - -config.cache_classes = production -config.whiny_nils = true -config.action_controller.consider_all_requests_local = !production -config.action_controller.perform_caching = true -config.action_view.debug_rjs = !production -config.action_mailer.raise_delivery_errors = false diff --git a/vendor/plugins/interlock/test/integration/app/config/environments/production.rb b/vendor/plugins/interlock/test/integration/app/config/environments/production.rb deleted file mode 100644 index cb295b83f..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/environments/production.rb +++ /dev/null @@ -1,18 +0,0 @@ -# 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 - -# Use a different logger for distributed setups -# config.logger = SyslogLogger.new - -# Full error reports are disabled and caching is turned on -config.action_controller.consider_all_requests_local = false -config.action_controller.perform_caching = true - -# 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 diff --git a/vendor/plugins/interlock/test/integration/app/config/environments/test.rb b/vendor/plugins/interlock/test/integration/app/config/environments/test.rb deleted file mode 100644 index 58850a797..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/environments/test.rb +++ /dev/null @@ -1,22 +0,0 @@ -# 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 - -# Disable request forgery protection in test environment -config.action_controller.allow_forgery_protection = false - -# Tell ActionMailer 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 diff --git a/vendor/plugins/interlock/test/integration/app/config/initializers/inflections.rb b/vendor/plugins/interlock/test/integration/app/config/initializers/inflections.rb deleted file mode 100644 index 09158b865..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/initializers/inflections.rb +++ /dev/null @@ -1,10 +0,0 @@ -# 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): -# 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 diff --git a/vendor/plugins/interlock/test/integration/app/config/initializers/mime_types.rb b/vendor/plugins/interlock/test/integration/app/config/initializers/mime_types.rb deleted file mode 100644 index 72aca7e44..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/initializers/mime_types.rb +++ /dev/null @@ -1,5 +0,0 @@ -# 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 diff --git a/vendor/plugins/interlock/test/integration/app/config/memcached.yml b/vendor/plugins/interlock/test/integration/app/config/memcached.yml deleted file mode 100644 index bdd49fc84..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/memcached.yml +++ /dev/null @@ -1,10 +0,0 @@ -defaults: - ttl: 30 - namespace: interlock - sessions: true - client: <%= ENV['CLIENT'] || 'memcached' %> - with_finders: <%= ENV['FINDERS'] || true %> -development: - servers: - - 127.0.0.1:43042 - - 127.0.0.1:43043 diff --git a/vendor/plugins/interlock/test/integration/app/config/routes.rb b/vendor/plugins/interlock/test/integration/app/config/routes.rb deleted file mode 100644 index d94afa1b9..000000000 --- a/vendor/plugins/interlock/test/integration/app/config/routes.rb +++ /dev/null @@ -1,35 +0,0 @@ -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 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 => "welcome" - - # See how all your routes lay out with "rake routes" - - # Install the default routes as the lowest priority. - map.connect ':controller/:action/:id' - map.connect ':controller/:action/:id.:format' -end diff --git a/vendor/plugins/interlock/test/integration/app/db/migrate/001_create_items.rb b/vendor/plugins/interlock/test/integration/app/db/migrate/001_create_items.rb deleted file mode 100644 index 58da1077e..000000000 --- a/vendor/plugins/interlock/test/integration/app/db/migrate/001_create_items.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateItems < ActiveRecord::Migration - def self.up - create_table :items do |t| - t.string :name - t.string :description - t.timestamps - end - end - - def self.down - drop_table :items - end -end diff --git a/vendor/plugins/interlock/test/integration/app/db/migrate/002_create_books.rb b/vendor/plugins/interlock/test/integration/app/db/migrate/002_create_books.rb deleted file mode 100644 index 4e8155f8b..000000000 --- a/vendor/plugins/interlock/test/integration/app/db/migrate/002_create_books.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateBooks < ActiveRecord::Migration - def self.up - create_table :books, :id => false do |t| - t.string :name - t.string :description - t.timestamps - end - add_column :books, :guid, :integer, :primary => true - end - - def self.down - drop_table :books - end -end diff --git a/vendor/plugins/interlock/test/integration/app/db/migrate/003_add_counter_to_items.rb b/vendor/plugins/interlock/test/integration/app/db/migrate/003_add_counter_to_items.rb deleted file mode 100644 index df9f8a9e3..000000000 --- a/vendor/plugins/interlock/test/integration/app/db/migrate/003_add_counter_to_items.rb +++ /dev/null @@ -1,9 +0,0 @@ -class AddCounterToItems < ActiveRecord::Migration - def self.up - add_column :items, :counting_something, :integer, :default => 0 - end - - def self.down - remove_column :items, :countering_something - end -end diff --git a/vendor/plugins/interlock/test/integration/app/doc/README_FOR_APP b/vendor/plugins/interlock/test/integration/app/doc/README_FOR_APP deleted file mode 100644 index fe41f5cc2..000000000 --- a/vendor/plugins/interlock/test/integration/app/doc/README_FOR_APP +++ /dev/null @@ -1,2 +0,0 @@ -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. diff --git a/vendor/plugins/interlock/test/integration/app/public/.htaccess b/vendor/plugins/interlock/test/integration/app/public/.htaccess deleted file mode 100644 index d9d211c05..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/.htaccess +++ /dev/null @@ -1,40 +0,0 @@ -# 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" diff --git a/vendor/plugins/interlock/test/integration/app/public/404.html b/vendor/plugins/interlock/test/integration/app/public/404.html deleted file mode 100644 index eff660b90..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/404.html +++ /dev/null @@ -1,30 +0,0 @@ -<!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>
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/422.html b/vendor/plugins/interlock/test/integration/app/public/422.html deleted file mode 100644 index b54e4a3ca..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/422.html +++ /dev/null @@ -1,30 +0,0 @@ -<!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>
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/500.html b/vendor/plugins/interlock/test/integration/app/public/500.html deleted file mode 100644 index 0e9c14f4c..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/500.html +++ /dev/null @@ -1,30 +0,0 @@ -<!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>
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/dispatch.cgi b/vendor/plugins/interlock/test/integration/app/public/dispatch.cgi deleted file mode 100755 index a76782ae0..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/dispatch.cgi +++ /dev/null @@ -1,10 +0,0 @@ -#!/opt/local/bin/ruby - -require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) - -# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: -# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired -require "dispatcher" - -ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) -Dispatcher.dispatch
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/dispatch.fcgi b/vendor/plugins/interlock/test/integration/app/public/dispatch.fcgi deleted file mode 100755 index a5267664e..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/dispatch.fcgi +++ /dev/null @@ -1,24 +0,0 @@ -#!/opt/local/bin/ruby -# -# You may specify the path to the FastCGI crash log (a log of unhandled -# exceptions which forced the FastCGI instance to exit, great for debugging) -# and the number of requests to process before running garbage collection. -# -# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log -# and the GC period is nil (turned off). A reasonable number of requests -# could range from 10-100 depending on the memory footprint of your app. -# -# Example: -# # Default log path, normal GC behavior. -# RailsFCGIHandler.process! -# -# # Default log path, 50 requests between GC. -# RailsFCGIHandler.process! nil, 50 -# -# # Custom log path, normal GC behavior. -# RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log' -# -require File.dirname(__FILE__) + "/../config/environment" -require 'fcgi_handler' - -RailsFCGIHandler.process! diff --git a/vendor/plugins/interlock/test/integration/app/public/dispatch.rb b/vendor/plugins/interlock/test/integration/app/public/dispatch.rb deleted file mode 100755 index a76782ae0..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/dispatch.rb +++ /dev/null @@ -1,10 +0,0 @@ -#!/opt/local/bin/ruby - -require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) - -# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: -# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired -require "dispatcher" - -ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) -Dispatcher.dispatch
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/favicon.ico b/vendor/plugins/interlock/test/integration/app/public/favicon.ico deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/favicon.ico +++ /dev/null diff --git a/vendor/plugins/interlock/test/integration/app/public/images/rails.png b/vendor/plugins/interlock/test/integration/app/public/images/rails.png Binary files differdeleted file mode 100644 index b8441f182..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/images/rails.png +++ /dev/null diff --git a/vendor/plugins/interlock/test/integration/app/public/index.html b/vendor/plugins/interlock/test/integration/app/public/index.html deleted file mode 100644 index 84b7b57c9..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/index.html +++ /dev/null @@ -1,277 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html> - <head> - <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> - <title>Ruby on Rails: Welcome aboard</title> - <style type="text/css" media="screen"> - body { - margin: 0; - margin-bottom: 25px; - padding: 0; - background-color: #f0f0f0; - font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana"; - font-size: 13px; - color: #333; - } - - h1 { - font-size: 28px; - color: #000; - } - - a {color: #03c} - a:hover { - background-color: #03c; - color: white; - text-decoration: none; - } - - - #page { - background-color: #f0f0f0; - width: 750px; - margin: 0; - margin-left: auto; - margin-right: auto; - } - - #content { - float: left; - background-color: white; - border: 3px solid #aaa; - border-top: none; - padding: 25px; - width: 500px; - } - - #sidebar { - float: right; - width: 175px; - } - - #footer { - clear: both; - } - - - #header, #about, #getting-started { - padding-left: 75px; - padding-right: 30px; - } - - - #header { - background-image: url("images/rails.png"); - background-repeat: no-repeat; - background-position: top left; - height: 64px; - } - #header h1, #header h2 {margin: 0} - #header h2 { - color: #888; - font-weight: normal; - font-size: 16px; - } - - - #about h3 { - margin: 0; - margin-bottom: 10px; - font-size: 14px; - } - - #about-content { - background-color: #ffd; - border: 1px solid #fc0; - margin-left: -11px; - } - #about-content table { - margin-top: 10px; - margin-bottom: 10px; - font-size: 11px; - border-collapse: collapse; - } - #about-content td { - padding: 10px; - padding-top: 3px; - padding-bottom: 3px; - } - #about-content td.name {color: #555} - #about-content td.value {color: #000} - - #about-content.failure { - background-color: #fcc; - border: 1px solid #f00; - } - #about-content.failure p { - margin: 0; - padding: 10px; - } - - - #getting-started { - border-top: 1px solid #ccc; - margin-top: 25px; - padding-top: 15px; - } - #getting-started h1 { - margin: 0; - font-size: 20px; - } - #getting-started h2 { - margin: 0; - font-size: 14px; - font-weight: normal; - color: #333; - margin-bottom: 25px; - } - #getting-started ol { - margin-left: 0; - padding-left: 0; - } - #getting-started li { - font-size: 18px; - color: #888; - margin-bottom: 25px; - } - #getting-started li h2 { - margin: 0; - font-weight: normal; - font-size: 18px; - color: #333; - } - #getting-started li p { - color: #555; - font-size: 13px; - } - - - #search { - margin: 0; - padding-top: 10px; - padding-bottom: 10px; - font-size: 11px; - } - #search input { - font-size: 11px; - margin: 2px; - } - #search-text {width: 170px} - - - #sidebar ul { - margin-left: 0; - padding-left: 0; - } - #sidebar ul h3 { - margin-top: 25px; - font-size: 16px; - padding-bottom: 10px; - border-bottom: 1px solid #ccc; - } - #sidebar li { - list-style-type: none; - } - #sidebar ul.links li { - margin-bottom: 5px; - } - - </style> - <script type="text/javascript" src="javascripts/prototype.js"></script> - <script type="text/javascript" src="javascripts/effects.js"></script> - <script type="text/javascript"> - function about() { - if (Element.empty('about-content')) { - new Ajax.Updater('about-content', 'rails/info/properties', { - method: 'get', - onFailure: function() {Element.classNames('about-content').add('failure')}, - onComplete: function() {new Effect.BlindDown('about-content', {duration: 0.25})} - }); - } else { - new Effect[Element.visible('about-content') ? - 'BlindUp' : 'BlindDown']('about-content', {duration: 0.25}); - } - } - - window.onload = function() { - $('search-text').value = ''; - $('search').onsubmit = function() { - $('search-text').value = 'site:rubyonrails.org ' + $F('search-text'); - } - } - </script> - </head> - <body> - <div id="page"> - <div id="sidebar"> - <ul id="sidebar-items"> - <li> - <form id="search" action="http://www.google.com/search" method="get"> - <input type="hidden" name="hl" value="en" /> - <input type="text" id="search-text" name="q" value="site:rubyonrails.org " /> - <input type="submit" value="Search" /> the Rails site - </form> - </li> - - <li> - <h3>Join the community</h3> - <ul class="links"> - <li><a href="http://www.rubyonrails.org/">Ruby on Rails</a></li> - <li><a href="http://weblog.rubyonrails.org/">Official weblog</a></li> - <li><a href="http://lists.rubyonrails.org/">Mailing lists</a></li> - <li><a href="http://wiki.rubyonrails.org/rails/pages/IRC">IRC channel</a></li> - <li><a href="http://wiki.rubyonrails.org/">Wiki</a></li> - <li><a href="http://dev.rubyonrails.org/">Bug tracker</a></li> - </ul> - </li> - - <li> - <h3>Browse the documentation</h3> - <ul class="links"> - <li><a href="http://api.rubyonrails.org/">Rails API</a></li> - <li><a href="http://stdlib.rubyonrails.org/">Ruby standard library</a></li> - <li><a href="http://corelib.rubyonrails.org/">Ruby core</a></li> - </ul> - </li> - </ul> - </div> - - <div id="content"> - <div id="header"> - <h1>Welcome aboard</h1> - <h2>You’re riding Ruby on Rails!</h2> - </div> - - <div id="about"> - <h3><a href="rails/info/properties" onclick="about(); return false">About your application’s environment</a></h3> - <div id="about-content" style="display: none"></div> - </div> - - <div id="getting-started"> - <h1>Getting started</h1> - <h2>Here’s how to get rolling:</h2> - - <ol> - <li> - <h2>Create your databases and edit <tt>config/database.yml</tt></h2> - <p>Rails needs to know your login and password.</p> - </li> - - <li> - <h2>Use <tt>script/generate</tt> to create your models and controllers</h2> - <p>To see all available options, run it without parameters.</p> - </li> - - <li> - <h2>Set up a default route and remove or rename this file</h2> - <p>Routes are set up in config/routes.rb.</p> - </li> - </ol> - </div> - </div> - - <div id="footer"> </div> - </div> - </body> -</html>
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/javascripts/application.js b/vendor/plugins/interlock/test/integration/app/public/javascripts/application.js deleted file mode 100644 index fe4577696..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/javascripts/application.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults diff --git a/vendor/plugins/interlock/test/integration/app/public/javascripts/controls.js b/vendor/plugins/interlock/test/integration/app/public/javascripts/controls.js deleted file mode 100644 index da7bfa2a7..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/javascripts/controls.js +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2007 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, 'keypress', 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(); - if(Prototype.Browser.WebKit) Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - if(Prototype.Browser.WebKit) 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; - }, - 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)); - } -}); diff --git a/vendor/plugins/interlock/test/integration/app/public/javascripts/dragdrop.js b/vendor/plugins/interlock/test/integration/app/public/javascripts/dragdrop.js deleted file mode 100644 index ccf4a1e45..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/javascripts/dragdrop.js +++ /dev/null @@ -1,972 +0,0 @@ -// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2007 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.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this.element._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.element._originallyAbsolute) - Position.relativize(this.element); - delete this.element._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){ - var s = Sortable.options(element); - - 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')]; -} diff --git a/vendor/plugins/interlock/test/integration/app/public/javascripts/effects.js b/vendor/plugins/interlock/test/integration/app/public/javascripts/effects.js deleted file mode 100644 index 65aed2395..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/javascripts/effects.js +++ /dev/null @@ -1,1120 +0,0 @@ -// Copyright (c) 2005-2007 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) + 0.5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; - }, - pulse: function(pos, pulses) { - pulses = pulses || 5; - return ( - ((pos % (1/pulses)) * pulses).round() == 0 ? - ((pos * pulses * 2) - (pos * pulses * 2).floor()) : - 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) - ); - }, - 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; - - eval('this.render = function(pos){ '+ - 'if (this.state=="idle"){this.state="running";'+ - codeForEvent(this.options,'beforeSetup')+ - (this.setup ? 'this.setup();':'')+ - codeForEvent(this.options,'afterSetup')+ - '};if (this.state=="running"){'+ - 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ - 'this.position=pos;'+ - codeForEvent(this.options,'beforeUpdate')+ - (this.update ? 'this.update(pos);':'')+ - codeForEvent(this.options,'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(), - max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1] > max ? max : 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] || { }; - var oldOpacity = element.getInlineOpacity(); - var transition = options.transition || Effect.Transitions.sinoidal; - var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; - reverser.bind(transition); - 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(hash, property) { - hash.set(property, css[property]); - return hash; - }); - if (!styles.opacity) styles.set('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); diff --git a/vendor/plugins/interlock/test/integration/app/public/javascripts/prototype.js b/vendor/plugins/interlock/test/integration/app/public/javascripts/prototype.js deleted file mode 100644 index 086ba2ea6..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/javascripts/prototype.js +++ /dev/null @@ -1,4200 +0,0 @@ -/* Prototype JavaScript framework, version 1.6.0 - * (c) 2005-2007 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', - - Browser: { - IE: !!(window.attachEvent && !window.opera), - Opera: !!window.opera, - 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, - 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 = Object.extend((function(m) { - return function() { return ancestor[m].apply(this, arguments) }; - })(property).wrap(method), { - valueOf: function() { return method }, - toString: function() { return method.toString() } - }); - } - 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() : object.toString(); - } 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 && object.constructor === Array; - }, - - 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].split(",").invoke("strip"); - 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); - }, - - 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))); - }; - } -}); - -Function.prototype.defer = Function.prototype.delay.curry(0.01); - -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.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('') -}); - -with (String.prototype.escapeHTML) div.appendChild(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); - }.bind(this)); - } -}); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; - -var $break = { }; - -var Enumerable = { - each: function(iterator, context) { - var index = 0; - iterator = iterator.bind(context); - try { - this._each(function(value) { - iterator(value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - }, - - eachSlice: function(number, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var index = -number, slices = [], array = this.toArray(); - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - }, - - all: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function(iterator, context) { - iterator = iterator.bind(context); - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(filter, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(filter); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator(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) { - iterator = iterator.bind(context); - this.each(function(value, index) { - memo = iterator(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 ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator(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) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator, context) { - iterator = iterator.bind(context); - return this.map(function(value, index) { - return {value: value, criteria: iterator(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, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -if (Prototype.Browser.WebKit) { - function $A(iterable) { - if (!iterable) return []; - if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && - iterable.toArray) return iterable.toArray(); - var length = iterable.length, 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) { - $R(0, this, true).each(iterator); - 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) { - 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.map(function(pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return values.map(toQueryPair.curry(key)).join('&'); - } - return toQueryPair(key, values); - }).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 && 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; - } - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name); - } 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); - } 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); - } 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.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -function $(element) { - if (arguments.length > 1) { - for (var i = 0, elements = [], length = arguments.length; i < length; i++) - elements.push($(arguments[i])); - return elements; - } - if (Object.isString(element)) - element = document.getElementById(element); - return Element.extend(element); -} - -if (Prototype.BrowserFeatures.XPath) { - document._getElementsByXPath = function(expression, parentElement) { - var results = []; - var query = document.evaluate(expression, $(parentElement) || document, - null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0, length = query.snapshotLength; i < length; i++) - results.push(Element.extend(query.snapshotItem(i))); - return results; - }; -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Node) var Node = { }; - -if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding - Object.extend(Node, { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12 - }); -} - -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { - attributes = attributes || { }; - tagName = tagName.toLowerCase(); - var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { - tagName = '<' + tagName + ' name="' + attributes.name + '">'; - delete attributes.name; - return Element.writeAttribute(document.createElement(tagName), attributes); - } - if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); - return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); - }; - Object.extend(this.Element, element || { }); -}).call(window); - -Element.cache = { }; - -Element.Methods = { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function(element) { - element = $(element); - Element[Element.visible(element) ? 'hide' : 'show'](element); - return element; - }, - - hide: function(element) { - $(element).style.display = 'none'; - return element; - }, - - show: function(element) { - $(element).style.display = ''; - return element; - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - return element; - }, - - update: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - content = Object.toHTML(content); - element.innerHTML = content.stripScripts(); - content.evalScripts.bind(content).defer(); - return element; - }, - - replace: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - element.parentNode.replaceChild(content, element); - return element; - }, - - insert: function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; - - var content, t, range; - - for (position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - t = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - t.insert(element, content); - continue; - } - - content = Object.toHTML(content); - - range = element.ownerDocument.createRange(); - t.initializeRange(element, range); - t.insert(element, range.createContextualFragment(content.stripScripts())); - - content.evalScripts.bind(content).defer(); - } - - return element; - }, - - wrap: function(element, wrapper, attributes) { - element = $(element); - if (Object.isElement(wrapper)) - $(wrapper).writeAttribute(attributes || { }); - else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); - else wrapper = new Element('div', wrapper); - if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); - return wrapper; - }, - - inspect: function(element) { - element = $(element); - var result = '<' + element.tagName.toLowerCase(); - $H({'id': 'id', 'className': 'class'}).each(function(pair) { - var property = pair.first(), attribute = pair.last(); - var value = (element[property] || '').toString(); - if (value) result += ' ' + attribute + '=' + value.inspect(true); - }); - return result + '>'; - }, - - recursivelyCollect: function(element, property) { - element = $(element); - var elements = []; - while (element = element[property]) - if (element.nodeType == 1) - elements.push(Element.extend(element)); - return elements; - }, - - ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); - }, - - descendants: function(element) { - return $(element).getElementsBySelector("*"); - }, - - firstDescendant: function(element) { - element = $(element).firstChild; - while (element && element.nodeType != 1) element = element.nextSibling; - return $(element); - }, - - immediateDescendants: function(element) { - if (!(element = $(element).firstChild)) return []; - while (element && element.nodeType != 1) element = element.nextSibling; - if (element) return [element].concat($(element).nextSiblings()); - return []; - }, - - previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); - }, - - nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); - }, - - siblings: function(element) { - element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); - }, - - match: function(element, selector) { - if (Object.isString(selector)) - selector = new Selector(selector); - return selector.match($(element)); - }, - - up: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); - return expression ? Selector.findElement(ancestors, expression, index) : - ancestors[index || 0]; - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - var descendants = element.descendants(); - return expression ? Selector.findElement(descendants, expression, index) : - descendants[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); - return expression ? Selector.findElement(previousSiblings, expression, index) : - previousSiblings[index || 0]; - }, - - next: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); - return expression ? Selector.findElement(nextSiblings, expression, index) : - nextSiblings[index || 0]; - }, - - select: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element, args); - }, - - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element.parentNode, args).without(element); - }, - - identify: function(element) { - element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; - if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); - return id; - }, - - readAttribute: function(element, name) { - element = $(element); - if (Prototype.Browser.IE) { - var t = Element._attributeTranslations.read; - if (t.values[name]) return t.values[name](element, name); - if (t.names[name]) name = t.names[name]; - if (name.include(':')) { - return (!element.attributes || !element.attributes[name]) ? null : - element.attributes[name].value; - } - } - return element.getAttribute(name); - }, - - writeAttribute: function(element, name, value) { - element = $(element); - var attributes = { }, t = Element._attributeTranslations.write; - - if (typeof name == 'object') attributes = name; - else attributes[name] = Object.isUndefined(value) ? true : value; - - for (var attr in attributes) { - name = t.names[attr] || attr; - value = attributes[attr]; - if (t.values[attr]) name = t.values[attr](element, value); - if (value === false || value === null) - element.removeAttribute(name); - else if (value === true) - element.setAttribute(name, name); - else element.setAttribute(name, value); - } - return element; - }, - - getHeight: function(element) { - return $(element).getDimensions().height; - }, - - getWidth: function(element) { - return $(element).getDimensions().width; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - var elementClassName = element.className; - return (elementClassName.length > 0 && (elementClassName == className || - new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - if (!element.hasClassName(className)) - element.className += (element.className ? ' ' : '') + className; - return element; - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - element.className = element.className.replace( - new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); - return element; - }, - - toggleClassName: function(element, className) { - if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - var node = element.firstChild; - while (node) { - var nextNode = node.nextSibling; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - element.removeChild(node); - node = nextNode; - } - return element; - }, - - empty: function(element) { - return $(element).innerHTML.blank(); - }, - - descendantOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - var originalAncestor = ancestor; - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (element.sourceIndex && !Prototype.Browser.Opera) { - var e = element.sourceIndex, a = ancestor.sourceIndex, - nextAncestor = ancestor.nextSibling; - if (!nextAncestor) { - do { ancestor = ancestor.parentNode; } - while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); - } - if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); - } - - while (element = element.parentNode) - if (element == originalAncestor) return true; - return false; - }, - - scrollTo: function(element) { - element = $(element); - var pos = element.cumulativeOffset(); - window.scrollTo(pos[0], pos[1]); - return element; - }, - - getStyle: function(element, style) { - element = $(element); - style = style == 'float' ? 'cssFloat' : style.camelize(); - var value = element.style[style]; - if (!value) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } - if (style == 'opacity') return value ? parseFloat(value) : 1.0; - return value == 'auto' ? null : value; - }, - - getOpacity: function(element) { - return $(element).getStyle('opacity'); - }, - - setStyle: function(element, styles) { - element = $(element); - var elementStyle = element.style, match; - if (Object.isString(styles)) { - element.style.cssText += ';' + styles; - return styles.include('opacity') ? - element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]); - else - elementStyle[(property == 'float' || property == 'cssFloat') ? - (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : - property] = styles[property]; - - return element; - }, - - setOpacity: function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - return element; - }, - - getDimensions: function(element) { - element = $(element); - var display = $(element).getStyle('display'); - if (display != 'none' && display != null) // Safari bug - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - var originalDisplay = els.display; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = 'block'; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = originalDisplay; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - return element; - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - return element; - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return element; - element._overflow = Element.getStyle(element, 'overflow') || 'auto'; - if (element._overflow !== 'hidden') - element.style.overflow = 'hidden'; - return element; - }, - - undoClipping: function(element) { - element = $(element); - if (!element._overflow) return element; - element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; - element._overflow = null; - return element; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (element.tagName == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (element.getStyle('position') == 'absolute') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - var offsets = element.positionedOffset(); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; - return element; - }, - - relativize: function(element) { - element = $(element); - if (element.getStyle('position') == 'relative') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - return element; - }, - - cumulativeScrollOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - getOffsetParent: function(element) { - if (element.offsetParent) return $(element.offsetParent); - if (element == document.body) return $(element); - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return $(element); - - return $(document.body); - }, - - viewportOffset: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent == document.body && - Element.getStyle(element, 'position') == 'absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - if (!Prototype.Browser.Opera || element.tagName == 'BODY') { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - - return Element._returnOffset(valueL, valueT); - }, - - clonePosition: function(element, source) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || { }); - - // find page position of source - source = $(source); - var p = source.viewportOffset(); - - // find coordinate system to use - element = $(element); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(element, 'position') == 'absolute') { - parent = element.getOffsetParent(); - delta = parent.viewportOffset(); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if (options.setWidth) element.style.width = source.offsetWidth + 'px'; - if (options.setHeight) element.style.height = source.offsetHeight + 'px'; - return element; - } -}; - -Element.Methods.identify.counter = 1; - -Object.extend(Element.Methods, { - getElementsBySelector: Element.Methods.select, - childElements: Element.Methods.immediateDescendants -}); - -Element._attributeTranslations = { - write: { - names: { - className: 'class', - htmlFor: 'for' - }, - values: { } - } -}; - - -if (!document.createRange || Prototype.Browser.Opera) { - Element.Methods.insert = function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = { bottom: insertions }; - - var t = Element._insertionTranslations, content, position, pos, tagName; - - for (position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - pos = t[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - pos.insert(element, content); - continue; - } - - content = Object.toHTML(content); - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - if (t.tags[tagName]) { - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - if (position == 'top' || position == 'after') fragments.reverse(); - fragments.each(pos.insert.curry(element)); - } - else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); - - content.evalScripts.bind(content).defer(); - } - - return element; - }; -} - -if (Prototype.Browser.Opera) { - Element.Methods._getStyle = Element.Methods.getStyle; - Element.Methods.getStyle = function(element, style) { - switch(style) { - case 'left': - case 'top': - case 'right': - case 'bottom': - if (Element._getStyle(element, 'position') == 'static') return null; - default: return Element._getStyle(element, style); - } - }; - Element.Methods._readAttribute = Element.Methods.readAttribute; - Element.Methods.readAttribute = function(element, attribute) { - if (attribute == 'title') return element.title; - return Element._readAttribute(element, attribute); - }; -} - -else if (Prototype.Browser.IE) { - $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - var position = element.getStyle('position'); - if (position != 'static') return proceed(element); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.getStyle = function(element, style) { - element = $(element); - style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); - var value = element.style[style]; - if (!value && element.currentStyle) value = element.currentStyle[style]; - - if (style == 'opacity') { - if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if (value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - - if (value == 'auto') { - if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset' + style.capitalize()] + 'px'; - return null; - } - return value; - }; - - Element.Methods.setOpacity = function(element, value) { - function stripAlpha(filter){ - return filter.replace(/alpha\([^\)]*\)/gi,''); - } - element = $(element); - var currentStyle = element.currentStyle; - if ((currentStyle && !currentStyle.hasLayout) || - (!currentStyle && element.style.zoom == 'normal')) - element.style.zoom = 1; - - var filter = element.getStyle('filter'), style = element.style; - if (value == 1 || value === '') { - (filter = stripAlpha(filter)) ? - style.filter = filter : style.removeAttribute('filter'); - return element; - } else if (value < 0.00001) value = 0; - style.filter = stripAlpha(filter) + - 'alpha(opacity=' + (value * 100) + ')'; - return element; - }; - - Element._attributeTranslations = { - read: { - names: { - 'class': 'className', - 'for': 'htmlFor' - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: function(element, attribute) { - attribute = element.getAttribute(attribute); - return attribute ? attribute.toString().slice(23, -2) : null; - }, - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); - }, - title: function(element) { - return element.title; - } - } - } - }; - - Element._attributeTranslations.write = { - names: Object.clone(Element._attributeTranslations.read.names), - values: { - checked: function(element, value) { - element.checked = !!value; - }, - - style: function(element, value) { - element.style.cssText = value ? value : ''; - } - } - }; - - Element._attributeTranslations.has = {}; - - $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + - 'encType maxLength readOnly longDesc').each(function(attr) { - Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; - Element._attributeTranslations.has[attr.toLowerCase()] = attr; - }); - - (function(v) { - Object.extend(v, { - href: v._getAttr, - src: v._getAttr, - type: v._getAttr, - action: v._getAttrNode, - disabled: v._flag, - checked: v._flag, - readonly: v._flag, - multiple: v._flag, - onload: v._getEv, - onunload: v._getEv, - onclick: v._getEv, - ondblclick: v._getEv, - onmousedown: v._getEv, - onmouseup: v._getEv, - onmouseover: v._getEv, - onmousemove: v._getEv, - onmouseout: v._getEv, - onfocus: v._getEv, - onblur: v._getEv, - onkeypress: v._getEv, - onkeydown: v._getEv, - onkeyup: v._getEv, - onsubmit: v._getEv, - onreset: v._getEv, - onselect: v._getEv, - onchange: v._getEv - }); - })(Element._attributeTranslations.read.values); -} - -else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1) ? 0.999999 : - (value === '') ? '' : (value < 0.00001) ? 0 : value; - return element; - }; -} - -else if (Prototype.Browser.WebKit) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - - if (value == 1) - if(element.tagName == 'IMG' && element.width) { - element.width++; element.width--; - } else try { - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch (e) { } - - return element; - }; - - // Safari returns margins on body which is incorrect if the child is absolutely - // positioned. For performance reasons, redefine Position.cumulativeOffset for - // KHTML/WebKit only. - Element.Methods.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return Element._returnOffset(valueL, valueT); - }; -} - -if (Prototype.Browser.IE || Prototype.Browser.Opera) { - // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements - Element.Methods.update = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (tagName in Element._insertionTranslations.tags) { - $A(element.childNodes).each(function(node) { element.removeChild(node) }); - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { element.appendChild(node) }); - } - else element.innerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -if (document.createElement('div').outerHTML) { - Element.Methods.replace = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (Element._insertionTranslations.tags[tagName]) { - var nextSibling = element.next(); - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - parent.removeChild(element); - if (nextSibling) - fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); - else - fragments.each(function(node) { parent.appendChild(node) }); - } - else element.outerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -Element._returnOffset = function(l, t) { - var result = [l, t]; - result.left = l; - result.top = t; - return result; -}; - -Element._getContentFromAnonymousElement = function(tagName, html) { - var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; - div.innerHTML = t[0] + html + t[1]; - t[2].times(function() { div = div.firstChild }); - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: { - adjacency: 'beforeBegin', - insert: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - initializeRange: function(element, range) { - range.setStartBefore(element); - } - }, - top: { - adjacency: 'afterBegin', - insert: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - initializeRange: function(element, range) { - range.selectNodeContents(element); - range.collapse(true); - } - }, - bottom: { - adjacency: 'beforeEnd', - insert: function(element, node) { - element.appendChild(node); - } - }, - after: { - adjacency: 'afterEnd', - insert: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - initializeRange: function(element, range) { - range.setStartAfter(element); - } - }, - tags: { - TABLE: ['<table>', '</table>', 1], - TBODY: ['<table><tbody>', '</tbody></table>', 2], - TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], - TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], - SELECT: ['<select>', '</select>', 1] - } -}; - -(function() { - this.bottom.initializeRange = this.top.initializeRange; - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD - }); -}).call(Element._insertionTranslations); - -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - attribute = Element._attributeTranslations.has[attribute] || attribute; - var node = $(element).getAttributeNode(attribute); - return node && node.specified; - } -}; - -Element.Methods.ByTag = { }; - -Object.extend(Element, Element.Methods); - -if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div').__proto__) { - window.HTMLElement = { }; - window.HTMLElement.prototype = document.createElement('div').__proto__; - Prototype.BrowserFeatures.ElementExtensions = true; -} - -Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) - return Prototype.K; - - var Methods = { }, ByTag = Element.Methods.ByTag; - - var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || - element.nodeType != 1 || element == window) return element; - - var methods = Object.clone(Methods), - tagName = element.tagName, property, value; - - // extend methods for specific tags - if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - - for (property in methods) { - value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } - - element._extendedByPrototype = Prototype.emptyFunction; - return element; - - }, { - refresh: function() { - // extend methods for all tags (Safari doesn't need this) - if (!Prototype.BrowserFeatures.ElementExtensions) { - Object.extend(Methods, Element.Methods); - Object.extend(Methods, Element.Methods.Simulated); - } - } - }); - - extend.refresh(); - return extend; -})(); - -Element.hasAttribute = function(element, attribute) { - if (element.hasAttribute) return element.hasAttribute(attribute); - return Element.Methods.Simulated.hasAttribute(element, attribute); -}; - -Element.addMethods = function(methods) { - var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; - - if (!methods) { - Object.extend(Form, Form.Methods); - Object.extend(Form.Element, Form.Element.Methods); - Object.extend(Element.Methods.ByTag, { - "FORM": Object.clone(Form.Methods), - "INPUT": Object.clone(Form.Element.Methods), - "SELECT": Object.clone(Form.Element.Methods), - "TEXTAREA": Object.clone(Form.Element.Methods) - }); - } - - if (arguments.length == 2) { - var tagName = methods; - methods = arguments[1]; - } - - if (!tagName) Object.extend(Element.Methods, methods || { }); - else { - if (Object.isArray(tagName)) tagName.each(extend); - else extend(tagName); - } - - function extend(tagName) { - tagName = tagName.toUpperCase(); - if (!Element.Methods.ByTag[tagName]) - Element.Methods.ByTag[tagName] = { }; - Object.extend(Element.Methods.ByTag[tagName], methods); - } - - function copy(methods, destination, onlyIfAbsent) { - onlyIfAbsent = onlyIfAbsent || false; - for (var property in methods) { - var value = methods[property]; - if (!Object.isFunction(value)) continue; - if (!onlyIfAbsent || !(property in destination)) - destination[property] = value.methodize(); - } - } - - function findDOMClass(tagName) { - var klass; - var trans = { - "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", - "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", - "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", - "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", - "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": - "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": - "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": - "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": - "FrameSet", "IFRAME": "IFrame" - }; - if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName.capitalize() + 'Element'; - if (window[klass]) return window[klass]; - - window[klass] = { }; - window[klass].prototype = document.createElement(tagName).__proto__; - return window[klass]; - } - - if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); - } - - if (F.SpecificElementExtensions) { - for (var tag in Element.Methods.ByTag) { - var klass = findDOMClass(tag); - if (Object.isUndefined(klass)) continue; - copy(T[tag], klass.prototype); - } - } - - Object.extend(Element, Element.Methods); - delete Element.ByTag; - - if (Element.extend.refresh) Element.extend.refresh(); - Element.cache = { }; -}; - -document.viewport = { - getDimensions: function() { - var dimensions = { }; - $w('width height').each(function(d) { - var D = d.capitalize(); - dimensions[d] = self['inner' + D] || - (document.documentElement['client' + D] || document.body['client' + D]); - }); - return dimensions; - }, - - getWidth: function() { - return this.getDimensions().width; - }, - - getHeight: function() { - return this.getDimensions().height; - }, - - getScrollOffsets: function() { - return Element._returnOffset( - window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); - } -}; -/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, - * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style - * license. Please see http://www.yui-ext.com/ for more information. */ - -var Selector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - this.compileMatcher(); - }, - - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; - - var e = this.expression; - - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; - - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) - return false; - - return true; - }, - - compileMatcher: function() { - if (this.shouldUseXPath()) - return this.compileXPathMatcher(); - - var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; - - if (Selector._cache[e]) { - this.matcher = Selector._cache[e]; - return; - } - - this.matcher = ["this.matcher = function(root) {", - "var r = root, h = Selector.handlers, c = false, n;"]; - - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : - new Template(c[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.matcher.push("return h.unique(n);\n}"); - eval(this.matcher.join('\n')); - Selector._cache[this.expression] = this.matcher; - }, - - compileXPathMatcher: function() { - var e = this.expression, ps = Selector.patterns, - x = Selector.xpath, le, m; - - if (Selector._cache[e]) { - this.xpath = Selector._cache[e]; return; - } - - this.matcher = ['.//*']; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - if (m = e.match(ps[i])) { - this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : - new Template(x[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.xpath = this.matcher.join(''); - Selector._cache[this.expression] = this.xpath; - }, - - findElements: function(root) { - root = root || document; - if (this.xpath) return document._getElementsByXPath(this.xpath, root); - return this.matcher(root); - }, - - match: function(element) { - this.tokens = []; - - var e = this.expression, ps = Selector.patterns, as = Selector.assertions; - var le, p, m; - - while (e && le !== e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - // use the Selector.assertions methods unless the selector - // is too complex. - if (as[i]) { - this.tokens.push([i, Object.clone(m)]); - e = e.replace(m[0], ''); - } else { - // reluctantly do a document-wide search - // and look for a match in the array - return this.findElements(document).include(element); - } - } - } - } - - var match = true, name, matches; - for (var i = 0, token; token = this.tokens[i]; i++) { - name = token[0], matches = token[1]; - if (!Selector.assertions[name](element, matches)) { - match = false; break; - } - } - - return match; - }, - - toString: function() { - return this.expression; - }, - - inspect: function() { - return "#<Selector:" + this.expression.inspect() + ">"; - } -}); - -Object.extend(Selector, { - _cache: { }, - - xpath: { - descendant: "//*", - child: "/*", - adjacent: "/following-sibling::*[1]", - laterSibling: '/following-sibling::*', - tagName: function(m) { - if (m[1] == '*') return ''; - return "[local-name()='" + m[1].toLowerCase() + - "' or local-name()='" + m[1].toUpperCase() + "']"; - }, - className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", - id: "[@id='#{1}']", - attrPresence: function(m) { - m[1] = m[1].toLowerCase(); - return new Template("[@#{1}]").evaluate(m); - }, - attr: function(m) { - m[1] = m[1].toLowerCase(); - m[3] = m[5] || m[6]; - return new Template(Selector.xpath.operators[m[2]]).evaluate(m); - }, - pseudo: function(m) { - var h = Selector.xpath.pseudos[m[1]]; - if (!h) return ''; - if (Object.isFunction(h)) return h(m); - return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); - }, - operators: { - '=': "[@#{1}='#{3}']", - '!=': "[@#{1}!='#{3}']", - '^=': "[starts-with(@#{1}, '#{3}')]", - '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", - '*=': "[contains(@#{1}, '#{3}')]", - '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", - '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" - }, - pseudos: { - 'first-child': '[not(preceding-sibling::*)]', - 'last-child': '[not(following-sibling::*)]', - 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', - 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", - 'checked': "[@checked]", - 'disabled': "[@disabled]", - 'enabled': "[not(@disabled)]", - 'not': function(m) { - var e = m[6], p = Selector.patterns, - x = Selector.xpath, le, v; - - var exclusion = []; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in p) { - if (m = e.match(p[i])) { - v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); - exclusion.push("(" + v.substring(1, v.length - 1) + ")"); - e = e.replace(m[0], ''); - break; - } - } - } - return "[not(" + exclusion.join(" and ") + ")]"; - }, - 'nth-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); - }, - 'nth-last-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); - }, - 'nth-of-type': function(m) { - return Selector.xpath.pseudos.nth("position() ", m); - }, - 'nth-last-of-type': function(m) { - return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); - }, - 'first-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); - }, - 'last-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); - }, - 'only-of-type': function(m) { - var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); - }, - nth: function(fragment, m) { - var mm, formula = m[6], predicate; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - if (mm = formula.match(/^(\d+)$/)) // digit only - return '[' + fragment + "= " + mm[1] + ']'; - if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (mm[1] == "-") mm[1] = -1; - var a = mm[1] ? Number(mm[1]) : 1; - var b = mm[2] ? Number(mm[2]) : 0; - predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + - "((#{fragment} - #{b}) div #{a} >= 0)]"; - return new Template(predicate).evaluate({ - fragment: fragment, a: a, b: b }); - } - } - } - }, - - criteria: { - tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', - className: 'n = h.className(n, r, "#{1}", c); c = false;', - id: 'n = h.id(n, r, "#{1}", c); c = false;', - attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); - }, - pseudo: function(m) { - if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); - return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); - }, - descendant: 'c = "descendant";', - child: 'c = "child";', - adjacent: 'c = "adjacent";', - laterSibling: 'c = "laterSibling";' - }, - - patterns: { - // combinators must be listed first - // (and descendant needs to be last combinator) - laterSibling: /^\s*~\s*/, - child: /^\s*>\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, - - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/, - attrPresence: /^\[([\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, - - // for Selector.match and Element#match - assertions: { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return Selector.operators[matches[2]](nodeValue, matches[3]); - } - }, - - handlers: { - // UTILITY FUNCTIONS - // joins two collections - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - a.push(node); - return a; - }, - - // marks an array of nodes for counting - mark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._counted = true; - return nodes; - }, - - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._counted = undefined; - return nodes; - }, - - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child - index: function(parentNode, reverse, ofType) { - parentNode._counted = true; - if (reverse) { - for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { - var node = nodes[i]; - if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; - } - }, - - // filters out duplicates and extends all nodes - unique: function(nodes) { - if (nodes.length == 0) return nodes; - var results = [], n; - for (var i = 0, l = nodes.length; i < l; i++) - if (!(n = nodes[i])._counted) { - n._counted = true; - results.push(Element.extend(n)); - } - return Selector.handlers.unmark(results); - }, - - // COMBINATOR FUNCTIONS - descendant: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName('*')); - return results; - }, - - child: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) { - for (var j = 0, child; child = node.childNodes[j]; j++) - if (child.nodeType == 1 && child.tagName != '!') results.push(child); - } - return results; - }, - - adjacent: function(nodes) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - var next = this.nextElementSibling(node); - if (next) results.push(next); - } - return results; - }, - - laterSibling: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, Element.nextSiblings(node)); - return results; - }, - - nextElementSibling: function(node) { - while (node = node.nextSibling) - if (node.nodeType == 1) return node; - return null; - }, - - previousElementSibling: function(node) { - while (node = node.previousSibling) - if (node.nodeType == 1) return node; - return null; - }, - - // TOKEN FUNCTIONS - tagName: function(nodes, root, tagName, combinator) { - tagName = tagName.toUpperCase(); - var results = [], h = Selector.handlers; - if (nodes) { - if (combinator) { - // fastlane for ordinary descendant combinators - if (combinator == "descendant") { - for (var i = 0, node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName(tagName)); - return results; - } else nodes = this[combinator](nodes); - if (tagName == "*") return nodes; - } - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() == tagName) results.push(node); - return results; - } else return root.getElementsByTagName(tagName); - }, - - id: function(nodes, root, id, combinator) { - var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; - if (nodes) { - if (combinator) { - if (combinator == 'child') { - for (var i = 0, node; node = nodes[i]; i++) - if (targetNode.parentNode == node) return [targetNode]; - } else if (combinator == 'descendant') { - for (var i = 0, node; node = nodes[i]; i++) - if (Element.descendantOf(targetNode, node)) return [targetNode]; - } else if (combinator == 'adjacent') { - for (var i = 0, node; node = nodes[i]; i++) - if (Selector.handlers.previousElementSibling(targetNode) == node) - return [targetNode]; - } else nodes = h[combinator](nodes); - } - for (var i = 0, node; node = nodes[i]; i++) - if (node == targetNode) return [targetNode]; - return []; - } - return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; - }, - - className: function(nodes, root, className, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - return Selector.handlers.byClassName(nodes, root, className); - }, - - byClassName: function(nodes, root, className) { - if (!nodes) nodes = Selector.handlers.descendant([root]); - var needle = ' ' + className + ' '; - for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { - nodeClassName = node.className; - if (nodeClassName.length == 0) continue; - if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) - results.push(node); - } - return results; - }, - - attrPresence: function(nodes, root, attr) { - if (!nodes) nodes = root.getElementsByTagName("*"); - var results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (Element.hasAttribute(node, attr)) results.push(node); - return results; - }, - - attr: function(nodes, root, attr, value, operator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - var handler = Selector.operators[operator], results = []; - for (var i = 0, node; node = nodes[i]; i++) { - var nodeValue = Element.readAttribute(node, attr); - if (nodeValue === null) continue; - if (handler(nodeValue, value)) results.push(node); - } - return results; - }, - - pseudo: function(nodes, name, value, root, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - if (!nodes) nodes = root.getElementsByTagName("*"); - return Selector.pseudos[name](nodes, value, root); - } - }, - - pseudos: { - 'first-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.previousElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'last-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.nextElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'only-child': function(nodes, value, root) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) - results.push(node); - return results; - }, - 'nth-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root); - }, - 'nth-last-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true); - }, - 'nth-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, false, true); - }, - 'nth-last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true, true); - }, - 'first-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, false, true); - }, - 'last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, true, true); - }, - 'only-of-type': function(nodes, formula, root) { - var p = Selector.pseudos; - return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); - }, - - // handles the an+b logic - getIndices: function(a, b, total) { - if (a == 0) return b > 0 ? [b] : []; - return $R(1, total).inject([], function(memo, i) { - if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); - return memo; - }); - }, - - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type - nth: function(nodes, formula, root, reverse, ofType) { - if (nodes.length == 0) return []; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - var h = Selector.handlers, results = [], indexed = [], m; - h.mark(nodes); - for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._counted) { - h.index(node.parentNode, reverse, ofType); - indexed.push(node.parentNode); - } - } - if (formula.match(/^\d+$/)) { // just a number - formula = Number(formula); - for (var i = 0, node; node = nodes[i]; i++) - if (node.nodeIndex == formula) results.push(node); - } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (m[1] == "-") m[1] = -1; - var a = m[1] ? Number(m[1]) : 1; - var b = m[2] ? Number(m[2]) : 0; - var indices = Selector.pseudos.getIndices(a, b, nodes.length); - for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { - for (var j = 0; j < l; j++) - if (node.nodeIndex == indices[j]) results.push(node); - } - } - h.unmark(nodes); - h.unmark(indexed); - return results; - }, - - 'empty': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes - if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; - results.push(node); - } - return results; - }, - - 'not': function(nodes, selector, root) { - var h = Selector.handlers, selectorType, m; - var exclusions = new Selector(selector).findElements(root); - h.mark(exclusions); - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node._counted) results.push(node); - h.unmark(exclusions); - return results; - }, - - 'enabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node.disabled) results.push(node); - return results; - }, - - 'disabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.disabled) results.push(node); - return results; - }, - - 'checked': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.checked) results.push(node); - return results; - } - }, - - operators: { - '=': function(nv, v) { return nv == v; }, - '!=': function(nv, v) { return nv != v; }, - '^=': function(nv, v) { return nv.startsWith(v); }, - '$=': function(nv, v) { return nv.endsWith(v); }, - '*=': function(nv, v) { return nv.include(v); }, - '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, - '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } - }, - - matchElements: function(elements, expression) { - var matches = new Selector(expression).findElements(), h = Selector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._counted) results.push(element); - h.unmark(matches); - return results; - }, - - findElement: function(elements, expression, index) { - if (Object.isNumber(expression)) { - index = expression; expression = false; - } - return Selector.matchElements(elements, expression || '*')[index || 0]; - }, - - findChildElements: function(element, expressions) { - var exprs = expressions.join(','); - expressions = []; - exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - var results = [], h = Selector.handlers; - for (var i = 0, l = expressions.length, selector; i < l; i++) { - selector = new Selector(expressions[i].strip()); - h.concat(results, selector.findElements(element)); - } - return (l > 1) ? h.unique(results) : results; - } -}); - -if (Prototype.Browser.IE) { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. - Selector.handlers.concat = function(a, b) { - for (var i = 0, node; node = b[i]; i++) - if (node.tagName !== "!") a.push(node); - return a; - }; -} - -function $$() { - return Selector.findChildElements(document, $A(arguments)); -} -var Form = { - reset: function(form) { - $(form).reset(); - return form; - }, - - serializeElements: function(elements, options) { - if (typeof options != 'object') options = { hash: !!options }; - else if (Object.isUndefined(options.hash)) options.hash = true; - var key, value, submitted = false, submit = options.submit; - - var data = elements.inject({ }, function(result, element) { - if (!element.disabled && element.name) { - key = element.name; value = $(element).getValue(); - if (value != null && (element.type != 'submit' || (!submitted && - submit !== false && (!submit || key == submit) && (submitted = true)))) { - if (key in result) { - // a key is already present; construct an array of values - if (!Object.isArray(result[key])) result[key] = [result[key]]; - result[key].push(value); - } - else result[key] = value; - } - } - return result; - }); - - return options.hash ? data : Object.toQueryString(data); - } -}; - -Form.Methods = { - serialize: function(form, options) { - return Form.serializeElements(Form.getElements(form), options); - }, - - getElements: function(form) { - return $A($(form).getElementsByTagName('*')).inject([], - function(elements, child) { - if (Form.Element.Serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - } - ); - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) return $A(inputs).map(Element.extend); - - for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || (name && input.name != name)) - continue; - matchingInputs.push(Element.extend(input)); - } - - return matchingInputs; - }, - - disable: function(form) { - form = $(form); - Form.getElements(form).invoke('disable'); - return form; - }, - - enable: function(form) { - form = $(form); - Form.getElements(form).invoke('enable'); - return form; - }, - - findFirstElement: function(form) { - var elements = $(form).getElements().findAll(function(element) { - return 'hidden' != element.type && !element.disabled; - }); - var firstByIndex = elements.findAll(function(element) { - return element.hasAttribute('tabIndex') && element.tabIndex >= 0; - }).sortBy(function(element) { return element.tabIndex }).first(); - - return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - form = $(form); - form.findFirstElement().activate(); - return form; - }, - - request: function(form, options) { - form = $(form), options = Object.clone(options || { }); - - var params = options.parameters, action = form.readAttribute('action') || ''; - if (action.blank()) action = window.location.href; - options.parameters = form.serialize(true); - - if (params) { - if (Object.isString(params)) params = params.toQueryParams(); - Object.extend(options.parameters, params); - } - - if (form.hasAttribute('method') && !options.method) - options.method = form.method; - - return new Ajax.Request(action, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -Form.Element = { - focus: function(element) { - $(element).focus(); - return element; - }, - - select: function(element) { - $(element).select(); - return element; - } -}; - -Form.Element.Methods = { - serialize: function(element) { - element = $(element); - if (!element.disabled && element.name) { - var value = element.getValue(); - if (value != undefined) { - var pair = { }; - pair[element.name] = value; - return Object.toQueryString(pair); - } - } - return ''; - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - return Form.Element.Serializers[method](element); - }, - - setValue: function(element, value) { - element = $(element); - var method = element.tagName.toLowerCase(); - Form.Element.Serializers[method](element, value); - return element; - }, - - clear: function(element) { - $(element).value = ''; - return element; - }, - - present: function(element) { - return $(element).value != ''; - }, - - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) - element.select(); - } catch (e) { } - return element; - }, - - disable: function(element) { - element = $(element); - element.blur(); - element.disabled = true; - return element; - }, - - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = { - input: function(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element, value); - default: - return Form.Element.Serializers.textarea(element, value); - } - }, - - inputSelector: function(element, value) { - if (Object.isUndefined(value)) return element.checked ? element.value : null; - else element.checked = !!value; - }, - - textarea: function(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - }, - - select: function(element, index) { - if (Object.isUndefined(index)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, value, single = !Object.isArray(index); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - value = this.optionValue(opt); - if (single) { - if (value == index) { - opt.selected = true; - return; - } - } - else opt.selected = index.include(value); - } - } - }, - - selectOne: function(element) { - var index = element.selectedIndex; - return index >= 0 ? this.optionValue(element.options[index]) : null; - }, - - selectMany: function(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(this.optionValue(opt)); - } - return values; - }, - - optionValue: function(opt) { - // extend element because hasAttribute may not be native - return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; - } -}; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = Class.create(PeriodicalExecuter, { - initialize: function($super, element, frequency, callback) { - $super(callback, frequency); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) var Event = { }; - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: { }, - - relatedTarget: function(event) { - var element; - switch(event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } -}); - -Event.Methods = (function() { - var isButton; - - if (Prototype.Browser.IE) { - var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; - }; - - } else if (Prototype.Browser.WebKit) { - isButton = function(event, code) { - switch (code) { - case 0: return event.which == 1 && !event.metaKey; - case 1: return event.which == 1 && event.metaKey; - default: return false; - } - }; - - } else { - isButton = function(event, code) { - return event.which ? (event.which === code + 1) : (event.button === code); - }; - } - - return { - isLeftClick: function(event) { return isButton(event, 0) }, - isMiddleClick: function(event) { return isButton(event, 1) }, - isRightClick: function(event) { return isButton(event, 2) }, - - element: function(event) { - var node = Event.extend(event).target; - return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); - }, - - findElement: function(event, expression) { - var element = Event.element(event); - if (!expression) return element; - var elements = [element].concat(element.ancestors()); - return Selector.findElement(elements, expression, 0); - }, - - pointer: function(event) { - return { - x: event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)), - y: event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)) - }; - }, - - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, - - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; - } - }; -})(); - -Event.extend = (function() { - var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { - m[name] = Event.Methods[name].methodize(); - return m; - }); - - if (Prototype.Browser.IE) { - Object.extend(methods, { - stopPropagation: function() { this.cancelBubble = true }, - preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } - }); - - return function(event) { - if (!event) return false; - if (event._extendedByPrototype) return event; - - event._extendedByPrototype = Prototype.emptyFunction; - var pointer = Event.pointer(event); - Object.extend(event, { - target: event.srcElement, - relatedTarget: Event.relatedTarget(event), - pageX: pointer.x, - pageY: pointer.y - }); - return Object.extend(event, methods); - }; - - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; - Object.extend(Event.prototype, methods); - return Prototype.K; - } -})(); - -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._eventID) return element._eventID; - arguments.callee.id = arguments.callee.id || 1; - return element._eventID = ++arguments.callee.id; - } - - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } - - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } - - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } - - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; - - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) - return false; - - Event.extend(event); - handler.call(element, event) - }; - - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } - - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } - - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); - } - - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; - } - - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } - - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); - - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; - - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); - } - - return element; - }, - - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); - - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; - - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } - - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; - - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } - - destroyWrapper(id, eventName, handler); - - return element; - }, - - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; - - if (document.createEvent) { - var event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - var event = document.createEventObject(); - event.eventType = "ondataavailable"; - } - - event.eventName = eventName; - event.memo = memo || { }; - - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); - } - - return Event.extend(event); - } - }; -})()); - -Object.extend(Event, Event.Methods); - -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); - -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize() -}); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ - - var timer, fired = false; - - function fireContentLoadedEvent() { - if (fired) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); - fired = true; - } - - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); - - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); - } - - } else { - document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); - $("__onDOMContentLoaded").onreadystatechange = function() { - if (this.readyState == "complete") { - this.onreadystatechange = null; - fireContentLoadedEvent(); - } - }; - } -})(); -/*------------------------------- DEPRECATED -------------------------------*/ - -Hash.toQueryString = Object.toQueryString; - -var Toggle = { display: Element.toggle }; - -Element.Methods.childOf = Element.Methods.descendantOf; - -var Insertion = { - Before: function(element, content) { - return Element.insert(element, {before:content}); - }, - - Top: function(element, content) { - return Element.insert(element, {top:content}); - }, - - Bottom: function(element, content) { - return Element.insert(element, {bottom:content}); - }, - - After: function(element, content) { - return Element.insert(element, {after:content}); - } -}; - -var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); - -// This should be moved to script.aculo.us; notice the deprecated methods -// further below, that map to the newer Element methods. -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = Element.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = Element.cumulativeScrollOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = Element.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - // Deprecation layer -- use newer Element methods now (1.5.2). - - cumulativeOffset: Element.Methods.cumulativeOffset, - - positionedOffset: Element.Methods.positionedOffset, - - absolutize: function(element) { - Position.prepare(); - return Element.absolutize(element); - }, - - relativize: function(element) { - Position.prepare(); - return Element.relativize(element); - }, - - realOffset: Element.Methods.cumulativeScrollOffset, - - offsetParent: Element.Methods.getOffsetParent, - - page: Element.Methods.viewportOffset, - - clone: function(source, target, options) { - options = options || { }; - return Element.clonePosition(target, source, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ - function iter(name) { - return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; - } - - instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? - function(element, className) { - className = className.toString().strip(); - var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); - return cond ? document._getElementsByXPath('.//*' + cond, element) : []; - } : function(element, className) { - className = className.toString().strip(); - var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); - if (!classNames && !className) return elements; - - var nodes = $(element).getElementsByTagName('*'); - className = ' ' + className + ' '; - - for (var i = 0, child, cn; child = nodes[i]; i++) { - if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || - (classNames && classNames.all(function(name) { - return !name.toString().blank() && cn.include(' ' + name + ' '); - })))) - elements.push(Element.extend(child)); - } - return elements; - }; - - return function(className, parentElement) { - return $(parentElement || document.body).getElementsByClassName(className); - }; -}(Element.Methods); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set($A(this).concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set($A(this).without(classNameToRemove).join(' ')); - }, - - toString: function() { - return $A(this).join(' '); - } -}; - -Object.extend(Element.ClassNames.prototype, Enumerable); - -/*--------------------------------------------------------------------------*/ - -Element.addMethods();
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/app/public/robots.txt b/vendor/plugins/interlock/test/integration/app/public/robots.txt deleted file mode 100644 index 085187fa5..000000000 --- a/vendor/plugins/interlock/test/integration/app/public/robots.txt +++ /dev/null @@ -1,5 +0,0 @@ -# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file -# -# To ban all spiders from the entire site uncomment the next two lines: -# User-Agent: * -# Disallow: / diff --git a/vendor/plugins/interlock/test/integration/app/script/about b/vendor/plugins/interlock/test/integration/app/script/about deleted file mode 100755 index cd38a32ab..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/about +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/about' diff --git a/vendor/plugins/interlock/test/integration/app/script/console b/vendor/plugins/interlock/test/integration/app/script/console deleted file mode 100755 index 498077ab3..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/console +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/console' diff --git a/vendor/plugins/interlock/test/integration/app/script/destroy b/vendor/plugins/interlock/test/integration/app/script/destroy deleted file mode 100755 index a4df765a3..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/destroy +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/destroy' diff --git a/vendor/plugins/interlock/test/integration/app/script/generate b/vendor/plugins/interlock/test/integration/app/script/generate deleted file mode 100755 index 173a9f147..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/generate +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/generate' diff --git a/vendor/plugins/interlock/test/integration/app/script/performance/benchmarker b/vendor/plugins/interlock/test/integration/app/script/performance/benchmarker deleted file mode 100755 index c842d35d3..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/performance/benchmarker +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/performance/benchmarker' diff --git a/vendor/plugins/interlock/test/integration/app/script/performance/profiler b/vendor/plugins/interlock/test/integration/app/script/performance/profiler deleted file mode 100755 index d855ac8b1..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/performance/profiler +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/performance/profiler' diff --git a/vendor/plugins/interlock/test/integration/app/script/performance/request b/vendor/plugins/interlock/test/integration/app/script/performance/request deleted file mode 100755 index ae3f38c74..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/performance/request +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/performance/request' diff --git a/vendor/plugins/interlock/test/integration/app/script/plugin b/vendor/plugins/interlock/test/integration/app/script/plugin deleted file mode 100755 index 87cd2070f..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/plugin +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/plugin' diff --git a/vendor/plugins/interlock/test/integration/app/script/process/inspector b/vendor/plugins/interlock/test/integration/app/script/process/inspector deleted file mode 100755 index bf25ad86d..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/process/inspector +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/process/inspector' diff --git a/vendor/plugins/interlock/test/integration/app/script/process/reaper b/vendor/plugins/interlock/test/integration/app/script/process/reaper deleted file mode 100755 index c77f04535..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/process/reaper +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/process/reaper' diff --git a/vendor/plugins/interlock/test/integration/app/script/process/spawner b/vendor/plugins/interlock/test/integration/app/script/process/spawner deleted file mode 100755 index 7118f3983..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/process/spawner +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/process/spawner' diff --git a/vendor/plugins/interlock/test/integration/app/script/runner b/vendor/plugins/interlock/test/integration/app/script/runner deleted file mode 100755 index a4a7cb25b..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/runner +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/runner' diff --git a/vendor/plugins/interlock/test/integration/app/script/server b/vendor/plugins/interlock/test/integration/app/script/server deleted file mode 100755 index 3c67f39b6..000000000 --- a/vendor/plugins/interlock/test/integration/app/script/server +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/server' diff --git a/vendor/plugins/interlock/test/integration/app/test/fixtures/books.yml b/vendor/plugins/interlock/test/integration/app/test/fixtures/books.yml deleted file mode 100644 index 7841212db..000000000 --- a/vendor/plugins/interlock/test/integration/app/test/fixtures/books.yml +++ /dev/null @@ -1,12 +0,0 @@ -one: - guid: 1137 - name: Book of Shred - description: The epic and definitive guide to shredding. - created_at: 2007-12-04 13:47:27 - updated_at: 2007-12-04 13:47:27 -two: - guid: 2001 - name: Red Hot and Rollin - description: Rip City Baby! - created_at: 2007-12-04 13:47:27 - updated_at: 2007-12-04 13:47:27 diff --git a/vendor/plugins/interlock/test/integration/app/test/fixtures/items.yml b/vendor/plugins/interlock/test/integration/app/test/fixtures/items.yml deleted file mode 100644 index bf18ebcfe..000000000 --- a/vendor/plugins/interlock/test/integration/app/test/fixtures/items.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html -one: - id: 1 - name: Artichoke - description: The Globe Artichoke (Cynara scolymus) is a perennial thistle originating in southern Europe around the Mediterranean. - created_at: 2007-12-04 13:47:27 - updated_at: 2007-12-04 13:47:27 -two: - id: 2 - name: Fire Apparatus - description: A fire apparatus, fire engine, fire truck, or fire appliance is a vehicle designed to assist in fighting fires, by transporting firefighters to the scene, and providing them with access, water or other equipment. - created_at: 2007-12-04 13:47:27 - updated_at: 2007-12-04 13:47:27 diff --git a/vendor/plugins/interlock/test/integration/app/test/functional/eval_controller_test.rb b/vendor/plugins/interlock/test/integration/app/test/functional/eval_controller_test.rb deleted file mode 100644 index 214842e26..000000000 --- a/vendor/plugins/interlock/test/integration/app/test/functional/eval_controller_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class EvalControllerTest < ActionController::TestCase - tests EvalController - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/vendor/plugins/interlock/test/integration/app/test/functional/items_controller_test.rb b/vendor/plugins/interlock/test/integration/app/test/functional/items_controller_test.rb deleted file mode 100644 index dd6e8e42a..000000000 --- a/vendor/plugins/interlock/test/integration/app/test/functional/items_controller_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class ItemsControllerTest < ActionController::TestCase - tests ItemsController - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/vendor/plugins/interlock/test/integration/app/test/test_helper.rb b/vendor/plugins/interlock/test/integration/app/test/test_helper.rb deleted file mode 100644 index b225a3349..000000000 --- a/vendor/plugins/interlock/test/integration/app/test/test_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -ENV["RAILS_ENV"] = "test" -require File.expand_path(File.dirname(__FILE__) + "/../config/environment") -require 'test_help' - -class Test::Unit::TestCase - self.use_transactional_fixtures = true - self.use_instantiated_fixtures = false - fixtures :all -end diff --git a/vendor/plugins/interlock/test/integration/app/test/unit/item_test.rb b/vendor/plugins/interlock/test/integration/app/test/unit/item_test.rb deleted file mode 100644 index fbb5b711f..000000000 --- a/vendor/plugins/interlock/test/integration/app/test/unit/item_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class ItemTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/vendor/plugins/interlock/test/integration/app/vendor/plugins/interlock b/vendor/plugins/interlock/test/integration/app/vendor/plugins/interlock deleted file mode 120000 index 3efed95be..000000000 --- a/vendor/plugins/interlock/test/integration/app/vendor/plugins/interlock +++ /dev/null @@ -1 +0,0 @@ -../../../../../
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/integration/server_test.rb b/vendor/plugins/interlock/test/integration/server_test.rb deleted file mode 100644 index 67335dd82..000000000 --- a/vendor/plugins/interlock/test/integration/server_test.rb +++ /dev/null @@ -1,230 +0,0 @@ - -require "#{File.dirname(__FILE__)}/../test_helper" -require 'open-uri' -require 'cgi' -require 'fileutils' - -class ServerTest < Test::Unit::TestCase - - PORT = 43041 - URL = "http://localhost:#{PORT}/" - LOG = "#{HERE}/integration/app/log/development.log" - - Dir.chdir RAILS_ROOT do - COVERAGE = "coverage" - RCOV = "#{COVERAGE}/cache-#{PORT}" # The port number must appear in `ps awx` - FileUtils.rm_rf(COVERAGE) if File.exist? COVERAGE - Dir.mkdir COVERAGE - end - - - ### Fragment caching tests - - def test_render - assert_match(/Welcome/, browse) - assert_match(/Artichoke/, browse("items")) - end - - def test_caching - browse("items") - assert_match(/cleared interlock local cache/, log) - assert_match(/all:untagged is running the controller block/, log) - assert_match(/all:untagged wrote/, log) - - truncate - browse("items") - assert_match(/cleared interlock local cache/, log) - assert_no_match(/all:untagged is running the controller block/, log) - assert_no_match(/all:untagged wrote/, log) - assert_match(/all:untagged read from memcached/, log) - end - - def test_controller_respects_log_level - remote = <<-CODE - RAILS_DEFAULT_LOGGER.level = Logger::INFO; - Interlock.config[:log_level] = 'info' - CODE - remote_eval(remote) - - truncate - browse("items") - assert_match(/cleared interlock local cache/, log) - - remote_eval("Interlock.config[:log_level] = 'debug'") - truncate - browse("items") - assert_no_match(/cleared interlock local cache/, log) - end - - def test_broad_invalidation - browse("items") - assert_match(/all:untagged is running the controller block/, log) - assert_match(/all:untagged wrote/, log) - - truncate - assert_equal "true", remote_eval("Item.find(:first).save!") - assert_match(/all:untagged invalidated by rule Item \-\> .all/, log) - browse("items") - assert_match(/all:untagged is running the controller block/, log) - assert_match(/all:untagged wrote/, log) - end - - def test_narrow_invalidation - browse("items/show/1") - assert_match(/show:1:untagged is running the controller block/, log) - - truncate - assert_equal "true", remote_eval("Item.find(2).save!") - assert_no_match(/show:1:untagged invalidated/, log) - browse("items/show/1") - assert_no_match(/show:1:untagged is running the controller block/, log) - - truncate - assert_equal "true", remote_eval("Item.find(1).save!") - assert_match(/show:1:untagged invalidated/, log) - browse("items/show/1") - assert_match(/show:1:untagged is running the controller block/, log) - end - - def test_caching_with_tag - # This test is a little over-complicated - remote_eval("Item.update_all('updated_at = NULL')") - - assert_no_match(/Artichoke/, browse("items/recent?seconds=3")) - assert_match(/recent:all:3 is running the controller block/, log) - - truncate - assert_no_match(/Artichoke/, browse("items/recent?seconds=2")) - assert_match(/recent:all:2 is running the controller block/, log) - assert_no_match(/recent:all:3 is running the controller block/, log) - - truncate - remote_eval("Item.find(1).update_attributes!(:description => 'Changed!')") - assert_match(/Artichoke/, browse("items/recent?seconds=4")) - assert_match(/recent:all:4 is running the controller block/, log) - - truncate - assert_no_match(/Artichoke/, browse("items/recent?seconds=3")) - assert_no_match(/recent:all:3 is running the controller block/, log) - end - - def test_caching_with_perform_false - browse("items/preview/1") - assert_no_match(/preview:1:untagged registered a dependency/, log) - assert_match(/preview:1:untagged is not cached/, log) - - truncate - browse("items/preview/1") - assert_no_match(/preview:1:untagged registered a dependency/, log) - assert_match(/preview:1:untagged is not cached/, log) - end - - def test_caching_with_ignore - assert_match(/Delicious cake/, browse('items')) - assert_match(/any:any:all:related is running the controller block/, log) - - truncate - assert_match(/Delicious cake/, browse("items/show/2")) - assert_no_match(/any:any:all:related is running the controller block/, log) - - truncate - remote_eval("Item.find(1).save!") - assert_match(/Delicious cake/, browse("items/show/2")) - assert_match(/any:any:all:related invalidated/, log) - assert_match(/any:any:all:related is running the controller block/, log) - end - - unless ENV['RAILS_GEM_VERSION'] == "1.2.6" - # This functionality not supported on 1.2.6 - - def test_caching_of_content_for - assert_match(/Interlock Test:\s*\d\s*Items/m, browse("items")) - assert_match(/all:untagged is running the controller block/, log) - assert_match(/all:untagged wrote/, log) - - truncate - assert_match(/Interlock Test:\s*\d\s*Items/m, browse("items")) - # Make sure we didn't copy the content_for too many times - assert_no_match(/Interlock Test:\s*\d\s*Items\s*\d\s*Items/m, browse("items")) - assert_no_match(/all:untagged is running the controller block/, log) - assert_match(/all:untagged read from memcached/, log) - end - - def test_nested_view_caches - assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1")) - assert_match(/detail:1:outer is running the controller block/, log) - assert_match(/detail:1:inner is running the controller block/, log) - - truncate - assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1")) - assert_no_match(/detail:1:outer is running the controller block/, log) - assert_no_match(/detail:1:inner is running the controller block/, log) - - truncate - remote_eval("Item.find(2).save!") - assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1")) - assert_match(/detail:1:outer is running the controller block/, log) - assert_no_match(/detail:1:inner is running the controller block/, log) - - truncate - remote_eval("Item.find(1).save!") - assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1")) - assert_match(/detail:1:outer is running the controller block/, log) - assert_match(/detail:1:inner is running the controller block/, log) - end - end - - ### Support methods - - def setup - # We test against an actual running server in order to lock down the environment - # class reloading situation - Process.fork do - Dir.chdir RAILS_ROOT do - if $rcov - exec("rcov --aggregate #{RCOV} --exclude config\/.*,app\/.*,boot\/.*,script\/server --include-file vendor\/plugins\/interlock\/lib\/.*\.rb script/server -- -p #{PORT} &> #{LOG}") - else - exec("script/server -p #{PORT} &> #{LOG}") - end - end - end - sleep(0.2) while log !~ /available at 0.0.0.0.#{PORT}/ - truncate - end - - def teardown - # Process.kill(9, pid) doesn't work because Mongrel has double-forked itself away - while (pids = `ps awx | grep #{PORT} | grep -v grep | awk '{print $1}'`.split("\n")).any? - pids.each {|pid| system("kill #{pid}")} - sleep(0.2) - end - end - - def truncate - system("> #{LOG}") - end - - def log - File.open(LOG, 'r') do |f| - f.read - end - end - - def browse(url = "") - flag = false - begin - open(URL + url).read - rescue Errno::ECONNREFUSED, OpenURI::HTTPError => e - raise "#{e.to_s}: #{URL + url}" if flag - flag = true - sleep 3 - retry - end - end - - def remote_eval(string) - # Server doesn't run in our process, so invalidations here don't affect it - browse("eval?string=#{CGI.escape(string)}") - end - -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/setup.rb b/vendor/plugins/interlock/test/setup.rb deleted file mode 100644 index 62d2b1ace..000000000 --- a/vendor/plugins/interlock/test/setup.rb +++ /dev/null @@ -1,22 +0,0 @@ - -# Setup integration system for the integration suite - -Dir.chdir "#{File.dirname(__FILE__)}/integration/app/" do - - `ps awx`.split("\n").grep(/4304[1-3]/).map do |process| - system("kill -9 #{process.to_i}") - end - - LOG = "/tmp/memcached.log" - - system "memcached -vv -p 43042 >> #{LOG} 2>&1 &" - system "memcached -vv -p 43043 >> #{LOG} 2>&1 &" - - Dir.chdir "vendor/plugins" do - system "rm interlock; ln -s ../../../../../ interlock" - end - - system "rake db:create" - system "rake db:migrate" - system "rake db:fixtures:load" -end diff --git a/vendor/plugins/interlock/test/teardown.rb b/vendor/plugins/interlock/test/teardown.rb deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/plugins/interlock/test/teardown.rb +++ /dev/null diff --git a/vendor/plugins/interlock/test/test_helper.rb b/vendor/plugins/interlock/test/test_helper.rb deleted file mode 100644 index 95eb1a629..000000000 --- a/vendor/plugins/interlock/test/test_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ - -$VERBOSE = nil -require 'rubygems' -require 'test/unit' -require 'echoe' -require 'multi_rails_init' - -if defined? ENV['MULTIRAILS_RAILS_VERSION'] - ENV['RAILS_GEM_VERSION'] = ENV['MULTIRAILS_RAILS_VERSION'] -end - -$rcov = ENV['RCOV'] -require 'ruby-debug' unless $rcov - -Echoe.silence do - HERE = File.expand_path(File.dirname(__FILE__)) - $LOAD_PATH << HERE -end - -require 'integration/app/config/environment' diff --git a/vendor/plugins/interlock/test/unit/active_record_test.rb b/vendor/plugins/interlock/test/unit/active_record_test.rb deleted file mode 100644 index 76c218fbb..000000000 --- a/vendor/plugins/interlock/test/unit/active_record_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "#{File.dirname(__FILE__)}/../test_helper" - -class FinderTest < Test::Unit::TestCase - def test_reload_should_work - item = Item.find(1) - assert_equal Item.find(1, {}), item.reload - end -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/unit/finder_test.rb b/vendor/plugins/interlock/test/unit/finder_test.rb deleted file mode 100644 index f73020be7..000000000 --- a/vendor/plugins/interlock/test/unit/finder_test.rb +++ /dev/null @@ -1,176 +0,0 @@ - -require "#{File.dirname(__FILE__)}/../test_helper" -require 'fileutils' - -class FinderTest < Test::Unit::TestCase - - LOG = "#{HERE}/integration/app/log/development.log" - - ### Finder caching tests - - def test_find_without_cache - # Non-empty options hash bypasses the cache entirely, including the logging - Item.find(1, {:conditions => "1 = 1"}) - assert_no_match(/model.*Item:find:1:default is loading from the db/, log) - end - - def test_find - assert_equal Item.find(1, {}), - Item.find(1) - assert_match(/model.*Item:find:1:default is loading from the db/, log) - - assert_equal Item.find(1, {}), - Item.find(1) - assert_match(/model.*Item:find:1:default is loading from memcached/, log) - end - - def test_find_with_array - assert_equal Item.find([1, 2], {}), - Item.find([1, 2]) - assert_match(/model.*Item:find:1:default is loading from the db/, log) - assert_match(/model.*Item:find:2:default is loading from the db/, log) - - assert_equal Item.find([1, 2], {}), - Item.find([1, 2]) - assert_match(/model.*Item:find:1:default is loading from memcached/, log) - assert_match(/model.*Item:find:2:default is loading from memcached/, log) - end - - def test_single_element_array_returns_array - assert_equal Item.find([1], {}), - Item.find([1]) - end - - def test_find_raise - assert_raises(ActiveRecord::RecordNotFound) do - Item.find(44) - end - end - - def test_find_with_array_raise - assert_raises(ActiveRecord::RecordNotFound) do - # Once from the DB - Item.find([1, 2, 44]) - end - assert_raises(ActiveRecord::RecordNotFound) do - # Once from Memcached - Item.find([1, 2, 44]) - end - end - - def test_find_with_array_ignores_nil - assert_equal Item.find(1, nil, {}), Item.find(1, nil) - assert_equal Item.find([1, nil], {}), Item.find([1, nil]) - end - - def test_invalidate - Item.find(1).save! - truncate - Item.find(1) - assert_match(/model.*Item:find:1:default is loading from the db/, log) - Item.find(1) - assert_match(/model.*Item:find:1:default is loading from memcached/, log) - end - - def test_reload_should_invalidate - item = Item.find(1) - item.reload - assert_match(/model.*Item:find:1:default invalidated with finders/, log) - truncate - Item.find(1) - assert_match(/model.*Item:find:1:default is loading from memcached/, log) - end - - def test_update_attributes_should_invalidate - item = Item.find(1) - name = item.name - - item.update_attributes!(:name => 'Updated') - updated_item = Item.find(1) - assert_equal 'Updated', item.name - - # Restore name for further tests - item.update_attributes!(:name => name) - end - - def test_update_all_should_invalidate - # TODO - end - - def test_update_counters_should_invalidate - item = Item.find(1) - Item.update_counters(1, :counting_something => 1) - updated_item = Item.find(1) - assert_equal updated_item.counting_something, item.counting_something + 1 - end - - def test_find_all_by_id - assert_equal Item.find_all_by_id(44, {}), - Item.find_all_by_id(44) - assert_equal Item.find_all_by_id([1,2], {}), - Item.find_all_by_id([1,2]) - assert_equal Item.find_all_by_id(1, 2, {}), - Item.find_all_by_id(1, 2) - end - - def test_invalidate_sti - # XXX Need a regression test - end - - def test_find_by_id - assert_equal Item.find_by_id(44, {}), - Item.find_by_id(44) - assert_equal Item.find_by_id([1,2], {}), - Item.find_by_id([1,2]) - assert_equal Item.find_by_id(1, 2, {}), - Item.find_by_id(1, 2) - end - - def test_custom_log_level - old_level = RAILS_DEFAULT_LOGGER.level - RAILS_DEFAULT_LOGGER.level = Logger::INFO - - Interlock.config[:log_level] = 'info' - truncate - Item.find(1) - assert_match(/model.*Item:find:1:default is loading/, log) - - Interlock.config[:log_level] = 'debug' - truncate - Item.find(1) - assert_no_match(/model.*Item:find:1:default is loading/, log) - ensure - RAILS_DEFAULT_LOGGER.level = old_level - end - - def test_find_with_nonstandard_primary_key - db = Book.find_via_db(1137) - cache = Book.find(1137) - assert_equal db, cache - assert_equal Book.find_via_db(1137, 2001, :order => "guid ASC"), Book.find(1137, 2001) - end - - ### Support methods - - def setup - # Change the asset ID; has a similar effect to flushing memcached - @old_asset_id = ENV['RAILS_ASSET_ID'] - ENV['RAILS_ASSET_ID'] = rand.to_s - truncate - end - - def teardown - # Restore the asset id - ENV['RAILS_ASSET_ID'] = @old_asset_id - end - - def truncate - system("> #{LOG}") - end - - def log - File.open(LOG, 'r') do |f| - f.read - end - end -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/unit/interlock_test.rb b/vendor/plugins/interlock/test/unit/interlock_test.rb deleted file mode 100644 index 3ffb8128b..000000000 --- a/vendor/plugins/interlock/test/unit/interlock_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "#{File.dirname(__FILE__)}/../test_helper" - -class InterlockTest < Test::Unit::TestCase - def test_caching_key_requires_controller_and_action - assert_raises ArgumentError do - Interlock.caching_key nil, nil, nil, nil - end - end - - def test_caching_key_prevents_too_long_keys - assert_equal Interlock::KEY_LENGTH_LIMIT, - Interlock.caching_key('controller', 'action', 'id', 'x'*Interlock::KEY_LENGTH_LIMIT).size, - "keys longer than #{Interlock::KEY_LENGTH_LIMIT} will result in errors from memcache-client" - end - - def test_caching_key_strips_whitespace - assert_no_match Interlock::ILLEGAL_KEY_CHARACTERS_PATTERN, - Interlock.caching_key('controller', 'action', 'id', 'tag with illegal characters') - 'generated keys should not contain illegal characters' - end - - def disabled_test_register_dependencies_with_many_keys_one_dependency - assert_nothing_raised do - (1..5000).each do |i| - Interlock.register_dependencies({Item=>:id}, Interlock.caching_key("a"*200, "show", i, nil)) - end - end - end - -end
\ No newline at end of file diff --git a/vendor/plugins/interlock/test/unit/lock_test.rb b/vendor/plugins/interlock/test/unit/lock_test.rb deleted file mode 100644 index bd75ddfee..000000000 --- a/vendor/plugins/interlock/test/unit/lock_test.rb +++ /dev/null @@ -1,45 +0,0 @@ - -require "#{File.dirname(__FILE__)}/../test_helper" - -class LockTest < Test::Unit::TestCase - - KEY = "memcached_test" - LOCK = "lock:#{KEY}" - - def setup - CACHE.delete KEY - CACHE.delete LOCK - end - - def test_unlocked - assert_nil CACHE.get(KEY) - assert_nil CACHE.get(LOCK) - - assert_nothing_raised do - CACHE.lock(KEY) { "A" } - end - - assert_nil CACHE.get(LOCK) - assert_equal("A", CACHE.get(KEY)) - end - - def test_locked - CACHE.set LOCK, "Bogus" - - assert_raises Interlock::LockAcquisitionError do - CACHE.lock(KEY, 30, 2) { "A" } - end - - assert_equal("Bogus", CACHE.get(LOCK)) - assert_nil CACHE.get(KEY) -end - - def test_ensure_lock_release - assert_raises RuntimeError do - CACHE.lock(KEY) { raise } - end - - assert_nil CACHE.get(LOCK) - end - -end |