All, The following patch series ports the entire conductor to Rails 3. With this full set of changes in place, we are able to get a UI that basically works. There are known problems still, in particular around Javascript; but I feel that it is better to get these patches in now, and enlist help from all of the experts. The easiest way to check out whether this works for you is to use Fedora rawhide, where all of the packages are ready to be used. If you don't want to use rawhide, the next best option is to use gem to install rails 3.0.9 and all of its dependencies. We will eventually make packages for Fedora-14 and Fedora-15 available, but that will take additional time. Note that I don't expect anyone to go through a line-by-line review of this series, as it is quite large. Mostly I am looking for reviewers to point out obvious problems and gotchas; we can fix the rest in-tree. This work has been done by a number of people, including Jan Provaznik, Jay Guiditta, Scott Seago, Mo Morsi, Matt Wagner, Tomas Sedovic, and myself (apologies if I left anyone out).
Comments and questions welcome.
From: Jan Provaznik jprovazn@redhat.com
--- src/app/models/instance.rb | 35 ++++++++--------------------- src/app/models/instance_key.rb | 26 ---------------------- src/app/models/instance_observer.rb | 8 ------ src/app/models/provider_account.rb | 6 ----- src/app/util/condormatic.rb | 5 +-- src/features/support/custom.rb | 10 -------- src/spec/factories/provider_account.rb | 3 -- src/spec/models/provider_account_spec.rb | 2 - 8 files changed, 12 insertions(+), 83 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 4700660..af5ec85 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -228,31 +228,6 @@ class Instance < ActiveRecord::Base end end
- def create_unique_key - return unless self.provider_account and self.provider_account.instance_key - # deltacloud/ec2 api's create_key method returns only private part of - # key -> we don't know public part, so we generate new ssh key - # and replace whole authorized_keys file - key_name = "#{self.name}_rsa_#{Time.now.to_f}" - self.instance_key = InstanceKey.new(self.provider_account.instance_key.attributes.merge({ - :instance_key_owner => self, - :name => key_name - })) - begin - self.instance_key.replace_key(self.public_addresses, self.provider_account.instance_key.pem) - self.events.create!(:summary => "successfully updated ssh key", :event_time => Time.now) - rescue - msg = "failed to upload ssh key: #{$!}" - self.last_error = msg - self.events.create!(:summary => msg, :event_time => Time.now) - ensure - # if replace_key fails, we still save instance_key - should be copy of - # provider_account key which was used when launching instance - self.instance_key.save! - self.save! - end - end - def self.get_user_instances_stats(user) stats = { :running_instances => 0, @@ -355,6 +330,16 @@ class Instance < ActiveRecord::Base read_attribute(:public_addresses) end
+ def create_auth_key + raise "instance provider_account is not set" unless self.provider_account + client = self.provider_account.connect + return nil unless client && client.feature?(:instances, :authentication_key) + kname = "#{self.name}_#{Time.now.to_i}_key_#{self.object_id}".gsub(/[^a-zA-Z0-9.-]/, '_') + if key = client.create_key(:name => kname) + self.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => self)) + end + end + named_scope :with_hardware_profile, lambda { {:include => :hardware_profile} } diff --git a/src/app/models/instance_key.rb b/src/app/models/instance_key.rb index 0246c9e..d19c422 100644 --- a/src/app/models/instance_key.rb +++ b/src/app/models/instance_key.rb @@ -40,30 +40,4 @@ require 'base64' class InstanceKey < ActiveRecord::Base
belongs_to :instance_key_owner, :polymorphic => true - - def replace_key(addr, old_pem) - key = generate_ssh_key - replace_on_server(addr, old_pem, key[:public]) - self.pem = key[:private] - end - - private - - def replace_on_server(addr, old_pem, new_pub) - provider_type = self.instance_key_owner.provider_account.provider.provider_type - Net::SCP::start(addr, provider_type.ssh_user, :key_data => [old_pem], :keys => []) do |scp| - scp.upload! StringIO.new(new_pub), File.join(provider_type.home_dir, '/.ssh/authorized_keys') - end - end - - def generate_ssh_key - key = OpenSSL::PKey::RSA.generate(1024) - writer = Net::SSH::Buffer.new - writer.write_key key - ssh_key = Base64.encode64( writer.to_s ).strip.gsub( /[\n\r\t ]/, "" ) - { - :private => key.export, - :public => "#{key.ssh_type} #{ssh_key} #{ENV['USER']}@#{ENV['HOSTNAME']}" - } - end end diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb index c71454a..e80bd40 100644 --- a/src/app/models/instance_observer.rb +++ b/src/app/models/instance_observer.rb @@ -68,14 +68,6 @@ class InstanceObserver < ActiveRecord::Observer end
def after_update(instance) - # we try to generate unique key only when instance is running - # and provider_account for this instance has instance_key (provider account - # instance_key is used as default ssh key when instance is launched) - if instance.state_changed? and instance.state == Instance::STATE_RUNNING and - not instance.instance_key and instance.provider_account and instance.provider_account.instance_key - instance.delay.create_unique_key - end - if instance.state_changed? event = Event.new(:source => instance, :event_time => DateTime.now, :summary => "state changed to #{instance.state}") diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb index 02fdf1d..e817579 100644 --- a/src/app/models/provider_account.rb +++ b/src/app/models/provider_account.rb @@ -201,12 +201,6 @@ class ProviderAccount < ActiveRecord::Base label_value_pairs.sort { |a, b| a[:label] <=> b[:label] } end
- def generate_auth_key - client = connect - return nil unless client && client.feature?(:instances, :authentication_key) - client.create_key(:name => "#{self.name}_#{Time.now.to_i}_key_#{self.object_id}") - end - def credentials_hash @credentials_hash = {} # Credential.all(:conditions => {:provider_account_id => id}, :include => :credential_definition).each do |cred| diff --git a/src/app/util/condormatic.rb b/src/app/util/condormatic.rb index b52ff46..b071bb6 100644 --- a/src/app/util/condormatic.rb +++ b/src/app/util/condormatic.rb @@ -75,12 +75,12 @@ def condormatic_instance_create(task)
overrides = HardwareProfile.generate_override_property_values(instance.hardware_profile, found.hwp) - keyname = found.account.instance_key ? found.account.instance_key.name : '' - pwfilename = write_pw_file(job_name, found.account.credentials_hash['password'])
instance.provider_account = found.account + instance.create_auth_key unless instance.instance_key + keyname = instance.instance_key ? instance.instance_key.name : ''
# I use the 2>&1 to get stderr and stdout together because popen3 does not # support the ability to get the exit value of the command in ruby 1.8. @@ -118,7 +118,6 @@ def condormatic_instance_create(task)
Rails.logger.error "$? (return value?) is #{$?}" raise ("Error calling condor_submit: #{out}") if $? != 0 - task.state = Task::STATE_PENDING instance.state = Instance::STATE_PENDING rescue Exception => ex diff --git a/src/features/support/custom.rb b/src/features/support/custom.rb index 2f6c459..27e5ed1 100644 --- a/src/features/support/custom.rb +++ b/src/features/support/custom.rb @@ -11,20 +11,10 @@ end
ProviderAccount.class_eval do
- alias :generate_auth_key_original :generate_auth_key - def valid_credentials? credentials_hash['username'].to_s == 'mockuser' && credentials_hash['password'].to_s == 'mockpassword' end
- def generate_auth_key - key = OpenStruct.new(:pem => 'PEM') - def key.id - "mock_#{Time.now.to_i}_key_#{self.object_id}" - end - key - end - # def instance_key # @key = mock('Key', :null_object => true) # @key.stub!(:pem).and_return("PEM") diff --git a/src/spec/factories/provider_account.rb b/src/spec/factories/provider_account.rb index d3944bd..28006e9 100644 --- a/src/spec/factories/provider_account.rb +++ b/src/spec/factories/provider_account.rb @@ -2,9 +2,6 @@ Factory.define :provider_account do |f| f.sequence(:label) { |n| "test label#{n}" } f.association :provider f.association :quota - f.after_build do |acc| - acc.stub!(:generate_auth_key).and_return(nil) if acc.respond_to?(:stub!) - end end
Factory.define :mock_provider_account, :parent => :provider_account do |f| diff --git a/src/spec/models/provider_account_spec.rb b/src/spec/models/provider_account_spec.rb index 370a132..c7647e1 100644 --- a/src/spec/models/provider_account_spec.rb +++ b/src/spec/models/provider_account_spec.rb @@ -52,9 +52,7 @@ describe ProviderAccount do
provider_account = Factory.build :ec2_provider_account provider_account.stub!(:connect).and_return(@client) - provider_account.stub!(:generate_auth_key).and_return(@key) provider_account.save - provider_account.instance_key.should_not == nil provider_account.instance_key.pem == "PEM" provider_account.instance_key.id == "1_user" end
Hi Jan,
I thought I was just going to ACK this, but I think there's enough small issues below to warrant re-spinning it
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jan Provaznik jprovazn@redhat.com
I'd like to see your nice explanation referenced in the commit log:
https://fedorahosted.org/pipermail/aeolus-devel/2011-June/002518.html
Also, you mentioned that we still need to:
- remove polymorphic instance key association (not needed for provider account anymore) - delete key (on provider side) on instance stop
I'm fine with you leaving those until later, but please file redmine tasks for them so that they aren't forgotten.
src/app/models/instance.rb | 35 ++++++++--------------------- src/app/models/instance_key.rb | 26 ---------------------- src/app/models/instance_observer.rb | 8 ------ src/app/models/provider_account.rb | 6 ----- src/app/util/condormatic.rb | 5 +-- src/features/support/custom.rb | 10 -------- src/spec/factories/provider_account.rb | 3 -- src/spec/models/provider_account_spec.rb | 2 - 8 files changed, 12 insertions(+), 83 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 4700660..af5ec85 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -228,31 +228,6 @@ class Instance < ActiveRecord::Base end end
- def create_unique_key
- return unless self.provider_account and self.provider_account.instance_key
- # deltacloud/ec2 api's create_key method returns only private part of
- # key -> we don't know public part, so we generate new ssh key
- # and replace whole authorized_keys file
- key_name = "#{self.name}_rsa_#{Time.now.to_f}"
- self.instance_key = InstanceKey.new(self.provider_account.instance_key.attributes.merge({
:instance_key_owner => self,
:name => key_name
- }))
- begin
self.instance_key.replace_key(self.public_addresses, self.provider_account.instance_key.pem)
self.events.create!(:summary => "successfully updated ssh key", :event_time => Time.now)
- rescue
msg = "failed to upload ssh key: #{$!}"
self.last_error = msg
self.events.create!(:summary => msg, :event_time => Time.now)
- ensure
# if replace_key fails, we still save instance_key - should be copy of
# provider_account key which was used when launching instance
self.instance_key.save!
self.save!
- end
- end
- def self.get_user_instances_stats(user) stats = { :running_instances => 0,
@@ -355,6 +330,16 @@ class Instance < ActiveRecord::Base read_attribute(:public_addresses) end
- def create_auth_key
- raise "instance provider_account is not set" unless self.provider_account
- client = self.provider_account.connect
- return nil unless client && client.feature?(:instances, :authentication_key)
- kname = "#{self.name}_#{Time.now.to_i}_key_#{self.object_id}".gsub(/[^a-zA-Z0-9.-]/, '_')
Would it be cleaner to split that out into a key_name helper method?
- if key = client.create_key(:name => kname)
self.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => self))
Why update_attribute instead of:
self.instance_key = InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => self) self.save!
- end
- end
- named_scope :with_hardware_profile, lambda { {:include => :hardware_profile} }
diff --git a/src/app/models/instance_key.rb b/src/app/models/instance_key.rb index 0246c9e..d19c422 100644 --- a/src/app/models/instance_key.rb +++ b/src/app/models/instance_key.rb @@ -40,30 +40,4 @@ require 'base64'
You can remove the base64 and openssl requires now
class InstanceKey < ActiveRecord::Base
belongs_to :instance_key_owner, :polymorphic => true
- def replace_key(addr, old_pem)
- key = generate_ssh_key
- replace_on_server(addr, old_pem, key[:public])
- self.pem = key[:private]
- end
- private
- def replace_on_server(addr, old_pem, new_pub)
- provider_type = self.instance_key_owner.provider_account.provider.provider_type
- Net::SCP::start(addr, provider_type.ssh_user, :key_data => [old_pem], :keys => []) do |scp|
scp.upload! StringIO.new(new_pub), File.join(provider_type.home_dir, '/.ssh/authorized_keys')
- end
- end
- def generate_ssh_key
- key = OpenSSL::PKey::RSA.generate(1024)
- writer = Net::SSH::Buffer.new
- writer.write_key key
- ssh_key = Base64.encode64( writer.to_s ).strip.gsub( /[\n\r\t ]/, "" )
- {
:private => key.export,
:public => "#{key.ssh_type} #{ssh_key} #{ENV['USER']}@#{ENV['HOSTNAME']}"
- }
- end
It's awesome to be getting rid of this mess
You should also eliminate the requirement for the net-scp gem
end diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb index c71454a..e80bd40 100644 --- a/src/app/models/instance_observer.rb +++ b/src/app/models/instance_observer.rb @@ -68,14 +68,6 @@ class InstanceObserver < ActiveRecord::Observer end
def after_update(instance)
- # we try to generate unique key only when instance is running
- # and provider_account for this instance has instance_key (provider account
- # instance_key is used as default ssh key when instance is launched)
- if instance.state_changed? and instance.state == Instance::STATE_RUNNING and
not instance.instance_key and instance.provider_account and instance.provider_account.instance_key
instance.delay.create_unique_key
- end
- if instance.state_changed? event = Event.new(:source => instance, :event_time => DateTime.now, :summary => "state changed to #{instance.state}")
diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb index 02fdf1d..e817579 100644 --- a/src/app/models/provider_account.rb +++ b/src/app/models/provider_account.rb @@ -201,12 +201,6 @@ class ProviderAccount < ActiveRecord::Base label_value_pairs.sort { |a, b| a[:label] <=> b[:label] } end
- def generate_auth_key
- client = connect
- return nil unless client && client.feature?(:instances, :authentication_key)
- client.create_key(:name => "#{self.name}_#{Time.now.to_i}_key_#{self.object_id}")
- end
This code is still used in provider_account_observer if this patch is applied. The patch to remove its use in provider_account_observer should be included in this patch.
Cheers, Mark.
On 07/28/2011 10:50 AM, Mark McLoughlin wrote:
Hi Jan,
I thought I was just going to ACK this, but I think there's enough small issues below to warrant re-spinning it
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jan Provaznikjprovazn@redhat.com
I'd like to see your nice explanation referenced in the commit log:
https://fedorahosted.org/pipermail/aeolus-devel/2011-June/002518.html
Also, you mentioned that we still need to:
- remove polymorphic instance key association (not needed for provider account anymore)
- delete key (on provider side) on instance stop
I'm fine with you leaving those until later, but please file redmine tasks for them so that they aren't forgotten.
src/app/models/instance.rb | 35 ++++++++--------------------- src/app/models/instance_key.rb | 26 ---------------------- src/app/models/instance_observer.rb | 8 ------ src/app/models/provider_account.rb | 6 ----- src/app/util/condormatic.rb | 5 +-- src/features/support/custom.rb | 10 -------- src/spec/factories/provider_account.rb | 3 -- src/spec/models/provider_account_spec.rb | 2 - 8 files changed, 12 insertions(+), 83 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 4700660..af5ec85 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -228,31 +228,6 @@ class Instance< ActiveRecord::Base end end
- def create_unique_key
- return unless self.provider_account and self.provider_account.instance_key
- # deltacloud/ec2 api's create_key method returns only private part of
- # key -> we don't know public part, so we generate new ssh key
- # and replace whole authorized_keys file
- key_name = "#{self.name}_rsa_#{Time.now.to_f}"
- self.instance_key = InstanceKey.new(self.provider_account.instance_key.attributes.merge({
:instance_key_owner => self,
:name => key_name
- }))
- begin
self.instance_key.replace_key(self.public_addresses, self.provider_account.instance_key.pem)
self.events.create!(:summary => "successfully updated ssh key", :event_time => Time.now)
- rescue
msg = "failed to upload ssh key: #{$!}"
self.last_error = msg
self.events.create!(:summary => msg, :event_time => Time.now)
- ensure
# if replace_key fails, we still save instance_key - should be copy of
# provider_account key which was used when launching instance
self.instance_key.save!
self.save!
- end
- end
- def self.get_user_instances_stats(user) stats = { :running_instances => 0,
@@ -355,6 +330,16 @@ class Instance< ActiveRecord::Base read_attribute(:public_addresses) end
- def create_auth_key
- raise "instance provider_account is not set" unless self.provider_account
- client = self.provider_account.connect
- return nil unless client&& client.feature?(:instances, :authentication_key)
- kname = "#{self.name}_#{Time.now.to_i}_key_#{self.object_id}".gsub(/[^a-zA-Z0-9.-]/, '_')
Would it be cleaner to split that out into a key_name helper method?
- if key = client.create_key(:name => kname)
self.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => self))
Why update_attribute instead of:
self.instance_key = InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => self) self.save!
- end
- end
- named_scope :with_hardware_profile, lambda { {:include => :hardware_profile} }
diff --git a/src/app/models/instance_key.rb b/src/app/models/instance_key.rb index 0246c9e..d19c422 100644 --- a/src/app/models/instance_key.rb +++ b/src/app/models/instance_key.rb @@ -40,30 +40,4 @@ require 'base64'
You can remove the base64 and openssl requires now
class InstanceKey< ActiveRecord::Base
belongs_to :instance_key_owner, :polymorphic => true
- def replace_key(addr, old_pem)
- key = generate_ssh_key
- replace_on_server(addr, old_pem, key[:public])
- self.pem = key[:private]
- end
- private
- def replace_on_server(addr, old_pem, new_pub)
- provider_type = self.instance_key_owner.provider_account.provider.provider_type
- Net::SCP::start(addr, provider_type.ssh_user, :key_data => [old_pem], :keys => []) do |scp|
scp.upload! StringIO.new(new_pub), File.join(provider_type.home_dir, '/.ssh/authorized_keys')
- end
- end
- def generate_ssh_key
- key = OpenSSL::PKey::RSA.generate(1024)
- writer = Net::SSH::Buffer.new
- writer.write_key key
- ssh_key = Base64.encode64( writer.to_s ).strip.gsub( /[\n\r\t ]/, "" )
- {
:private => key.export,
:public => "#{key.ssh_type} #{ssh_key} #{ENV['USER']}@#{ENV['HOSTNAME']}"
- }
- end
It's awesome to be getting rid of this mess
You should also eliminate the requirement for the net-scp gem
end diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb index c71454a..e80bd40 100644 --- a/src/app/models/instance_observer.rb +++ b/src/app/models/instance_observer.rb @@ -68,14 +68,6 @@ class InstanceObserver< ActiveRecord::Observer end
def after_update(instance)
- # we try to generate unique key only when instance is running
- # and provider_account for this instance has instance_key (provider account
- # instance_key is used as default ssh key when instance is launched)
- if instance.state_changed? and instance.state == Instance::STATE_RUNNING and
not instance.instance_key and instance.provider_account and instance.provider_account.instance_key
instance.delay.create_unique_key
- end
if instance.state_changed? event = Event.new(:source => instance, :event_time => DateTime.now, :summary => "state changed to #{instance.state}")
diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb index 02fdf1d..e817579 100644 --- a/src/app/models/provider_account.rb +++ b/src/app/models/provider_account.rb @@ -201,12 +201,6 @@ class ProviderAccount< ActiveRecord::Base label_value_pairs.sort { |a, b| a[:label]<=> b[:label] } end
- def generate_auth_key
- client = connect
- return nil unless client&& client.feature?(:instances, :authentication_key)
- client.create_key(:name => "#{self.name}_#{Time.now.to_i}_key_#{self.object_id}")
- end
This code is still used in provider_account_observer if this patch is applied. The patch to remove its use in provider_account_observer should be included in this patch.
Cheers, Mark.
Hi, good points, going to resend. Jan
From: Jan Provaznik jprovazn@redhat.com
No need to create bucket in iwhd anymore, no need to create ssh key for provider account (ssh key is generated per instance) --- src/app/models/provider_account_observer.rb | 34 --------------------- src/config/environment.rb | 2 +- src/spec/models/provider_account_observer_spec.rb | 23 -------------- 3 files changed, 1 insertions(+), 58 deletions(-) delete mode 100644 src/app/models/provider_account_observer.rb delete mode 100644 src/spec/models/provider_account_observer_spec.rb
diff --git a/src/app/models/provider_account_observer.rb b/src/app/models/provider_account_observer.rb deleted file mode 100644 index fd5b65a..0000000 --- a/src/app/models/provider_account_observer.rb +++ /dev/null @@ -1,34 +0,0 @@ -class ProviderAccountObserver < ActiveRecord::Observer - def after_create(account) - # FIXME: new boxgrinder doesn't create bucket for amis automatically, - # for now we create bucket from conductor - # remove this hotfix when fixed on boxgrinder side - if account.provider.provider_type_id == ProviderType.find_by_codename("ec2").id - create_bucket(account) - end - if key = account.generate_auth_key - account.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => account)) - end - account.populate_hardware_profiles - end - - private - - def create_bucket(account) - client = account.connect - bucket_name = "#{account.credentials_hash['account_id']}-imagefactory-amis" - # TODO (jprovazn): getting particular bucket takes long time (core fetches all - # buckets from provider), so we call directly create_bucket, if bucket exists, - # exception should be thrown (actually existing bucket is returned - this - # bug should be fixed soon) - #client.create_bucket(:name => bucket_name) unless client.bucket(bucket_name) - begin - client.create_bucket('id' => bucket_name) - rescue Exception => e - Rails.logger.error e.message - Rails.logger.error e.backtrace.join("\n ") - end - end -end - -ProviderAccountObserver.instance diff --git a/src/config/environment.rb b/src/config/environment.rb index eabb8a8..f657eca 100644 --- a/src/config/environment.rb +++ b/src/config/environment.rb @@ -56,7 +56,7 @@ Rails::Initializer.run do |config|
config.middleware.swap Rack::MethodOverride, 'Rack::RestfulSubmit'
- config.active_record.observers = :instance_observer, :task_observer, :provider_account_observer + config.active_record.observers = :instance_observer, :task_observer # Only load the plugins named here, in the order given. By default, all plugins # in vendor/plugins are loaded in alphabetical order. # :all can be used as a placeholder for all plugins not explicitly named diff --git a/src/spec/models/provider_account_observer_spec.rb b/src/spec/models/provider_account_observer_spec.rb deleted file mode 100644 index 6b7d62a..0000000 --- a/src/spec/models/provider_account_observer_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper' - -describe ProviderAccountObserver do - fixtures :all - - it "should create an instance_key if provider is EC2" do - @client = mock('Conductor', :null_object => true) - @provider = Factory.build :ec2_provider - @key = mock('Key', :null_object => true) - @key.stub!(:pem).and_return("PEM") - @key.stub!(:id).and_return("1_user") - @client.stub!(:"feature?").and_return(true) - @client.stub!(:"create_key").and_return(@key) - - provider_account = Factory.build :ec2_provider_account - provider_account.stub!(:connect).and_return(@client) - provider_account.stub!(:generate_auth_key).and_return(@key) - provider_account.save! - provider_account.instance_key.should_not == nil - provider_account.instance_key.pem == "PEM" - provider_account.instance_key.id == "1_user" - end -end
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jan Provaznik jprovazn@redhat.com
No need to create bucket in iwhd anymore,
Hmm, this is code to create an S3 bucket, not an IWHD bucket
You probably just mis-typed, though, since you're the one that added this code originally:
http://git.fedorahosted.org/git/?p=aeolus/conductor.git;a=commitdiff;h=cbe2d...
no need to create ssh key for provider account (ssh key is generated per instance)
src/app/models/provider_account_observer.rb | 34 --------------------- src/config/environment.rb | 2 +- src/spec/models/provider_account_observer_spec.rb | 23 -------------- 3 files changed, 1 insertions(+), 58 deletions(-) delete mode 100644 src/app/models/provider_account_observer.rb delete mode 100644 src/spec/models/provider_account_observer_spec.rb
diff --git a/src/app/models/provider_account_observer.rb b/src/app/models/provider_account_observer.rb deleted file mode 100644 index fd5b65a..0000000 --- a/src/app/models/provider_account_observer.rb +++ /dev/null @@ -1,34 +0,0 @@ -class ProviderAccountObserver < ActiveRecord::Observer
- def after_create(account)
- # FIXME: new boxgrinder doesn't create bucket for amis automatically,
- # for now we create bucket from conductor
- # remove this hotfix when fixed on boxgrinder side
- if account.provider.provider_type_id == ProviderType.find_by_codename("ec2").id
create_bucket(account)
- end
- if key = account.generate_auth_key
account.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => account))
- end
- account.populate_hardware_profiles
It looks like it's not correct to remove this populate_hardware_profiles call.
I think you should remove the instance key stuff in the previous patch and make this patch just about removing the bucket creation
Cheers, Mark.
On 07/28/2011 04:51 AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jan Provaznikjprovazn@redhat.com
No need to create bucket in iwhd anymore,
Hmm, this is code to create an S3 bucket, not an IWHD bucket
You probably just mis-typed, though, since you're the one that added this code originally:
http://git.fedorahosted.org/git/?p=aeolus/conductor.git;a=commitdiff;h=cbe2d...
no need to create ssh key for provider account (ssh key is generated per instance)
src/app/models/provider_account_observer.rb | 34 --------------------- src/config/environment.rb | 2 +- src/spec/models/provider_account_observer_spec.rb | 23 -------------- 3 files changed, 1 insertions(+), 58 deletions(-) delete mode 100644 src/app/models/provider_account_observer.rb delete mode 100644 src/spec/models/provider_account_observer_spec.rb
diff --git a/src/app/models/provider_account_observer.rb b/src/app/models/provider_account_observer.rb deleted file mode 100644 index fd5b65a..0000000 --- a/src/app/models/provider_account_observer.rb +++ /dev/null @@ -1,34 +0,0 @@ -class ProviderAccountObserver< ActiveRecord::Observer
- def after_create(account)
- # FIXME: new boxgrinder doesn't create bucket for amis automatically,
- # for now we create bucket from conductor
- # remove this hotfix when fixed on boxgrinder side
- if account.provider.provider_type_id == ProviderType.find_by_codename("ec2").id
create_bucket(account)
- end
- if key = account.generate_auth_key
account.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => account))
- end
- account.populate_hardware_profiles
It looks like it's not correct to remove this populate_hardware_profiles call.
I think you should remove the instance key stuff in the previous patch and make this patch just about removing the bucket creation
Cheers, Mark.
Not only that, I'm pretty sure we _do_ still need this bucket creation. One of the 0.3.0 bugs was to fix errors with this. The comment is misleading, as it's not needed for boxgrinder, it's needed for the ec2 tools.
Scott
On 07/28/11 - 10:01:17AM, Scott Seago wrote:
diff --git a/src/app/models/provider_account_observer.rb b/src/app/models/provider_account_observer.rb deleted file mode 100644 index fd5b65a..0000000 --- a/src/app/models/provider_account_observer.rb +++ /dev/null @@ -1,34 +0,0 @@ -class ProviderAccountObserver< ActiveRecord::Observer
- def after_create(account)
- # FIXME: new boxgrinder doesn't create bucket for amis automatically,
- # for now we create bucket from conductor
- # remove this hotfix when fixed on boxgrinder side
- if account.provider.provider_type_id == ProviderType.find_by_codename("ec2").id
create_bucket(account)
- end
- if key = account.generate_auth_key
account.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => account))
- end
- account.populate_hardware_profiles
It looks like it's not correct to remove this populate_hardware_profiles call.
I think you should remove the instance key stuff in the previous patch and make this patch just about removing the bucket creation
Cheers, Mark.
Not only that, I'm pretty sure we _do_ still need this bucket creation. One of the 0.3.0 bugs was to fix errors with this. The comment is misleading, as it's not needed for boxgrinder, it's needed for the ec2 tools.
Oh yeah, that is a really good point. It is arguable whether this bit of logic really belongs here (as it seems to me that this might better live in imagefactory), but we should leave it as-is for now.
On 07/28/2011 04:01 PM, Scott Seago wrote:
On 07/28/2011 04:51 AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jan Provaznikjprovazn@redhat.com
No need to create bucket in iwhd anymore,
Hmm, this is code to create an S3 bucket, not an IWHD bucket
You probably just mis-typed, though, since you're the one that added this code originally:
http://git.fedorahosted.org/git/?p=aeolus/conductor.git;a=commitdiff;h=cbe2d51f5fff
no need to create ssh key for provider account (ssh key is generated per instance)
src/app/models/provider_account_observer.rb | 34 --------------------- src/config/environment.rb | 2 +- src/spec/models/provider_account_observer_spec.rb | 23 -------------- 3 files changed, 1 insertions(+), 58 deletions(-) delete mode 100644 src/app/models/provider_account_observer.rb delete mode 100644 src/spec/models/provider_account_observer_spec.rb
diff --git a/src/app/models/provider_account_observer.rb b/src/app/models/provider_account_observer.rb deleted file mode 100644 index fd5b65a..0000000 --- a/src/app/models/provider_account_observer.rb +++ /dev/null @@ -1,34 +0,0 @@ -class ProviderAccountObserver< ActiveRecord::Observer
- def after_create(account)
- # FIXME: new boxgrinder doesn't create bucket for amis automatically,
- # for now we create bucket from conductor
- # remove this hotfix when fixed on boxgrinder side
- if account.provider.provider_type_id == ProviderType.find_by_codename("ec2").id
create_bucket(account)
- end
- if key = account.generate_auth_key
account.update_attribute(:instance_key, InstanceKey.create!(:pem => key.pem.first, :name => key.id, :instance_key_owner => account))
- end
- account.populate_hardware_profiles
It looks like it's not correct to remove this populate_hardware_profiles call.
I think you should remove the instance key stuff in the previous patch and make this patch just about removing the bucket creation
Cheers, Mark.
Not only that, I'm pretty sure we _do_ still need this bucket creation. One of the 0.3.0 bugs was to fix errors with this. The comment is misleading, as it's not needed for boxgrinder, it's needed for the ec2 tools.
Scott
Not sure which bug you mean, this one? https://bugzilla.redhat.com/show_bug.cgi?id=723926
From description of this bug it's not clear. if Wes reported only error printed he found in a logfile or if image build or something other didn't work.
Not sure where ec2 tools are used except imagefactory, but imagefactory creates bucket itself, also uses different bucket name. Do you know about another place where this could be used?
Anyway I resent only first patch (instance key generation) which now includes instance key stuff from this patch as Mark suggested so this patch is not required anymore for rails 3 upgrade.
Jan
Signed-off-by: Chris Lalancette clalance@redhat.com Signed-off-by: Scott Seago sseago@redhat.com --- aeolus-conductor.spec.in | 9 --- conf/conductor-delayed_job | 77 -------------------- src/Rakefile | 7 -- src/config/environment.rb | 1 - src/config/initializers/delayed_job.rb | 2 - .../migrate/20110124103216_create_delayed_jobs.rb | 21 ------ src/script/delayed_job | 5 -- util/check_services | 2 +- 8 files changed, 1 insertions(+), 123 deletions(-) delete mode 100755 conf/conductor-delayed_job delete mode 100644 src/config/initializers/delayed_job.rb delete mode 100644 src/db/migrate/20110124103216_create_delayed_jobs.rb delete mode 100755 src/script/delayed_job
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in index d2fb7f1..2977df3 100644 --- a/aeolus-conductor.spec.in +++ b/aeolus-conductor.spec.in @@ -34,7 +34,6 @@ Requires: rubygem(rest-client) Requires: rubygem(builder) Requires: rubygem(json) Requires: rubygem(rack-restful_submit) -Requires: rubygem(delayed_job) Requires: rubygem(net-scp) Requires: rubygem(uuidtools) Requires: postgresql @@ -194,7 +193,6 @@ done # copy over init scripts and various config %{__cp} conf/aeolus-conductor %{buildroot}%{_initrddir} %{__cp} conf/conductor-dbomatic %{buildroot}%{_initrddir} -%{__cp} conf/conductor-delayed_job %{buildroot}%{_initrddir} %{__cp} conf/aeolus-conductor-httpd.conf %{buildroot}%{_sysconfdir}/httpd/conf.d/aeolus-conductor.conf %{__cp} conf/aeolus-conductor.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/aeolus-conductor %{__cp} conf/aeolus-conductor.sysconf %{buildroot}%{_sysconfdir}/sysconfig/aeolus-conductor @@ -212,7 +210,6 @@ touch %{buildroot}%{_localstatedir}/log/%{name}/dbomatic.log touch %{buildroot}%{_localstatedir}/run/%{name}/event_log_position
%{__mkdir} -p %{buildroot}%{app_root}/log -touch %{buildroot}%{app_root}/log/delayed_job.log
# copy script files over %{__cp} -r src/script %{buildroot}%{app_root} @@ -247,7 +244,6 @@ fi # Register the services /sbin/chkconfig --add aeolus-conductor /sbin/chkconfig --add conductor-dbomatic -/sbin/chkconfig --add conductor-delayed_job
%preun daemons if [ $1 = 0 ]; then @@ -255,8 +251,6 @@ if [ $1 = 0 ]; then /sbin/chkconfig --del aeolus-conductor /sbin/service conductor-dbomatic stop > /dev/null 2>&1 /sbin/chkconfig --del conductor-dbomatic - /sbin/service conductor-delayed_job stop > /dev/null 2>&1 - /sbin/chkconfig --del conductor-delayed_job fi
%files @@ -271,14 +265,12 @@ fi %{app_root}/log %{app_root}/public %{app_root}/Rakefile -%{app_root}/script/delayed_job %config %{_sysconfdir}/%{name} %doc AUTHORS COPYING
%files daemons %{_initrddir}/aeolus-conductor %{_initrddir}/conductor-dbomatic -%{_initrddir}/conductor-delayed_job %config(noreplace) %{_sysconfdir}/logrotate.d/%{name} %config(noreplace) %{_sysconfdir}/sysconfig/aeolus-conductor %config(noreplace) %{_sysconfdir}/sysconfig/conductor-rails @@ -286,7 +278,6 @@ fi %attr(-, aeolus, aeolus) %{_localstatedir}/lib/%{name} %attr(-, aeolus, aeolus) %{_localstatedir}/run/%{name} %attr(-, aeolus, aeolus) %{_localstatedir}/log/%{name} -%attr(-, aeolus, aeolus) %{app_root}/log/delayed_job.log %doc AUTHORS COPYING
%files doc diff --git a/conf/conductor-delayed_job b/conf/conductor-delayed_job deleted file mode 100755 index 9b7f517..0000000 --- a/conf/conductor-delayed_job +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash -# -# -# conductor-delayed_job startup script for conductor-delayed_job -# -# chkconfig: - 99 01 -# description: conductor-delayed_job is service for running conductor -# background jobs - -[ -r /etc/sysconfig/conductor-rails ] && . /etc/sysconfig/conductor-rails - -[ -r /etc/sysconfig/aeolus-conductor ] && . /etc/sysconfig/aeolus-conductor - -RAILS_ENV="${RAILS_ENV:-production}" -CONDUCTOR_DIR="${CONDUCTOR_DIR:-/usr/share/aeolus-conductor}" -AEOLUS_USER="${AEOLUS_USER:-aeolus}" -DJOB_LOCKFILE="${DJOB_LOCKFILE:-/var/lock/subsys/conductor-delayed_job}" -DJOB_PIDDIR="${DJOB_PIDDIR:-/var/run/aeolus-conductor/}" - -DJOB_PATH=$CONDUCTOR_DIR/script/ -DJOB_PROG=delayed_job -DJOB_PIDFILE=$DJOB_PIDDIR/$DJOB_PROG.pid - -. /etc/init.d/functions - -start() { - echo -n "Starting conductor-delayed_job: " - - daemon --user=$AEOLUS_USER $DJOB_PATH/$DJOB_PROG start --pid-dir=$DJOB_PIDDIR - RETVAL=$? - if [ $RETVAL -eq 0 ] && touch $DJOB_LOCKFILE ; then - echo_success - echo - else - echo_failure - echo - fi -} - -stop() { - echo -n "Shutting down conductor-delayed_job: " - $DJOB_PATH/$DJOB_PROG stop --pid-dir=$DJOB_PIDDIR - RETVAL=$? - if [ $RETVAL -eq 0 ] && rm -f $DJOB_LOCKFILE ; then - echo_success - echo - else - echo_failure - echo - fi -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - restart) - stop - start - ;; - status) - status -p $DJOB_PIDFILE $DJOB_PROG - RETVAL=$? - ;; - force-reload) - restart - ;; - *) - echo "Usage: conductor-delayed_job {start|stop|restart|status}" - exit 1 - ;; -esac - -exit $RETVAL diff --git a/src/Rakefile b/src/Rakefile index c1f9d60..37c683b 100644 --- a/src/Rakefile +++ b/src/Rakefile @@ -8,11 +8,4 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask'
-begin - #gem 'delayed_job', :version => '~>2.0.4' - require 'delayed/tasks' -rescue LoadError - STDERR.puts "Run `rake gems:install` to install delayed_job" -end - require 'tasks/rails' diff --git a/src/config/environment.rb b/src/config/environment.rb index f657eca..5966b0d 100644 --- a/src/config/environment.rb +++ b/src/config/environment.rb @@ -50,7 +50,6 @@ Rails::Initializer.run do |config| config.gem "typhoeus" config.gem 'rest-client', :version => '>= 1.6.1' config.gem 'rack-restful_submit', :version => '1.1.2' - config.gem 'delayed_job', :version => '~>2.0.4' config.gem 'net-scp', :lib => 'net/scp' config.gem 'uuidtools'
diff --git a/src/config/initializers/delayed_job.rb b/src/config/initializers/delayed_job.rb deleted file mode 100644 index a8684b4..0000000 --- a/src/config/initializers/delayed_job.rb +++ /dev/null @@ -1,2 +0,0 @@ -Delayed::Worker.backend = :active_record -Delayed::Worker.max_attempts = 1 diff --git a/src/db/migrate/20110124103216_create_delayed_jobs.rb b/src/db/migrate/20110124103216_create_delayed_jobs.rb deleted file mode 100644 index 943ff9b..0000000 --- a/src/db/migrate/20110124103216_create_delayed_jobs.rb +++ /dev/null @@ -1,21 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration - def self.up - create_table :delayed_jobs, :force => true do |table| - table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue - table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually. - table.text :handler # YAML-encoded string of the object that will do work - table.text :last_error # reason for last failure (See Note below) - table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future. - table.datetime :locked_at # Set when a client is working on this object - table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead) - table.string :locked_by # Who is working on this object (if locked) - table.timestamps - end - - add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority' - end - - def self.down - drop_table :delayed_jobs - end -end diff --git a/src/script/delayed_job b/src/script/delayed_job deleted file mode 100755 index edf1959..0000000 --- a/src/script/delayed_job +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env ruby - -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) -require 'delayed/command' -Delayed::Command.new(ARGV).daemonize diff --git a/util/check_services b/util/check_services index db0e930..8cd51e8 100755 --- a/util/check_services +++ b/util/check_services @@ -1,5 +1,5 @@ #!/usr/bin/ruby -init_scripts=%w(aeolus-conductor condor conductor-delayed_job deltacloud-core deltacloud-ec2-us-east-1 deltacloud-ec2-us-west-1 deltacloud-mock httpd imagefactory iwhd libvirtd mongod ntpd postgresql qpidd) +init_scripts=%w(aeolus-conductor condor deltacloud-core deltacloud-ec2-us-east-1 deltacloud-ec2-us-west-1 deltacloud-mock httpd imagefactory iwhd libvirtd mongod ntpd postgresql qpidd)
init_scripts.each do |script| puts "\nChecking #{script} ..."
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
diff --git a/src/db/migrate/20110124103216_create_delayed_jobs.rb b/src/db/migrate/20110124103216_create_delayed_jobs.rb deleted file mode 100644 index 943ff9b..0000000 --- a/src/db/migrate/20110124103216_create_delayed_jobs.rb +++ /dev/null @@ -1,21 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration
- def self.up
- create_table :delayed_jobs, :force => true do |table|
Is this really the right thing to do? Why aren't we adding a new migration which removes the table?
Cheers, Mark.
On 07/28/11 - 09:57:56AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
diff --git a/src/db/migrate/20110124103216_create_delayed_jobs.rb b/src/db/migrate/20110124103216_create_delayed_jobs.rb deleted file mode 100644 index 943ff9b..0000000 --- a/src/db/migrate/20110124103216_create_delayed_jobs.rb +++ /dev/null @@ -1,21 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration
- def self.up
- create_table :delayed_jobs, :force => true do |table|
Is this really the right thing to do? Why aren't we adding a new migration which removes the table?
Hey Mark, The reason I removed this initially is because I was getting errors along the lines of "delayed_job gem missing" when trying to run this migration. Now, I didn't investigate all that closely at the time, so it is possible that there was something else causing that error and this was just a red herring. However, that being said, I think Jay, Scott, Matt, and I came to the conclusion that deleting migrations is a safe thing to do. That is, if you are upgrading from a version previous to this, the migration won't have any idea about the delayed_jobs table, and will just ignore it. It will be an unused table in the database, but it shouldn't harm anything. And since we don't have any "real" users yet, it is just a bit of ugliness for developers, and shouldn't be that big of a deal.
On Thu, 2011-07-28 at 05:23 -0400, Chris Lalancette wrote:
On 07/28/11 - 09:57:56AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
diff --git a/src/db/migrate/20110124103216_create_delayed_jobs.rb b/src/db/migrate/20110124103216_create_delayed_jobs.rb deleted file mode 100644 index 943ff9b..0000000 --- a/src/db/migrate/20110124103216_create_delayed_jobs.rb +++ /dev/null @@ -1,21 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration
- def self.up
- create_table :delayed_jobs, :force => true do |table|
Is this really the right thing to do? Why aren't we adding a new migration which removes the table?
Hey Mark, The reason I removed this initially is because I was getting errors along the lines of "delayed_job gem missing" when trying to run this migration. Now, I didn't investigate all that closely at the time, so it is possible that there was something else causing that error and this was just a red herring.
I think that was because of src/config/initializers/delayed_job.rb not the migration
I doesn't look like the migration uses delayed_job itself
However, that being said, I think Jay, Scott, Matt, and I came to the
conclusion that deleting migrations is a safe thing to do. That is, if you are upgrading from a version previous to this, the migration won't have any idea about the delayed_jobs table, and will just ignore it. It will be an unused table in the database, but it shouldn't harm anything. And since we don't have any "real" users yet, it is just a bit of ugliness for developers, and shouldn't be that big of a deal.
I'd be fine with that, if there was a real reason for not doing it the correct way
(We've had some discussion before about "compressing" migrations - i.e. removing support for migrating from a version of the DB before a certain version - which would be a better way to get rid of code like this in the long run)
Cheers, Mark.
On Thu, 2011-07-28 at 10:32 +0100, Mark McLoughlin wrote:
On Thu, 2011-07-28 at 05:23 -0400, Chris Lalancette wrote:
On 07/28/11 - 09:57:56AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
diff --git a/src/db/migrate/20110124103216_create_delayed_jobs.rb b/src/db/migrate/20110124103216_create_delayed_jobs.rb deleted file mode 100644 index 943ff9b..0000000 --- a/src/db/migrate/20110124103216_create_delayed_jobs.rb +++ /dev/null @@ -1,21 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration
- def self.up
- create_table :delayed_jobs, :force => true do |table|
Is this really the right thing to do? Why aren't we adding a new migration which removes the table?
Hey Mark, The reason I removed this initially is because I was getting errors along the lines of "delayed_job gem missing" when trying to run this migration. Now, I didn't investigate all that closely at the time, so it is possible that there was something else causing that error and this was just a red herring.
I think that was because of src/config/initializers/delayed_job.rb not the migration
I doesn't look like the migration uses delayed_job itself
Happy to ACK the rest of the patch FWIW
If there's still some problem caused by the migration after that, we can dig into the specifics
Cheers, Mark.
From: Jason Guiditta jguiditt@redhat.com
These should no longer be used anywhere. (edited by Scott Seago sseago@redhat.com) --- aeolus-conductor.spec.in | 3 +- src/app/views/layouts/_bar.rhtml | 9 ----- src/app/views/layouts/_main_nav.html.erb | 19 ----------- src/app/views/layouts/confirmation.rhtml | 2 - src/app/views/layouts/old.haml | 51 ------------------------------ src/app/views/layouts/popup.rhtml | 7 ---- 6 files changed, 1 insertions(+), 90 deletions(-) delete mode 100644 src/app/views/layouts/_bar.rhtml delete mode 100644 src/app/views/layouts/_main_nav.html.erb delete mode 100644 src/app/views/layouts/confirmation.rhtml delete mode 100644 src/app/views/layouts/old.haml delete mode 100644 src/app/views/layouts/popup.rhtml
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in index 2977df3..b288209 100644 --- a/aeolus-conductor.spec.in +++ b/aeolus-conductor.spec.in @@ -124,7 +124,6 @@ builder="app/views/errors" cgi="public" css="public/stylesheets public/stylesheets/jquery.ui-1.8.1 \ public/javascripts/jquery-svg" -erb="app/views/layouts" fcgi="public" feature="features" gif="public/images public/stylesheets/images" @@ -161,7 +160,7 @@ ttf="public/fonts" txt="public" yml="config config/locales"
-for filetype in builder cgi css erb fcgi feature gif haml html ico jpg js json \ +for filetype in builder cgi css fcgi feature gif haml html ico jpg js json \ key opts png rake rb rhtml scss svg ttf txt yml; do dirs=${!filetype}
diff --git a/src/app/views/layouts/_bar.rhtml b/src/app/views/layouts/_bar.rhtml deleted file mode 100644 index 4eb4981..0000000 --- a/src/app/views/layouts/_bar.rhtml +++ /dev/null @@ -1,9 +0,0 @@ -<div id="top_bar"> -<% if false %> -<span class="hello_message">Hello current_user.display_name</span> -<span class="account_message"><span class="login">current_user.login</span> | <%= link_to "home", '/users/user' %> | <%= link_to "log out", logout_url %></span> -<% else %> -<span class="hello_message">Hello there <%= @controller.get_login_user %>!</span> -<span class="account_message"><%= link_to "hardware pools", :controller => 'hardware' %> | <%= link_to "VM resource pools", :controller => "resources" %></span> -<% end %> -</div> diff --git a/src/app/views/layouts/_main_nav.html.erb b/src/app/views/layouts/_main_nav.html.erb deleted file mode 100644 index d877029..0000000 --- a/src/app/views/layouts/_main_nav.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -<% cur_id = params[:id].to_i %> - -<h3>Pools</h3> -<ul id="pools"> - <% if !@pools.nil? %> - <% @pools.each { |pool| %> - <% if controller.controller_name == "pools" && pool.id == cur_id - selected_pool = "selected" - else selected_pool = "" - end %> - <li><%= link_to pool.name, - {:controller => "pools", :action => "show", :id => pool}, - :class => "poolname #{selected_pool}" %></li> - <% } %> - <% end %> -</ul> -<% if check_privilege(Privilege::CREATE, Pool, BasePermissionObject.general_permission_scope) %> - <%= link_to "Add a pool", {:controller => "pools", :action => "new"}, :class => "actionlink" %> -<% end %> diff --git a/src/app/views/layouts/confirmation.rhtml b/src/app/views/layouts/confirmation.rhtml deleted file mode 100644 index 736517c..0000000 --- a/src/app/views/layouts/confirmation.rhtml +++ /dev/null @@ -1,2 +0,0 @@ -<%# currently nothing for popups here. %> -<%= yield %> diff --git a/src/app/views/layouts/old.haml b/src/app/views/layouts/old.haml deleted file mode 100644 index 67d3d74..0000000 --- a/src/app/views/layouts/old.haml +++ /dev/null @@ -1,51 +0,0 @@ -!!! -%html - %head - %meta(http-equiv="Content-Type" content="text/html; charset=UTF-8") - %title - Red Hat Cloud Engine - = yield :title - = stylesheet_link_tag 'facebox' - = stylesheet_link_tag 'jquery.ui-1.8.1/jquery-ui-1.8.1.custom.css' - = stylesheet_link_tag 'jquery.loadmask' - = stylesheet_link_tag 'compiled/application' - - / [if lt IE 9] - = javascript_include_tag "http://html5shiv.googlecode.com/svn/trunk/html5.js" - = javascript_include_tag "jquery-1.6.1.min.js" - = javascript_include_tag "application.js" - = javascript_include_tag "jquery.ui-1.8.1/jquery-ui-1.8.1.custom.min.js" - = javascript_include_tag "jquery.loadmask.min" - = javascript_include_tag "modernizr-1.5" - /= javascript_include_tag "jquery.html5form" - = yield :scripts - %body - %div#head - %header.container_16 - = render :partial => '/layouts/header' - - if @current_user.nil? - #content.container_16 - = render :partial => '/layouts/notification' - #formwindow - = yield - - else - #subheader - %nav.container_16 - = render_navigation({:expand_all => true, :level => 1}) - = render_navigation({:expand_all => true, :level => 2}) - #content - #saved-searches - Saved searches - - details = !(yield :details).blank? - #list-view{ :class => details ? 'part' : 'full'} - - form_tag({:action => 'index'}, :method => :get) do - = text_field_tag :q, @search_term - = submit_tag "Search" - = render :partial => '/layouts/notification' - = (yield :list or yield) - #details-view.ui-tabs.ui-widget.ui-widget-content.ui-corner-all{ :class => ('hidden' unless details)} - - if details - = yield :details - %footer - = render :partial => "layouts/footer" - #grid diff --git a/src/app/views/layouts/popup.rhtml b/src/app/views/layouts/popup.rhtml deleted file mode 100644 index b67e5da..0000000 --- a/src/app/views/layouts/popup.rhtml +++ /dev/null @@ -1,7 +0,0 @@ -<div id="window"> -<div class="dialog_title_small"> - <div class="header"><%= yield :title -%></div> - <div><%= yield :description -%></div> -</div> -<%= yield %> -</div>
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jason Guiditta jguiditt@redhat.com
These should no longer be used anywhere. (edited by Scott Seago sseago@redhat.com)
Right, these all look obsolete and everything appears to work without them. ACK
(No need to wait until rails3 before pushing this)
Cheers, Mark.
On 07/28/11 - 10:04:03AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jason Guiditta jguiditt@redhat.com
These should no longer be used anywhere. (edited by Scott Seago sseago@redhat.com)
Right, these all look obsolete and everything appears to work without them. ACK
(No need to wait until rails3 before pushing this)
Thanks, pushed.
From: Mohammed Morsi mmorsi@redhat.com
These changes update the base rails framework to v3.0.x. No deltacloud-specific sources are modified here
(edited by Jason Guiditta jguiditt@redhat.com) (edited by Scott Seago sseago@redhat.com) --- aeolus-conductor.spec.in | 6 ++---- src/public/404.html | 34 +++++++++++++++------------------- src/public/422.html | 26 ++++++++++++++++++++++++++ src/public/500.html | 36 ++++++++++++++++-------------------- src/public/dispatch.cgi | 10 ---------- src/public/dispatch.fcgi | 24 ------------------------ src/public/dispatch.rb | 29 ----------------------------- src/public/javascripts/controls.js | 8 +++++--- src/public/javascripts/dragdrop.js | 13 +++++++------ src/public/javascripts/effects.js | 21 ++++++++------------- src/public/robots.txt | 6 +++++- src/script/about | 3 --- src/script/autospec | 6 ------ src/script/breakpointer | 3 --- src/script/console | 3 --- src/script/dbconsole | 3 --- src/script/destroy | 3 --- src/script/generate | 3 --- src/script/performance/benchmarker | 3 --- src/script/performance/profiler | 3 --- src/script/performance/request | 3 --- src/script/plugin | 3 --- src/script/process/inspector | 3 --- src/script/process/reaper | 3 --- src/script/process/spawner | 3 --- src/script/rails | 6 ++++++ src/script/runner | 3 --- src/script/server | 9 --------- src/script/spec | 10 ---------- 29 files changed, 90 insertions(+), 196 deletions(-) create mode 100644 src/public/422.html delete mode 100755 src/public/dispatch.cgi delete mode 100755 src/public/dispatch.fcgi delete mode 100755 src/public/dispatch.rb delete mode 100755 src/script/about delete mode 100755 src/script/autospec delete mode 100755 src/script/breakpointer delete mode 100755 src/script/console delete mode 100755 src/script/dbconsole delete mode 100755 src/script/destroy delete mode 100755 src/script/generate delete mode 100755 src/script/performance/benchmarker delete mode 100755 src/script/performance/profiler delete mode 100755 src/script/performance/request delete mode 100755 src/script/plugin delete mode 100755 src/script/process/inspector delete mode 100755 src/script/process/reaper delete mode 100755 src/script/process/spawner create mode 100755 src/script/rails delete mode 100755 src/script/runner delete mode 100755 src/script/server delete mode 100755 src/script/spec
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in index b288209..2ea98e6 100644 --- a/aeolus-conductor.spec.in +++ b/aeolus-conductor.spec.in @@ -121,10 +121,8 @@ getent passwd aeolus >/dev/null || \ # extension may exist. For instance cgi="public" means that src/public/*.cgi # will be copied from the source into the RPM. builder="app/views/errors" -cgi="public" css="public/stylesheets public/stylesheets/jquery.ui-1.8.1 \ public/javascripts/jquery-svg" -fcgi="public" feature="features" gif="public/images public/stylesheets/images" haml="app/views/hardware_profiles app/views/realm_mappings \ @@ -151,7 +149,7 @@ rb="app/models app/controllers \ app/helpers \ app/services app/util \ config config/initializers config/environments db db/migrate dutils \ - features/support features/step_definitions lib public spec \ + features/support features/step_definitions lib spec \ spec/controllers spec/factories spec/helpers spec/models spec/services" rhtml="app/views/layouts" scss="app/stylesheets" @@ -160,7 +158,7 @@ ttf="public/fonts" txt="public" yml="config config/locales"
-for filetype in builder cgi css fcgi feature gif haml html ico jpg js json \ +for filetype in builder css feature gif haml html ico jpg js json \ key opts png rake rb rhtml scss svg ttf txt yml; do dirs=${!filetype}
diff --git a/src/public/404.html b/src/public/404.html index eff660b..9a48320 100644 --- a/src/public/404.html +++ b/src/public/404.html @@ -1,23 +1,19 @@ -<!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"> - +<!DOCTYPE html> +<html> <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> + <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> @@ -27,4 +23,4 @@ <p>You may have mistyped the address or the page may have moved.</p> </div> </body> -</html> \ No newline at end of file +</html> diff --git a/src/public/422.html b/src/public/422.html new file mode 100644 index 0000000..83660ab --- /dev/null +++ b/src/public/422.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <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> diff --git a/src/public/500.html b/src/public/500.html index f0aee0e..b80307f 100644 --- a/src/public/500.html +++ b/src/public/500.html @@ -1,23 +1,19 @@ -<!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"> - +<!DOCTYPE html> +<html> <head> - <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> - <title>We're sorry, but something went wrong</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> + <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> @@ -27,4 +23,4 @@ <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 +</html> diff --git a/src/public/dispatch.cgi b/src/public/dispatch.cgi deleted file mode 100755 index 9730473..0000000 --- a/src/public/dispatch.cgi +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/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/src/public/dispatch.fcgi b/src/public/dispatch.fcgi deleted file mode 100755 index f934b30..0000000 --- a/src/public/dispatch.fcgi +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/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/src/public/dispatch.rb b/src/public/dispatch.rb deleted file mode 100755 index a82be08..0000000 --- a/src/public/dispatch.rb +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/ruby -# -# Copyright (C) 2008 Red Hat, Inc. -# Written by Scott Seago sseago@redhat.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. A copy of the GNU General Public License is -# also available at http://www.gnu.org/copyleft/gpl.html. - - -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/src/public/javascripts/controls.js b/src/public/javascripts/controls.js index ca29aef..7392fb6 100644 --- a/src/public/javascripts/controls.js +++ b/src/public/javascripts/controls.js @@ -1,6 +1,8 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2009 Jon Tirsen (http://www.tirsen.com) // Contributors: // Richard Livsey // Rahul Bhargava diff --git a/src/public/javascripts/dragdrop.js b/src/public/javascripts/dragdrop.js index 07229f9..15c6dbc 100644 --- a/src/public/javascripts/dragdrop.js +++ b/src/public/javascripts/dragdrop.js @@ -1,5 +1,6 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // 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/ @@ -311,7 +312,7 @@ var Draggable = Class.create({ tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); + var pos = this.element.cumulativeOffset(); this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this); @@ -454,7 +455,7 @@ var Draggable = Class.create({ },
draw: function(point) { - var pos = Position.cumulativeOffset(this.element); + var pos = this.element.cumulativeOffset(); if(this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; @@ -730,7 +731,7 @@ var Sortable = { }
// keep reference - this.sortables[element.id] = options; + this.sortables[element.identify()] = options;
// for onupdate Draggables.addObserver(new SortableObserver(element, options.onUpdate)); @@ -825,7 +826,7 @@ var Sortable = { hide().addClassName('dropmarker').setStyle({position:'absolute'}); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); } - var offsets = Position.cumulativeOffset(dropon); + var offsets = dropon.cumulativeOffset(); Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after') diff --git a/src/public/javascripts/effects.js b/src/public/javascripts/effects.js index 5a639d2..c81e6c7 100644 --- a/src/public/javascripts/effects.js +++ b/src/public/javascripts/effects.js @@ -1,4 +1,6 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) @@ -145,14 +147,13 @@ var Effect = { 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade'] }, - toggle: function(element, effect) { + toggle: function(element, effect, options) { element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ + effect = (effect || 'appear').toLowerCase(); + + return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, 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); + }, options || {})); } };
@@ -228,12 +229,6 @@ 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; diff --git a/src/public/robots.txt b/src/public/robots.txt index 4ab9e89..085187f 100644 --- a/src/public/robots.txt +++ b/src/public/robots.txt @@ -1 +1,5 @@ -# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file \ No newline at end of file +# 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/src/script/about b/src/script/about deleted file mode 100755 index 7b07d46..0000000 --- a/src/script/about +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/about' \ No newline at end of file diff --git a/src/script/autospec b/src/script/autospec deleted file mode 100755 index 837bbd7..0000000 --- a/src/script/autospec +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env ruby -gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 -ENV['RSPEC'] = 'true' # allows autotest to discover rspec -ENV['AUTOTEST'] = 'true' # allows autotest to run w/ color on linux -system((RUBY_PLATFORM =~ /mswin|mingw/ ? 'autotest.bat' : 'autotest'), *ARGV) || - $stderr.puts("Unable to find autotest. Please install ZenTest or fix your PATH") diff --git a/src/script/breakpointer b/src/script/breakpointer deleted file mode 100755 index 64af76e..0000000 --- a/src/script/breakpointer +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/breakpointer' \ No newline at end of file diff --git a/src/script/console b/src/script/console deleted file mode 100755 index 42f28f7..0000000 --- a/src/script/console +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/console' \ No newline at end of file diff --git a/src/script/dbconsole b/src/script/dbconsole deleted file mode 100755 index caa60ce..0000000 --- a/src/script/dbconsole +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/dbconsole' diff --git a/src/script/destroy b/src/script/destroy deleted file mode 100755 index fa0e6fc..0000000 --- a/src/script/destroy +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/destroy' \ No newline at end of file diff --git a/src/script/generate b/src/script/generate deleted file mode 100755 index ef976e0..0000000 --- a/src/script/generate +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/generate' \ No newline at end of file diff --git a/src/script/performance/benchmarker b/src/script/performance/benchmarker deleted file mode 100755 index c842d35..0000000 --- a/src/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/src/script/performance/profiler b/src/script/performance/profiler deleted file mode 100755 index d855ac8..0000000 --- a/src/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/src/script/performance/request b/src/script/performance/request deleted file mode 100755 index ae3f38c..0000000 --- a/src/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/src/script/plugin b/src/script/plugin deleted file mode 100755 index 26ca64c..0000000 --- a/src/script/plugin +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/plugin' \ No newline at end of file diff --git a/src/script/process/inspector b/src/script/process/inspector deleted file mode 100755 index bf25ad8..0000000 --- a/src/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/src/script/process/reaper b/src/script/process/reaper deleted file mode 100755 index c77f045..0000000 --- a/src/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/src/script/process/spawner b/src/script/process/spawner deleted file mode 100755 index 7118f39..0000000 --- a/src/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/src/script/rails b/src/script/rails new file mode 100755 index 0000000..f8da2cf --- /dev/null +++ b/src/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/src/script/runner b/src/script/runner deleted file mode 100755 index ccc30f9..0000000 --- a/src/script/runner +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/runner' \ No newline at end of file diff --git a/src/script/server b/src/script/server deleted file mode 100755 index 8d5e871..0000000 --- a/src/script/server +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby - -if Process.uid == 0 or Process.gid == 0 - puts "Aeolus Conductor cannot be run as root" - exit(1) -end - -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/server' diff --git a/src/script/spec b/src/script/spec deleted file mode 100755 index 46fdbe6..0000000 --- a/src/script/spec +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env ruby -if ARGV.any? {|arg| %w[--drb -X --generate-options -G --help -h --version -v].include?(arg)} - require 'rubygems' unless ENV['NO_RUBYGEMS'] -else - gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 - ENV["RAILS_ENV"] ||= 'test' - require File.expand_path(File.dirname(__FILE__) + "/../config/environment") unless defined?(RAILS_ROOT) -end -require 'spec/autorun' -exit ::Spec::Runner::CommandLine.run
From: Mohammed Morsi mmorsi@redhat.com
Introduce Gemfile for bundler (edited by Jason Guiditta jguiditt@redhat.com) (edited by Scott Seago sseago@redhat.com) (edited by Chris Lalancette clalance@redhat.com) --- aeolus-conductor.spec.in | 2 ++ src/Gemfile | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 0 deletions(-) create mode 100644 src/Gemfile
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in index 2ea98e6..0792898 100644 --- a/aeolus-conductor.spec.in +++ b/aeolus-conductor.spec.in @@ -171,6 +171,7 @@ done # misc files %{__cp} src/Rakefile %{buildroot}%{app_root} %{__cp} src/config.ru %{buildroot}%{app_root} +%{__cp} src/Gemfile %{buildroot}%{app_root}
%{__mkdir} -p %{buildroot}%{app_root}/config %{__cp} src/config/database.pg %{buildroot}%{app_root}/config @@ -262,6 +263,7 @@ fi %{app_root}/log %{app_root}/public %{app_root}/Rakefile +%{app_root}/Gemfile %config %{_sysconfdir}/%{name} %doc AUTHORS COPYING
diff --git a/src/Gemfile b/src/Gemfile new file mode 100644 index 0000000..f54185d --- /dev/null +++ b/src/Gemfile @@ -0,0 +1,34 @@ +source 'http://rubygems.org' + +gem 'rails' + +gem 'sqlite3', :require => 'sqlite3' + +gem 'authlogic' +gem 'deltacloud-client', :require => 'deltacloud' +gem 'sass' +gem 'haml' +gem 'will_paginate' +gem 'nokogiri' +gem 'compass' +gem 'compass-960-plugin', :require => 'ninesixty' +gem 'simple-navigation' +gem 'typhoeus' +gem 'rest-client' +#gem 'rack-restful_submit' +gem 'net-scp', :require => 'net/scp' +gem 'uuidtools' +gem 'pg' +gem 'thin' +group :development, :test do + #gem 'rspec-rails' + #gem 'factory_girl_rails' + #gem 'timecop' + + #gem 'cucumber' + #gem 'cucumber-rails' + #gem 'database_cleaner' + #gem 'webrat' + #gem 'vcr' + #gem 'webmock' +end
From: Mohammed Morsi mmorsi@redhat.com
Note that this patch should be ammended with more vetted routes.rb updates (and fix the commented ones).
(edited by Jason Guiditta jguiditt@redhat.com)
Signed-off-by: Chris Lalancette clalance@redhat.com --- src/Rakefile | 6 +- src/config.ru | 9 +- src/config/application.rb | 49 ++++++++ src/config/boot.rb | 123 ++------------------- src/config/environment.rb | 94 +--------------- src/config/environments/development.rb | 52 +++------ src/config/environments/production.rb | 58 ++++++++--- src/config/environments/test.rb | 79 ++++++-------- src/config/initializers/new_rails_defaults.rb | 19 --- src/config/initializers/secret_token.rb | 7 + src/config/initializers/session_store.rb | 4 +- src/config/routes.rb | 146 +++++++++++++++---------- 12 files changed, 267 insertions(+), 379 deletions(-) create mode 100644 src/config/application.rb delete mode 100644 src/config/initializers/new_rails_defaults.rb create mode 100644 src/config/initializers/secret_token.rb
diff --git a/src/Rakefile b/src/Rakefile index 37c683b..d654057 100644 --- a/src/Rakefile +++ b/src/Rakefile @@ -1,11 +1,9 @@ -# -*- ruby -*- # 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 File.expand_path('../config/application', __FILE__) require 'rake' require 'rake/testtask' require 'rake/rdoctask'
-require 'tasks/rails' +Conductor::Application.load_tasks diff --git a/src/config.ru b/src/config.ru index acbfe4e..51a0775 100644 --- a/src/config.ru +++ b/src/config.ru @@ -1,7 +1,4 @@ -# Rack Dispatcher +# This file is used by Rack-based servers to start the application.
-# Require your environment file to bootstrap Rails -require File.dirname(__FILE__) + '/config/environment' - -# Dispatch the request -run ActionController::Dispatcher.new +require ::File.expand_path('../config/environment', __FILE__) +run Conductor::Application diff --git a/src/config/application.rb b/src/config/application.rb new file mode 100644 index 0000000..042dc8a --- /dev/null +++ b/src/config/application.rb @@ -0,0 +1,49 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +# If you have a Gemfile, require the gems listed there, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(:default, Rails.env) if defined?(Bundler) + +$: << File.join(File.dirname(__FILE__), "../app") + +module Aggregator + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + config.active_record.observers = :instance_observer, :task_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # JavaScript files you want as :defaults (application.js is always included). + # config.action_view.javascript_expansions[:defaults] = %w(jquery rails) + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password, :password_confirmation] + + config.after_initialize do + Haml::Template.options[:format] = :html5 + end + end +end diff --git a/src/config/boot.rb b/src/config/boot.rb index 9759b93..ab6cb37 100644 --- a/src/config/boot.rb +++ b/src/config/boot.rb @@ -1,110 +1,13 @@ -# Don't change this file! -# Configure your app in config/environment.rb and config/environments/*.rb - -RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) - -module Rails - class << self - def boot! - unless booted? - preinitialize - pick_boot.run - end - end - - def booted? - defined? Rails::Initializer - end - - def pick_boot - (vendor_rails? ? VendorBoot : GemBoot).new - end - - def vendor_rails? - File.exist?("#{RAILS_ROOT}/vendor/rails") - end - - def preinitialize - load(preinitializer_path) if File.exist?(preinitializer_path) - end - - def preinitializer_path - "#{RAILS_ROOT}/config/preinitializer.rb" - end - end - - class Boot - def run - load_initializer - Rails::Initializer.run(:set_load_path) - end - end - - class VendorBoot < Boot - def load_initializer - require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" - Rails::Initializer.run(:install_gem_spec_stubs) - Rails::GemDependency.add_frozen_gem_path - end - end - - class GemBoot < Boot - def load_initializer - self.class.load_rubygems - load_rails_gem - require 'initializer' - end - - def load_rails_gem - if version = self.class.gem_version - gem 'rails', version - else - gem 'rails' - end - rescue Gem::LoadError => load_error - $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 rescue nil - end - - def gem_version - if defined? RAILS_GEM_VERSION - RAILS_GEM_VERSION - elsif ENV.include?('RAILS_GEM_VERSION') - ENV['RAILS_GEM_VERSION'] - else - parse_gem_version(read_environment_rb) - end - end - - def load_rubygems - min_version = '1.3.1' - require 'rubygems' - unless rubygems_version >= min_version - $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) - exit 1 - end - - rescue LoadError - $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) - exit 1 - end - - def parse_gem_version(text) - $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ - end - - private - def read_environment_rb - File.read("#{RAILS_ROOT}/config/environment.rb") - end - end - end -end - -# All that for this: -Rails.boot! +require 'rubygems' + +# Set up gems listed in the Gemfile. +gemfile = File.expand_path('../../Gemfile', __FILE__) +begin + ENV['BUNDLE_GEMFILE'] = gemfile + require 'bundler' + Bundler.setup +rescue Bundler::GemNotFound => e + STDERR.puts e.message + STDERR.puts "Try running `bundle install`." + exit! +end if File.exist?(gemfile) diff --git a/src/config/environment.rb b/src/config/environment.rb index 5966b0d..d9e2695 100644 --- a/src/config/environment.rb +++ b/src/config/environment.rb @@ -1,91 +1,5 @@ -# -# Copyright (C) 2009 Red Hat, Inc. -# Written by Scott Seago sseago@redhat.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. A copy of the GNU General Public License is -# also available at http://www.gnu.org/copyleft/gpl.html. +# Load the rails application +require File.expand_path('../application', __FILE__)
-# Be sure to restart your web server when you modify this file. - -# Specifies gem version of Rails to use when vendor/rails is not present -RAILS_GEM_VERSION = '>= 2.3.2' unless defined? RAILS_GEM_VERSION - -# Bootstrap the Rails environment, frameworks, and default configuration -require File.join(File.dirname(__FILE__), 'boot') -require 'util/condormatic' - - -Rails::Initializer.run do |config| - # Settings in config/environments/* take precedence over those specified here - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - # See Rails::Configuration for more options. - - # Skip frameworks you're not going to use. To use Rails without a database - # you must remove the Active Record framework. - # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] - - # Specify gems that this application depends on. - # They can then be installed with "rake gems:install" on new installations. - config.gem "authlogic" - config.gem "deltacloud-client", :lib => "deltacloud", :version => ">= 0.0.9.8" - config.gem "haml" - config.gem "will_paginate" - config.gem "nokogiri", :version => ">= 1.4.0" - config.gem "compass", :version => ">= 0.10.2" - config.gem "compass-960-plugin", :lib => "ninesixty" - config.gem "simple-navigation" - config.gem "typhoeus" - config.gem 'rest-client', :version => '>= 1.6.1' - config.gem 'rack-restful_submit', :version => '1.1.2' - config.gem 'net-scp', :lib => 'net/scp' - config.gem 'uuidtools' - - config.middleware.swap Rack::MethodOverride, 'Rack::RestfulSubmit' - - config.active_record.observers = :instance_observer, :task_observer - # Only load the plugins named here, in the order given. By default, all plugins - # in vendor/plugins are loaded in alphabetical order. - # :all can be used as a placeholder for all plugins not explicitly named - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - - # Add additional load paths for your own custom dirs - # config.load_paths += %W( #{RAILS_ROOT}/extras ) - - # Force all environments to use the same logger level - # (by default production uses :info, the others :debug) - # config.log_level = :debug - - # Make Time.zone default to the specified zone, and make Active Record store time values - # in the database in UTC, and return them converted to the specified local zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Uncomment to use default local time. - config.time_zone = 'UTC' - - # Use SQL instead of Active Record's schema dumper when creating the test database. - # This is necessary if your schema can't be completely dumped by the schema dumper, - # like if you have constraints or database-specific column types - # config.active_record.schema_format = :sql - - # Activate observers that should always be running - # config.active_record.observers = :cacher, :garbage_collector - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] - # config.i18n.default_locale = :de - - config.after_initialize do - Haml::Template.options[:format] = :html5 - end -end +# Initialize the rails application +Conductor::Application.initialize! diff --git a/src/config/environments/development.rb b/src/config/environments/development.rb index 9bd4fa6..d4d3942 100644 --- a/src/config/environments/development.rb +++ b/src/config/environments/development.rb @@ -1,39 +1,25 @@ -# -# Copyright (C) 2008 Red Hat, Inc. -# Written by Scott Seago sseago@redhat.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. A copy of the GNU General Public License is -# also available at http://www.gnu.org/copyleft/gpl.html. +Conductor::Application.configure do + # Settings specified here will take precedence over those in config/environment.rb
-# Settings specified here will take precedence over those in config/environment.rb + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the webserver when you make code changes. + config.cache_classes = false
-# In the development environment your application's code is reloaded on -# every request. This slows down response time but is perfect for development -# since you don't have to restart the webserver when you make code changes. -config.cache_classes = false + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true
-# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_view.debug_rjs = true + config.action_controller.perform_caching = false
-# Enable the breakpoint server that script/breakpointer connects to -#config.breakpoint_server = true + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false
-# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_controller.perform_caching = false -config.action_view.debug_rjs = true + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log
-# Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin +end diff --git a/src/config/environments/production.rb b/src/config/environments/production.rb index 9ad4568..ecc0196 100644 --- a/src/config/environments/production.rb +++ b/src/config/environments/production.rb @@ -17,22 +17,52 @@ # MA 02110-1301, USA. A copy of the GNU General Public License is # also available at http://www.gnu.org/copyleft/gpl.html.
-# Settings specified here will take precedence over those in config/environment.rb +Conductor::Application.configure do + # 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 + # 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.consider_all_requests_local = false + config.action_controller.perform_caching = true
-# Full error reports are disabled and caching is turned on -config.action_controller.consider_all_requests_local = false -config.action_controller.perform_caching = true + # Specifies the header that your server uses for sending files + config.action_dispatch.x_sendfile_header = "X-Sendfile"
-# Enable serving of images, stylesheets, and javascripts from an asset server -# config.action_controller.asset_host = "http://assets.example.com" + # For nginx: + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
-# Disable delivery errors, bad email addresses will be ignored -# config.action_mailer.raise_delivery_errors = false -config.log_path = "/var/log/aeolus-conductor/rails.log" + # If you have no front-end server that supports something like X-Sendfile, + # just comment this out and Rails will serve the files + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Disable Rails's static asset server + # In production, Apache or nginx will already do this + config.serve_static_assets = false + + # Enable serving of images, stylesheets, and javascripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/src/config/environments/test.rb b/src/config/environments/test.rb index 42ed90f..ba633db 100644 --- a/src/config/environments/test.rb +++ b/src/config/environments/test.rb @@ -1,44 +1,35 @@ -# -# Copyright (C) 2008 Red Hat, Inc. -# Written by Scott Seago sseago@redhat.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. A copy of the GNU General Public License is -# also available at http://www.gnu.org/copyleft/gpl.html. - -# 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 - -# 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 - -config.gem 'rspec-rails', :version => '>= 1.3.2', :lib => false unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) -config.gem "factory_girl", :lib => "factory_girl", :version => ">=1.3.1" -config.gem 'timecop', :lib => 'timecop', :version => '>= 0.3.5' -config.gem 'vcr', :lib => 'vcr', :version => '>= 1.10.0' -config.gem 'webmock', :lib => 'webmock', :version => '>= 1.6.4' +Aggregator::Application.configure do + # 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.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/src/config/initializers/new_rails_defaults.rb b/src/config/initializers/new_rails_defaults.rb deleted file mode 100644 index 8ec3186..0000000 --- a/src/config/initializers/new_rails_defaults.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# These settings change the behavior of Rails 2 apps and will be defaults -# for Rails 3. You can remove this initializer when Rails 3 is released. - -if defined?(ActiveRecord) - # Include Active Record class name as root for JSON serialized output. - ActiveRecord::Base.include_root_in_json = true - - # Store the full class name (including module namespace) in STI type column. - ActiveRecord::Base.store_full_sti_class = true -end - -# Use ISO 8601 format for JSON serialized times and dates. -ActiveSupport.use_standard_json_time_format = true - -# Don't escape HTML entities in JSON, leave that for the #json_escape helper. -# if you're including raw json in an HTML page. -ActiveSupport.escape_html_entities_in_json = false \ No newline at end of file diff --git a/src/config/initializers/secret_token.rb b/src/config/initializers/secret_token.rb new file mode 100644 index 0000000..7c6aba6 --- /dev/null +++ b/src/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Conductor::Application.config.secret_token = '538786e891b468964662eb7385b3b781062b907175875c6b7fc344ffb9eb7de5abd7bca07e7901bf0bfdda57e52a10f2688fae7e86e30e6194d22dc489bd9b54' diff --git a/src/config/initializers/session_store.rb b/src/config/initializers/session_store.rb index 64dbf51..55d2275 100644 --- a/src/config/initializers/session_store.rb +++ b/src/config/initializers/session_store.rb @@ -4,7 +4,7 @@ # If you change this key, all old sessions will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -ActionController::Base.session = { +Conductor::Application.config.session = { :key => '_rails23-app_session', :secret => '41713a6b4a92b5b7af55314d2ef6fc499a177269ea91b9fdaa7d15c42e1234b70b32f52278ae26b774b38dbdfeb7d078585d10f643e81b6615d32410f192f1de' } @@ -12,4 +12,4 @@ ActionController::Base.session = { # Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information # (create the session table with "rake db:sessions:create") -ActionController::Base.session_store = :active_record_store +Conductor::Application.config.session_store = :active_record_store diff --git a/src/config/routes.rb b/src/config/routes.rb index 7f83338..2589742 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -1,75 +1,107 @@ -# -# Copyright (C) 2009 Red Hat, Inc. -# Written by Scott Seago sseago@redhat.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. A copy of the GNU General Public License is -# also available at http://www.gnu.org/copyleft/gpl.html. - -ActionController::Routing::Routes.draw do |map| - - # The priority is based upon order of creation: first created -> highest priority. +Conductor::Application.routes.draw do + # The priority is based upon order of creation: + # first created -> highest priority.
# Sample of regular route: - # map.connect 'products/:id', :controller => 'catalog', :action => 'view' + # match 'products/:id' => 'catalog#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' + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # This route can be invoked with purchase_url(:id => product.id) + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products
- # You can have the root of your site routed by hooking up '' - # -- just remember to delete public/index.html. + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end
- map.resources :pools, :collection => { :multi_destroy => :delete } - map.resources :deployments, :collection => { :multi_stop => :get, :launch_new => :get, :check_name => :get } - map.resources :instances, :collection => {:start => :get, :multi_stop => :get, :remove_failed => :get, :can_start => :get, :can_create => :get }, :member => {:key => :get} + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end
- map.can_start_instance '/instances/:instance_id/can_start/:provider_account_id', :controller => 'instances', :action => 'can_start', :conditions => { :method => :get } - map.can_create_instance '/instances/:instance_id/can_create/:provider_account_id', :controller => 'instances', :action => 'can_create', :conditions => { :method => :get } + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end
- map.resources :image_imports + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end
- map.resources :hardware_profiles, :collection => { :multi_destroy => :delete } - map.resources :providers, :collection => { :multi_destroy => :delete } - map.resources :provider_types, :only => :index - map.resources :users, :collection => { :multi_destroy => :delete } - map.resources :provider_accounts, :collection => { :multi_destroy => :delete, :set_selected_provider => :get} - map.resources :roles, :collection => { :multi_destroy => :delete } - map.resources :settings, :collection => { :self_service => :get, :general_settings => :get } - map.resources :pool_families, :collection => { :multi_destroy => :delete, :add_provider_account => :post, :multi_destroy_provider_accounts => :delete } - map.resources :realms, :collection => { :multi_destroy => :delete } - map.resources :realm_mappings, :collection => { :multi_destroy => :delete } - map.resources :suggested_deployables, :collection => { :multi_destroy => :delete } + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => "welcome#index"
- map.matching_profiles '/hardware_profiles/matching_profiles/:hardware_profile_id/provider/:provider_id', :controller => 'hardware_profiles', :action => 'matching_profiles', :conditions => { :method => :get } + # See how all your routes lay out with "rake routes"
- map.login 'login', :controller => "user_sessions", :action => "new" - map.logout 'logout', :controller => "user_sessions", :action => "destroy" - map.resource :user_session - map.register 'register', :controller => 'users', :action => 'new' - map.resource :account, :controller => "users" - map.resources :permissions, :collection => { :list => :get } + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))'
- map.root :controller => 'pools' + #Do we still need this one? => resource :user_session + match 'login', :to => 'user_sessions#new', :as => 'login' + match 'logout', :to => 'user_sessions#destroy', :as => 'logout' + match 'register', :to => 'users#new', :as => 'register'
+ resource 'account', :to => 'users' + resources :users, :instances, :templates, :builds + resources :permissions, :collection => { :list => :get} + resources :settings do + collection do + get :self_service + get :general_settings + end + end + resources :pools do + get :hardware_profiles + get :realms + end
- # Allow downloading Web Service WSDL as a file with an extension - # instead of a file named 'wsdl' - map.connect ':controller/service.wsdl', :action => 'wsdl' + resources :pools, :collection => { :multi_destroy => :delete } + resources :deployments, :collection => { :multi_stop => :get, :launch_new => :get, :check_name => :get } + resources :instances, :collection => {:start => :get, :multi_stop => :get, :remove_failed => :get, :can_start => :get, :can_create => :get }, :member => {:key => :get}
- # Install the default route as the lowest priority. - map.connect ':controller/:action/:id.:format' - map.connect ':controller/:action/:id' + #map.can_start_instance '/instances/:instance_id/can_start/:provider_account_id', :controller => 'instances', :action => 'can_start', :conditions => { :method => :get } + #map.can_create_instance '/instances/:instance_id/can_create/:provider_account_id', :controller => 'instances', :action => 'can_create', :conditions => { :method => :get } + + resources :image_imports + + resources :hardware_profiles, :collection => { :multi_destroy => :delete } + resources :providers, :collection => { :multi_destroy => :delete } + #This may be the correct way to do the above now.... + #resources :providers do + # resources :accounts, :to => :cloud_accounts + #end + resources :provider_types, :only => :index + resources :users, :collection => { :multi_destroy => :delete } + resources :provider_accounts, :collection => { :multi_destroy => :delete, :set_selected_provider => :get} + resources :roles, :collection => { :multi_destroy => :delete } + resources :settings, :collection => { :self_service => :get, :general_settings => :get } + resources :pool_families, :collection => { :multi_destroy => :delete, :add_provider_account => :post, :multi_destroy_provider_accounts => :delete } + resources :realms, :collection => { :multi_destroy => :delete } + resources :realm_mappings, :collection => { :multi_destroy => :delete } + resources :suggested_deployables, :collection => { :multi_destroy => :delete } + + #match 'matching_profiles', :to => '/hardware_profiles/matching_profiles/:hardware_profile_id/provider/:provider_id', :controller => 'hardware_profiles', :action => 'matching_profiles', :conditions => { :method => :get }, :as =>'matching_profiles' + match 'dashboard', :to => 'dashboard', :as => 'dashboard' + root :to => "pools#index" + + match '/:controller(/:action(/:id))' end
From: Mohammed Morsi mmorsi@redhat.com
This largely gets rid of rails deprecations
(edited by Jason Guiditta jguiditt@redhat.com) (edited by Scott Seago sseago@redhat.com) --- src/app/controllers/application_controller.rb | 6 ++---- src/app/models/hardware_profile.rb | 2 +- src/app/models/provider.rb | 5 ++--- src/app/models/quota.rb | 2 ++ src/app/models/search_filter.rb | 2 +- src/app/models/task.rb | 4 +++- src/app/models/user_session.rb | 6 ++++++ src/config/application.rb | 3 ++- src/config/environments/test.rb | 2 +- 9 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/src/app/controllers/application_controller.rb b/src/app/controllers/application_controller.rb index 8329459..b6159e5 100644 --- a/src/app/controllers/application_controller.rb +++ b/src/app/controllers/application_controller.rb @@ -25,13 +25,11 @@ require 'viewstate.rb' class ApplicationController < ActionController::Base # FIXME: not sure what we're doing aobut service layer w/ deltacloud include ApplicationService - filter_parameter_logging :password, :password_confirmation helper_method :current_user_session, :current_user, :filter_view? before_filter :read_breadcrumbs
def top_section; end
- # General error handlers, must be in order from least specific # to most specific rescue_from Exception, :with => :handle_general_error @@ -77,7 +75,7 @@ class ApplicationController < ActionController::Base end
def handle_error(hash) - log_error(hash[:error]) if hash[:error] + logger.fatal(hash[:error].to_s) if hash[:error] msg = hash[:message] || hash[:error].message title = hash[:title] || "Internal Server Error" status = hash[:status] || :internal_server_error @@ -199,7 +197,7 @@ class ApplicationController < ActionController::Base end
def store_location - session[:return_to] = request.request_uri + session[:return_to] = request.fullpath end
def redirect_back_or_default(default) diff --git a/src/app/models/hardware_profile.rb b/src/app/models/hardware_profile.rb index 9eb116e..57d5fd8 100644 --- a/src/app/models/hardware_profile.rb +++ b/src/app/models/hardware_profile.rb @@ -39,7 +39,7 @@
class HardwareProfile < ActiveRecord::Base has_many :instances - named_scope :frontend, :conditions => { :provider_id => nil } + scope :frontend, :conditions => { :provider_id => nil } has_many :provider_instances, :class_name => "Instance", :foreign_key => "provider_hardware_profile_id"
diff --git a/src/app/models/provider.rb b/src/app/models/provider.rb index 18df84f..1d70232 100644 --- a/src/app/models/provider.rb +++ b/src/app/models/provider.rb @@ -52,7 +52,6 @@ class Provider < ActiveRecord::Base validates_format_of :name, :with => /^[\w -]*$/n, :message => "must only contain: numbers, letters, spaces, '_' and '-'" validates_length_of :name, :maximum => 255
- has_many :permissions, :as => :permission_object, :dependent => :destroy, :include => [:role], :order => "permissions.id ASC" @@ -67,7 +66,7 @@ class Provider < ActiveRecord::Base self.provider_accounts.each do |c| unless c.instances.empty? inst_list = c.instances.map {|i| i.name}.join(', ') - self.errors.add_to_base "there are instances for cloud account '#{c.name}': #{inst_list}" + self.errors.add(:base, "there are instances for cloud account '#{c.name}': #{inst_list}") end end end @@ -95,7 +94,7 @@ class Provider < ActiveRecord::Base end
protected - def validate + def validate_provider if !nil_or_empty(url) errors.add("url", "must be a valid provider url") unless valid_framework? end diff --git a/src/app/models/quota.rb b/src/app/models/quota.rb index 9583e5f..44b25d1 100644 --- a/src/app/models/quota.rb +++ b/src/app/models/quota.rb @@ -36,6 +36,8 @@
class Quota < ActiveRecord::Base
+ set_table_name "quotas" + has_one :pool has_one :pool_family has_one :provider_account diff --git a/src/app/models/search_filter.rb b/src/app/models/search_filter.rb index 0913933..a56aab8 100644 --- a/src/app/models/search_filter.rb +++ b/src/app/models/search_filter.rb @@ -20,7 +20,7 @@ module SearchFilter def self.included(base) base.class_eval do - named_scope :search_filter, lambda {|str, cols| + scope :search_filter, lambda {|str, cols| if str.to_s.empty? {:conditions => {}} else diff --git a/src/app/models/task.rb b/src/app/models/task.rb index 15e2eb7..ac164c7 100644 --- a/src/app/models/task.rb +++ b/src/app/models/task.rb @@ -136,7 +136,9 @@ class Task < ActiveRecord::Base time_ended - time_started end
- def validate + validate :validate_task + + def validate_task errors.add("created_at", "Task started but does not have the creation time set") if time_started and created_at.nil? # Removed check on time_started exisiting. if time_ended does. This can now occur, when the task fails before is starts. e.g. When Over Qutoa #errors.add("time_started", "Task ends but does not have the start time set") if time_ended and time_started.nil? diff --git a/src/app/models/user_session.rb b/src/app/models/user_session.rb index 544ec6b..43f4547 100644 --- a/src/app/models/user_session.rb +++ b/src/app/models/user_session.rb @@ -21,4 +21,10 @@
class UserSession < Authlogic::Session::Base generalize_credentials_error_messages true + + # http://railsplugins.org/plugins/56-authlogic + def to_key + new_record? ? nil : [self.send(self.class.primary_key)] + end + end diff --git a/src/config/application.rb b/src/config/application.rb index 042dc8a..11261ac 100644 --- a/src/config/application.rb +++ b/src/config/application.rb @@ -8,7 +8,7 @@ Bundler.require(:default, Rails.env) if defined?(Bundler)
$: << File.join(File.dirname(__FILE__), "../app")
-module Aggregator +module Conductor class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers @@ -41,6 +41,7 @@ module Aggregator
# Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password, :password_confirmation] + require 'lib/warehouse_model.rb'
config.after_initialize do Haml::Template.options[:format] = :html5 diff --git a/src/config/environments/test.rb b/src/config/environments/test.rb index ba633db..f4e4baf 100644 --- a/src/config/environments/test.rb +++ b/src/config/environments/test.rb @@ -1,4 +1,4 @@ -Aggregator::Application.configure do +Conductor::Application.configure do # Settings specified here will take precedence over those in config/environment.rb
# The test environment is used exclusively to run your application's
From: Mohammed Morsi mmorsi@redhat.com
Largely removes haml deprecations (-/=)
(edited by Jason Guiditta jguiditt@redhat.com) --- src/app/views/permissions/new.haml | 2 +- src/app/views/pools/new.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/app/views/permissions/new.haml b/src/app/views/permissions/new.haml index 9794368..3ae7745 100644 --- a/src/app/views/permissions/new.haml +++ b/src/app/views/permissions/new.haml @@ -3,7 +3,7 @@ %h2 Add new Permission for #{@permission_object.name} %br/ - - form_tag :action => 'create' do + = form_tag :action => 'create' do %ul %li %label diff --git a/src/app/views/pools/new.haml b/src/app/views/pools/new.haml index 949343a..b40557d 100644 --- a/src/app/views/pools/new.haml +++ b/src/app/views/pools/new.haml @@ -1 +1 @@ -= render :partial => 'new' \ No newline at end of file += render :partial => 'new'
From: Mohammed Morsi mmorsi@redhat.com
(edited by Jason Guiditta jguiditt@redhat.com) (edited by Scott Seago sseago@redhat.com) --- src/.rspec | 2 + src/Rakefile | 2 +- src/autotest/discover.rb | 2 + src/features/support/env.rb | 6 +- src/features/support/paths.rb | 2 +- src/lib/tasks/cucumber.rake | 29 +--- src/lib/tasks/demo_data.rake | 2 +- src/lib/tasks/rspec.rake | 157 -------------------- src/spec/controllers/pools_controller_spec.rb | 3 +- .../controllers/user_sessions_controller_spec.rb | 3 +- src/spec/controllers/users_controller_spec.rb | 1 + src/spec/models/hardware_profile_spec.rb | 2 +- src/spec/models/provider_spec.rb | 6 +- src/spec/models/user_spec.rb | 8 +- .../services/data_service_active_record_spec.rb | 6 +- src/spec/services/registration_service_spec.rb | 3 +- src/spec/spec.opts | 4 - src/spec/spec_helper.rb | 48 +----- 18 files changed, 42 insertions(+), 244 deletions(-) create mode 100644 src/.rspec create mode 100644 src/autotest/discover.rb delete mode 100644 src/lib/tasks/rspec.rake delete mode 100644 src/spec/spec.opts
diff --git a/src/.rspec b/src/.rspec new file mode 100644 index 0000000..89da67b --- /dev/null +++ b/src/.rspec @@ -0,0 +1,2 @@ +--colour +--format progress diff --git a/src/Rakefile b/src/Rakefile index d654057..408a087 100644 --- a/src/Rakefile +++ b/src/Rakefile @@ -4,6 +4,6 @@ require File.expand_path('../config/application', __FILE__) require 'rake' require 'rake/testtask' -require 'rake/rdoctask' +require 'rdoc/task'
Conductor::Application.load_tasks diff --git a/src/autotest/discover.rb b/src/autotest/discover.rb new file mode 100644 index 0000000..f421dc5 --- /dev/null +++ b/src/autotest/discover.rb @@ -0,0 +1,2 @@ +Autotest.add_discovery { "rails" } +Autotest.add_discovery { "rspec2" } diff --git a/src/features/support/env.rb b/src/features/support/env.rb index 33f9ed2..d06255f 100644 --- a/src/features/support/env.rb +++ b/src/features/support/env.rb @@ -4,11 +4,10 @@ # instead of editing this one. Cucumber will automatically load all features/**/*.rb # files.
-ENV["RAILS_ENV"] ||= "cucumber" +ENV["RAILS_ENV"] ||= "test" require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support -require 'cucumber/rails/rspec' require 'cucumber/rails/world' require 'cucumber/rails/active_record' require 'cucumber/web/tableish' @@ -20,11 +19,10 @@ require 'webrat' require 'webrat/core/matchers'
Webrat.configure do |config| - config.mode = :rails + config.mode = :rack config.open_error_files = false # Set to true if you want error pages to pop up in the browser end
- # If you set this to false, any error raised from within your app will bubble # up to your step definition and out to cucumber unless you catch it somewhere # on the way. You can make Rails rescue errors and render error pages on a diff --git a/src/features/support/paths.rb b/src/features/support/paths.rb index 35f0cfc..1461077 100644 --- a/src/features/support/paths.rb +++ b/src/features/support/paths.rb @@ -30,7 +30,7 @@ module NavigationHelpers account_path
when /the login error page/ - user_session_path + url_for :controller => 'user_sessions', :action => 'new', :only_path => true
when /the providers page/ url_for :controller => 'providers', :action => 'index', :only_path => true diff --git a/src/lib/tasks/cucumber.rake b/src/lib/tasks/cucumber.rake index 453f43c..64cca31 100644 --- a/src/lib/tasks/cucumber.rake +++ b/src/lib/tasks/cucumber.rake @@ -43,28 +43,11 @@ begin task :features => :cucumber do STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" end - - namespace :hudson do - def report_path - "hudson/reports/features/" - end - - Cucumber::Rake::Task.new({'cucumber' => [:report_setup]}) do |t| - t.cucumber_opts = %{--profile default --format junit --out #{report_path}} - end - - task :report_setup do - rm_rf report_path - mkdir_p report_path - end - - end - - rescue LoadError - desc 'cucumber rake task not available (cucumber not installed)' - task :cucumber do - abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' - end +rescue LoadError + desc 'cucumber rake task not available (cucumber not installed)' + task :cucumber do + abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' end +end
-end \ No newline at end of file +end diff --git a/src/lib/tasks/demo_data.rake b/src/lib/tasks/demo_data.rake index 8a58ede..4a32b3c 100644 --- a/src/lib/tasks/demo_data.rake +++ b/src/lib/tasks/demo_data.rake @@ -25,7 +25,7 @@ namespace :db do SHORT_ACC = PROB_SHORT_REPONSE + PROB_FAILURE MEDIUM_ACC = PROB_MEDIUM_RESPONSE + PROB_SHORT_REPONSE + PROB_FAILURE
- task :demo_data, :cloud_account_id, :user_id, :time_period, :number_of_tasks, :needs => :environment do |t, args| + task :demo_data, [:cloud_account_id, :user_id, :time_period, :number_of_tasks] => :environment do |t, args|
@time_scale = args[:time_period].to_f * 60 * 60 @number_of_tasks = args[:number_of_tasks] diff --git a/src/lib/tasks/rspec.rake b/src/lib/tasks/rspec.rake deleted file mode 100644 index 80d000d..0000000 --- a/src/lib/tasks/rspec.rake +++ /dev/null @@ -1,157 +0,0 @@ -gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 - -rspec_gem_dir = nil -Dir["#{RAILS_ROOT}/vendor/gems/*"].each do |subdir| - rspec_gem_dir = subdir if subdir.gsub("#{RAILS_ROOT}/vendor/gems/","") =~ /^(\w+-)?rspec-(\d+)/ && File.exist?("#{subdir}/lib/spec/rake/spectask.rb") -end -rspec_plugin_dir = File.expand_path(File.dirname(__FILE__) + '/../../vendor/plugins/rspec') - -if rspec_gem_dir && (test ?d, rspec_plugin_dir) - raise "\n#{'*'*50}\nYou have rspec installed in both vendor/gems and vendor/plugins\nPlease pick one and dispose of the other.\n#{'*'*50}\n\n" -end - -if rspec_gem_dir - $LOAD_PATH.unshift("#{rspec_gem_dir}/lib") -elsif File.exist?(rspec_plugin_dir) - $LOAD_PATH.unshift("#{rspec_plugin_dir}/lib") -end - -# Don't load rspec if running "rake gems:*" -unless ARGV.any? {|a| a =~ /^gems/} - -begin - require 'spec/rake/spectask' -rescue MissingSourceFile - module Spec - module Rake - class SpecTask - def initialize(name) - task name do - # if rspec-rails is a configured gem, this will output helpful material and exit ... - require File.expand_path(File.join(File.dirname(__FILE__),"..","..","config","environment")) - - # ... otherwise, do this: - raise <<-MSG - -#{"*" * 80} -* You are trying to run an rspec rake task defined in -* #{__FILE__}, -* but rspec can not be found in vendor/gems, vendor/plugins or system gems. -#{"*" * 80} -MSG - end - end - end - end - end -end - -Rake.application.instance_variable_get('@tasks').delete('default') - -spec_prereq = File.exist?(File.join(RAILS_ROOT, 'config', 'database.yml')) ? "db:test:prepare" : :noop -task :noop do -end - -task :default => :spec -task :stats => "spec:statsetup" - -desc "Run all specs in spec directory (excluding plugin specs)" -Spec::Rake::SpecTask.new(:spec => spec_prereq) do |t| - t.spec_opts = ['--options', ""#{RAILS_ROOT}/spec/spec.opts""] - t.spec_files = FileList['spec/**/*_spec.rb'] -end - -namespace :spec do - desc "Run all specs in spec directory with RCov (excluding plugin specs)" - Spec::Rake::SpecTask.new(:rcov) do |t| - t.spec_opts = ['--options', ""#{RAILS_ROOT}/spec/spec.opts""] - t.spec_files = FileList['spec/**/*_spec.rb'] - t.rcov = true - t.rcov_opts = lambda do - IO.readlines("#{RAILS_ROOT}/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten - end - end - - desc "Prepare JUnit output rspec for Hudson" - task :pre_junit do - gem 'ci_reporter' - require 'ci/reporter/rake/rspec' - ENV["CI_REPORTS"] = 'hudson/reports/spec/' - end - - desc "Run JUnit output filter for spec" - task :junit => [:pre_junit, "ci:setup:rspec", "spec"] - - desc "Print Specdoc for all specs (excluding plugin specs)" - Spec::Rake::SpecTask.new(:doc) do |t| - t.spec_opts = ["--format", "specdoc", "--dry-run"] - t.spec_files = FileList['spec/**/*_spec.rb'] - end - - desc "Print Specdoc for all plugin examples" - Spec::Rake::SpecTask.new(:plugin_doc) do |t| - t.spec_opts = ["--format", "specdoc", "--dry-run"] - t.spec_files = FileList['vendor/plugins/**/spec/**/*_spec.rb'].exclude('vendor/plugins/rspec/*') - end - - [:models, :controllers, :views, :helpers, :lib, :integration].each do |sub| - desc "Run the code examples in spec/#{sub}" - Spec::Rake::SpecTask.new(sub => spec_prereq) do |t| - t.spec_opts = ['--options', ""#{RAILS_ROOT}/spec/spec.opts""] - t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"] - end - end - - desc "Run the code examples in vendor/plugins (except RSpec's own)" - Spec::Rake::SpecTask.new(:plugins => spec_prereq) do |t| - t.spec_opts = ['--options', ""#{RAILS_ROOT}/spec/spec.opts""] - t.spec_files = FileList['vendor/plugins/**/spec/**/*_spec.rb'].exclude('vendor/plugins/rspec/*').exclude("vendor/plugins/rspec-rails/*") - end - - namespace :plugins do - desc "Runs the examples for rspec_on_rails" - Spec::Rake::SpecTask.new(:rspec_on_rails) do |t| - t.spec_opts = ['--options', ""#{RAILS_ROOT}/spec/spec.opts""] - t.spec_files = FileList['vendor/plugins/rspec-rails/spec/**/*_spec.rb'] - end - end - - # Setup specs for stats - task :statsetup do - require 'code_statistics' - ::STATS_DIRECTORIES << %w(Model\ specs spec/models) if File.exist?('spec/models') - ::STATS_DIRECTORIES << %w(View\ specs spec/views) if File.exist?('spec/views') - ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers) if File.exist?('spec/controllers') - ::STATS_DIRECTORIES << %w(Helper\ specs spec/helpers) if File.exist?('spec/helpers') - ::STATS_DIRECTORIES << %w(Library\ specs spec/lib) if File.exist?('spec/lib') - ::STATS_DIRECTORIES << %w(Routing\ specs spec/routing) if File.exist?('spec/routing') - ::STATS_DIRECTORIES << %w(Integration\ specs spec/integration) if File.exist?('spec/integration') - ::CodeStatistics::TEST_TYPES << "Model specs" if File.exist?('spec/models') - ::CodeStatistics::TEST_TYPES << "View specs" if File.exist?('spec/views') - ::CodeStatistics::TEST_TYPES << "Controller specs" if File.exist?('spec/controllers') - ::CodeStatistics::TEST_TYPES << "Helper specs" if File.exist?('spec/helpers') - ::CodeStatistics::TEST_TYPES << "Library specs" if File.exist?('spec/lib') - ::CodeStatistics::TEST_TYPES << "Routing specs" if File.exist?('spec/routing') - ::CodeStatistics::TEST_TYPES << "Integration specs" if File.exist?('spec/integration') - end - - namespace :db do - namespace :fixtures do - desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z." - task :load => :environment do - ActiveRecord::Base.establish_connection(Rails.env) - base_dir = File.join(Rails.root, 'spec', 'fixtures') - fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir - - require 'active_record/fixtures' - (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file| - Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*')) - end - end - end - end -end - -end - - diff --git a/src/spec/controllers/pools_controller_spec.rb b/src/spec/controllers/pools_controller_spec.rb index f5ee0cf..f9ec856 100644 --- a/src/spec/controllers/pools_controller_spec.rb +++ b/src/spec/controllers/pools_controller_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper'
describe PoolsController do + fixtures :all before(:each) do @admin_permission = Factory :admin_permission @@ -20,7 +21,7 @@ describe PoolsController do response.should_not be_success end
- it "should provider means to create new pool" do + it "should provide means to create new pool" do UserSession.create(@admin) lambda do post :create, :pool => { diff --git a/src/spec/controllers/user_sessions_controller_spec.rb b/src/spec/controllers/user_sessions_controller_spec.rb index b890b2e..33402bf 100644 --- a/src/spec/controllers/user_sessions_controller_spec.rb +++ b/src/spec/controllers/user_sessions_controller_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper'
describe UserSessionsController do + fixtures :all before(:each) do @tuser = Factory :tuser @@ -8,7 +9,7 @@ describe UserSessionsController do end
it "should call new method" do - route_for(:controller => 'user_sessions', :action => 'new').should == 'login' + {:get => 'login'}.should route_to(:controller => 'user_sessions', :action => 'new') get :new @current_user.should == nil UserSession.find.should == nil diff --git a/src/spec/controllers/users_controller_spec.rb b/src/spec/controllers/users_controller_spec.rb index 66bb50a..27d3037 100644 --- a/src/spec/controllers/users_controller_spec.rb +++ b/src/spec/controllers/users_controller_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper'
describe UsersController do
+ fixtures :all before(:each) do @tuser = Factory :tuser @admin_permission = Factory :admin_permission diff --git a/src/spec/models/hardware_profile_spec.rb b/src/spec/models/hardware_profile_spec.rb index 1dcd0af..c3b26aa 100644 --- a/src/spec/models/hardware_profile_spec.rb +++ b/src/spec/models/hardware_profile_spec.rb @@ -205,4 +205,4 @@ describe HardwareProfile do end enum_set.should == value_array end -end \ No newline at end of file +end diff --git a/src/spec/models/provider_spec.rb b/src/spec/models/provider_spec.rb index 0771c9a..49914c6 100644 --- a/src/spec/models/provider_spec.rb +++ b/src/spec/models/provider_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' describe Provider do context "(using stubbed out connect method)" do before(:each) do - @client = mock('', :null_object => true) + @client = mock('DeltaCloud').as_null_object @provider = Factory.build(:mock_provider) @provider.stub!(:connect).and_return(@client) end @@ -47,7 +47,7 @@ describe Provider do @provider.stub(:connect).and_return(nil) deltacloud = @provider.connect @provider.should have(1).error_on(:url) - @provider.errors.on(:url).should eql("must be a valid provider url") + @provider.errors[:url].first.should eql("must be a valid provider url") @provider.should_not be_valid deltacloud.should be_nil end @@ -86,7 +86,7 @@ describe Provider do
context "(using original connect method)" do it "should log errors when connecting to invalid url" do - @logger = mock('Logger', :null_object => true) + @logger = mock('Logger').as_null_object @provider = Factory.build(:mock_provider) @provider.stub!(:logger).and_return(@logger)
diff --git a/src/spec/models/user_spec.rb b/src/spec/models/user_spec.rb index acaba19..9637307 100644 --- a/src/spec/models/user_spec.rb +++ b/src/spec/models/user_spec.rb @@ -47,16 +47,16 @@ describe User do u = Factory(:tuser) u.first_name = ('a' * 256) u.valid?.should be_false - u.errors[:first_name].should_not be_nil - u.errors[:first_name].should =~ /^is too long.*/ + u.errors[:first_name].first.should_not be_nil + u.errors[:first_name].first.should =~ /^is too long.*/ end
it "should not be valid if last name is too long" do u = Factory(:tuser) u.last_name = ('a' * 256) u.valid?.should be_false - u.errors[:last_name].should_not be_nil - u.errors[:last_name].should =~ /^is too long.*/ + u.errors[:last_name].first.should_not be_nil + u.errors[:last_name].first.should =~ /^is too long.*/ end
it "should require quota to be set" do diff --git a/src/spec/services/data_service_active_record_spec.rb b/src/spec/services/data_service_active_record_spec.rb index d108e01..2a8ff8f 100644 --- a/src/spec/services/data_service_active_record_spec.rb +++ b/src/spec/services/data_service_active_record_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe DataServiceActiveRecord do
it "should calculate the total instance quota usage for a provider with a number of cloud accounts" do - client = mock('Conductor', :null_object => true) + client = mock('DeltaCloud').as_null_object provider = Factory.build(:mock_provider) provider.stub!(:connect).and_return(client) provider.save! @@ -29,7 +29,7 @@ describe DataServiceActiveRecord do end
it "should calculate the total number of instances and maximum number of instances of a cloud account" do - client = mock('Conductor', :null_object => true) + client = mock('DeltaCloud').as_null_object provider = Factory.build(:mock_provider) provider.stub!(:connect).and_return(client) provider.save! @@ -121,7 +121,7 @@ describe DataServiceActiveRecord do end_time = Time.utc(2010,"jan",1,20,15,1) start_time = end_time - (interval_length * no_intervals)
- client = mock('Conductor', :null_object => true) + client = mock('DeltaCloud').as_null_object provider = Factory.build(:mock_provider) provider.stub!(:connect).and_return(client) provider.save! diff --git a/src/spec/services/registration_service_spec.rb b/src/spec/services/registration_service_spec.rb index 222d028..dfc59ed 100644 --- a/src/spec/services/registration_service_spec.rb +++ b/src/spec/services/registration_service_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper'
describe RegistrationService do
+ fixtures :all before(:each) do end
@@ -14,7 +15,7 @@ describe RegistrationService do r.save.should be_false user.errors.empty?.should be_false user.errors.find_all do |attr,msg| - ["email","password","password_confirmation"].include?(attr).should be_true + [:email, :password, :password_confirmation].include?(attr).should be_true end end
diff --git a/src/spec/spec.opts b/src/spec/spec.opts deleted file mode 100644 index 391705b..0000000 --- a/src/spec/spec.opts +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---format progress ---loadby mtime ---reverse diff --git a/src/spec/spec_helper.rb b/src/spec/spec_helper.rb index ff6bde2..97aca3e 100644 --- a/src/spec/spec_helper.rb +++ b/src/spec/spec_helper.rb @@ -1,52 +1,22 @@ -# This file is copied to ~/spec when you run 'ruby script/generate rspec' -# from the project root directory. +# This file is copied to spec/ when you run 'rails generate rspec:install' ENV["RAILS_ENV"] ||= 'test' -require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment')) -require 'spec/autorun' -require 'spec/rails' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' require 'authlogic/test_case' require 'timecop' require 'database_cleaner' require 'vcr_setup'
-# Uncomment the next line to use webrat's matchers -#require 'webrat/integrations/rspec-rails' +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
-# Requires supporting files with custom matchers and macros, etc, -# in ./support/ and its subdirectories. -Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f} - -Spec::Runner.configure do |config| - # If you're not using ActiveRecord you should remove these - # lines, delete config/database.yml and disable :active_record - # in your config/boot.rb - config.use_transactional_fixtures = true - config.use_instantiated_fixtures = false - config.fixture_path = RAILS_ROOT + '/spec/fixtures/' - - # == Fixtures - # - # You can declare fixtures for each example_group like this: - # describe "...." do - # fixtures :table_a, :table_b - # - # Alternatively, if you prefer to declare them only once, you can - # do so right here. Just uncomment the next line and replace the fixture - # names with your fixtures. - # - # config.global_fixtures = :table_a, :table_b - # - # If you declare global fixtures, be aware that they will be declared - # for all of your examples, even those that don't use them. - # - # You can also declare which fixtures to use (for example fixtures for test/fixtures): - # - # config.fixture_path = RAILS_ROOT + '/spec/fixtures/' +RSpec.configure do |config| + include Authlogic::TestCase # # == Mock Framework # - # RSpec uses its own mocking framework by default. If you prefer to - # use mocha, flexmock or RR, uncomment the appropriate line: + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: # # config.mock_with :mocha # config.mock_with :flexmock
From: Mohammed Morsi mmorsi@redhat.com
Completely not code-related, just housekeeping
(edited by Jason Guiditta jguiditt@redhat.com) --- src/.gitignore | 5 ++++- src/.project | 12 ------------ 2 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 src/.project
diff --git a/src/.gitignore b/src/.gitignore index 6cddb31..af64fae 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1 +1,4 @@ -po +.bundle +db/*.sqlite3 +log/*.log +tmp/**/* diff --git a/src/.project b/src/.project deleted file mode 100644 index 52f7855..0000000 --- a/src/.project +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>Aeolus Conductor</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - </buildSpec> - <natures> - <nature>com.aptana.ide.project.nature.web</nature> - </natures> -</projectDescription>
From: Jason Guiditta jguiditt@redhat.com
We have never used this library, and should have excised this code long ago. --- src/public/javascripts/controls.js | 965 -------- src/public/javascripts/dragdrop.js | 974 -------- src/public/javascripts/effects.js | 1123 --------- src/public/javascripts/prototype.js | 4320 ----------------------------------- 4 files changed, 0 insertions(+), 7382 deletions(-) delete mode 100644 src/public/javascripts/controls.js delete mode 100644 src/public/javascripts/dragdrop.js delete mode 100644 src/public/javascripts/effects.js delete mode 100644 src/public/javascripts/prototype.js
diff --git a/src/public/javascripts/controls.js b/src/public/javascripts/controls.js deleted file mode 100644 index 7392fb6..0000000 --- a/src/public/javascripts/controls.js +++ /dev/null @@ -1,965 +0,0 @@ -// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 - -// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2009 Jon Tirsen (http://www.tirsen.com) -// Contributors: -// Richard Livsey -// Rahul Bhargava -// Rob Wills -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { }; -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element); - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - '<iframe id="' + this.update.id + '_iefix" '+ - 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + - 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index--; - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++; - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + - elem.substr(entry.length) + "</li>"); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + - elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( - foundPos + entry.length) + "</li>"); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); - return "<ul>" + ret.join('') + "</ul>"; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve tdd@tddsworld.com (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -}; - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML.unescapeHTML(); - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^[.*]$/.test(js)) // TODO: improve sanity check - throw('Server returned an invalid collection representation.'); - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}); \ No newline at end of file diff --git a/src/public/javascripts/dragdrop.js b/src/public/javascripts/dragdrop.js deleted file mode 100644 index 15c6dbc..0000000 --- a/src/public/javascripts/dragdrop.js +++ /dev/null @@ -1,974 +0,0 @@ -// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 - -// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// -// 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 = this.element.cumulativeOffset(); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this._originallyAbsolute) - Position.relativize(this.element); - delete this._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = this.element.cumulativeOffset(); - if(this.options.ghosting) { - var r = Position.realOffset(this.element); - pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)); - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight; - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_-](?:[A-Za-z0-9-_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - element = $(element); - var s = Sortable.sortables[element.id]; - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - }; - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - }; - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.identify()] = 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 = dropon.cumulativeOffset(); - 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')]; -}; \ No newline at end of file diff --git a/src/public/javascripts/effects.js b/src/public/javascripts/effects.js deleted file mode 100644 index c81e6c7..0000000 --- a/src/public/javascripts/effects.js +++ /dev/null @@ -1,1123 +0,0 @@ -// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 - -// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + .5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; - }, - pulse: function(pos, pulses) { - return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect, options) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - - return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, 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) { - if (options && options.transition === false) options.transition = Effect.Transitions.linear; - this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); - this.currentFrame = 0; - this.state = 'idle'; - this.startOn = this.options.delay*1000; - this.finishOn = this.startOn+(this.options.duration*1000); - this.fromToDelta = this.options.to-this.options.from; - this.totalTime = this.finishOn-this.startOn; - this.totalFrames = this.options.fps*this.options.duration; - - this.render = (function() { - function dispatch(effect, eventName) { - if (effect.options[eventName + 'Internal']) - effect.options[eventName + 'Internal'](effect); - if (effect.options[eventName]) - effect.options[eventName](effect); - } - - return function(pos) { - if (this.state === "idle") { - this.state = "running"; - dispatch(this, 'beforeSetup'); - if (this.setup) this.setup(); - dispatch(this, 'afterSetup'); - } - if (this.state === "running") { - pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; - this.position = pos; - dispatch(this, 'beforeUpdate'); - if (this.update) this.update(pos); - dispatch(this, 'afterUpdate'); - } - }; - })(); - - this.event('beforeStart'); - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).add(this); - }, - loop: function(timePos) { - if (timePos >= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()); } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }); - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}); }}); }}); }}); }}); }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ); - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }, - oldOpacity = element.getInlineOpacity(), - transition = options.transition || Effect.Transitions.linear, - reverser = function(pos){ - return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); - }; - - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - }; - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ); - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([+-]?[0-9.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ); - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([+-]?[0-9.]+)(em|ex|px|in|cm|mm|pt|pc|%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { - results[property] = css[property]; - return results; - }); - if (!styles.opacity) styles.opacity = element.getOpacity(); - return styles; - }; -} - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element); - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - }; - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/src/public/javascripts/prototype.js b/src/public/javascripts/prototype.js deleted file mode 100644 index dfe8ab4..0000000 --- a/src/public/javascripts/prototype.js +++ /dev/null @@ -1,4320 +0,0 @@ -/* Prototype JavaScript framework, version 1.6.0.3 - * (c) 2005-2008 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.6.0.3', - - Browser: { - IE: !!(window.attachEvent && - navigator.userAgent.indexOf('Opera') === -1), - Opera: navigator.userAgent.indexOf('Opera') > -1, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && - navigator.userAgent.indexOf('KHTML') === -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, - - BrowserFeatures: { - XPath: !!document.evaluate, - SelectorsAPI: !!document.querySelector, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div')['__proto__'] && - document.createElement('div')['__proto__'] !== - document.createElement('form')['__proto__'] - }, - - ScriptFragment: '<script[^>]*>([\S\s]*?)</script>', - JSONFilter: /^/*-secure-([\s\S]*)*/\s*$/, - - emptyFunction: function() { }, - K: function(x) { return x } -}; - -if (Prototype.Browser.MobileSafari) - Prototype.BrowserFeatures.SpecificElementExtensions = false; - - -/* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - var subclass = function() { }; - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0; i < properties.length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - - return klass; - } -}; - -Class.Methods = { - addMethods: function(source) { - var ancestor = this.superclass && this.superclass.prototype; - var properties = Object.keys(source); - - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames().first() == "$super") { - var method = value; - value = (function(m) { - return function() { return ancestor[m].apply(this, arguments) }; - })(property).wrap(method); - - value.valueOf = method.valueOf.bind(method); - value.toString = method.toString.bind(method); - } - this.prototype[property] = value; - } - - return this; - } -}; - -var Abstract = { }; - -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; - -Object.extend(Object, { - inspect: function(object) { - try { - if (Object.isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - }, - - toJSON: function(object) { - var type = typeof object; - switch (type) { - case 'undefined': - case 'function': - case 'unknown': return; - case 'boolean': return object.toString(); - } - - if (object === null) return 'null'; - if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; - - var results = []; - for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) - results.push(property.toJSON() + ': ' + value); - } - - return '{' + results.join(', ') + '}'; - }, - - toQueryString: function(object) { - return $H(object).toQueryString(); - }, - - toHTML: function(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, - - keys: function(object) { - var keys = []; - for (var property in object) - keys.push(property); - return keys; - }, - - values: function(object) { - var values = []; - for (var property in object) - values.push(object[property]); - return values; - }, - - clone: function(object) { - return Object.extend({ }, object); - }, - - isElement: function(object) { - return !!(object && object.nodeType == 1); - }, - - isArray: function(object) { - return object != null && typeof object == "object" && - 'splice' in object && 'join' in object; - }, - - isHash: function(object) { - return object instanceof Hash; - }, - - isFunction: function(object) { - return typeof object == "function"; - }, - - isString: function(object) { - return typeof object == "string"; - }, - - isNumber: function(object) { - return typeof object == "number"; - }, - - isUndefined: function(object) { - return typeof object == "undefined"; - } -}); - -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s(]*function[^(]*(([^)]*))/)[1] - .replace(/\s+/g, '').split(','); - return names.length == 1 && !names[0] ? [] : names; - }, - - bind: function() { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } - }, - - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function(event) { - return __method.apply(object, [event || window.event].concat(args)); - } - }, - - curry: function() { - if (!arguments.length) return this; - var __method = this, args = $A(arguments); - return function() { - return __method.apply(this, args.concat($A(arguments))); - } - }, - - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - }, - - defer: function() { - var args = [0.01].concat($A(arguments)); - return this.delay.apply(this, args); - }, - - wrap: function(wrapper) { - var __method = this; - return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); - } - }, - - methodize: function() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); - }; - } -}); - -Date.prototype.toJSON = function() { - return '"' + this.getUTCFullYear() + '-' + - (this.getUTCMonth() + 1).toPaddedString(2) + '-' + - this.getUTCDate().toPaddedString(2) + 'T' + - this.getUTCHours().toPaddedString(2) + ':' + - this.getUTCMinutes().toPaddedString(2) + ':' + - this.getUTCSeconds().toPaddedString(2) + 'Z"'; -}; - -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; - -RegExp.prototype.match = RegExp.prototype.test; - -RegExp.escape = function(str) { - return String(str).replace(/([.*+?^=!:${}()|[]/\])/g, '\$1'); -}; - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create({ - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - } finally { - this.currentlyExecuting = false; - } - } - } -}); -Object.extend(String, { - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\b', - '\t': '\t', - '\n': '\n', - '\f': '\f', - '\r': '\r', - '\': '\\' - } -}); - -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); - count = Object.isUndefined(count) ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - }, - - scan: function(pattern, iterator) { - this.gsub(pattern, iterator); - return String(this); - }, - - truncate: function(length, truncation) { - length = length || 30; - truncation = Object.isUndefined(truncation) ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : String(this); - }, - - strip: function() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - stripTags: function() { - return this.replace(/</?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(function(script) { return eval(script) }); - }, - - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, - - unescapeHTML: function() { - var div = new Element('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : - div.childNodes[0].nodeValue) : ''; - }, - - toQueryParams: function(separator) { - var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - return match[1].split(separator || '&').inject({ }, function(hash, pair) { - if ((pair = pair.split('='))[0]) { - var key = decodeURIComponent(pair.shift()); - var value = pair.length > 1 ? pair.join('=') : pair[0]; - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - return hash; - }); - }, - - toArray: function() { - return this.split(''); - }, - - succ: function() { - return this.slice(0, this.length - 1) + - String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, - - times: function(count) { - return count < 1 ? '' : new Array(count + 1).join(this); - }, - - camelize: function() { - var parts = this.split('-'), len = parts.length; - if (len == 1) return parts[0]; - - var camelized = this.charAt(0) == '-' - ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) - : parts[0]; - - for (var i = 1; i < len; i++) - camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); - - return camelized; - }, - - capitalize: function() { - return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - }, - - underscore: function() { - return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); - }, - - dasherize: function() { - return this.gsub(/_/,'-'); - }, - - inspect: function(useDoubleQuotes) { - var escapedString = this.gsub(/[\x00-\x1f\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\u00' + match[0].charCodeAt().toPaddedString(2, 16); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\"') + '"'; - return "'" + escapedString.replace(/'/g, '\'') + "'"; - }, - - toJSON: function() { - return this.inspect(true); - }, - - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, - - isJSON: function() { - var str = this; - if (str.blank()) return false; - str = this.replace(/\./g, '@').replace(/"[^"\\n\r]*"/g, ''); - return (/^[,:{}[]0-9.-+Eaeflnr-u \n\r\t]*$/).test(str); - }, - - evalJSON: function(sanitize) { - var json = this.unfilterJSON(); - try { - if (!sanitize || json.isJSON()) return eval('(' + json + ')'); - } catch (e) { } - throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - }, - - include: function(pattern) { - return this.indexOf(pattern) > -1; - }, - - startsWith: function(pattern) { - return this.indexOf(pattern) === 0; - }, - - endsWith: function(pattern) { - var d = this.length - pattern.length; - return d >= 0 && this.lastIndexOf(pattern) === d; - }, - - empty: function() { - return this == ''; - }, - - blank: function() { - return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); - } -}); - -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - }, - unescapeHTML: function() { - return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - } -}); - -String.prototype.gsub.prepareReplacement = function(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -String.prototype.parseQuery = String.prototype.toQueryParams; - -Object.extend(String.prototype.escapeHTML, { - div: document.createElement('div'), - text: document.createTextNode('') -}); - -String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); - -var Template = Class.create({ - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) - object = object.toTemplateReplacements(); - - return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; - - var before = match[1] || ''; - if (before == '\') return match[2]; - - var ctx = object, expr = match[3]; - var pattern = /^([^.[]+|[((?:.*?[^\])?)])(.|[|$)/; - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\]', ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + String.interpret(ctx); - }); - } -}); -Template.Pattern = /(^|.|\r|\n)(#{(.*?)})/; - -var $break = { }; - -var Enumerable = { - each: function(iterator, context) { - var index = 0; - try { - this._each(function(value) { - iterator.call(context, value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - }, - - eachSlice: function(number, iterator, context) { - var index = -number, slices = [], array = this.toArray(); - if (number < 1) return array; - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - }, - - all: function(iterator, context) { - iterator = iterator || Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator.call(context, value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator, context) { - iterator = iterator || Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator.call(context, value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator.call(context, value, index)); - }); - return results; - }, - - detect: function(iterator, context) { - var result; - this.each(function(value, index) { - if (iterator.call(context, value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator, context) { - var results = []; - this.each(function(value, index) { - if (iterator.call(context, value, index)) - results.push(value); - }); - return results; - }, - - grep: function(filter, iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(filter); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator.call(context, value, index)); - }); - return results; - }, - - include: function(object) { - if (Object.isFunction(this.indexOf)) - if (this.indexOf(object) != -1) return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inGroupsOf: function(number, fillWith) { - fillWith = Object.isUndefined(fillWith) ? null : fillWith; - return this.eachSlice(number, function(slice) { - while(slice.length < number) slice.push(fillWith); - return slice; - }); - }, - - inject: function(memo, iterator, context) { - this.each(function(value, index) { - memo = iterator.call(context, memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index); - if (result == null || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index); - if (result == null || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator, context) { - iterator = iterator || Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator.call(context, value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator, context) { - var results = []; - this.each(function(value, index) { - if (!iterator.call(context, value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator, context) { - return this.map(function(value, index) { - return { - value: value, - criteria: iterator.call(context, value, index) - }; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.map(); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - }, - - size: function() { - return this.toArray().length; - }, - - inspect: function() { - return '#<Enumerable:' + this.toArray().inspect() + '>'; - } -}; - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -if (Prototype.Browser.WebKit) { - $A = function(iterable) { - if (!iterable) return []; - // In Safari, only use the `toArray` method if it's not a NodeList. - // A NodeList is a function, has an function `item` property, and a numeric - // `length` property. Adapted from Google Doctype. - if (!(typeof iterable === 'function' && typeof iterable.length === - 'number' && typeof iterable.item === 'function') && iterable.toArray) - return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - }; -} - -Array.from = $A; - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0, length = this.length; i < length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, - - uniq: function(sorted) { - return this.inject([], function(array, value, index) { - if (0 == index || (sorted ? array.last() != value : !array.include(value))) - array.push(value); - return array; - }); - }, - - intersect: function(array) { - return this.uniq().findAll(function(item) { - return array.detect(function(value) { return item === value }); - }); - }, - - clone: function() { - return [].concat(this); - }, - - size: function() { - return this.length; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - }, - - toJSON: function() { - var results = []; - this.each(function(object) { - var value = Object.toJSON(object); - if (!Object.isUndefined(value)) results.push(value); - }); - return '[' + results.join(', ') + ']'; - } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; - -Array.prototype.toArray = Array.prototype.clone; - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); - for (var i = 0, length = arguments.length; i < length; i++) { - if (Object.isArray(arguments[i])) { - for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) - array.push(arguments[i][j]); - } else { - array.push(arguments[i]); - } - } - return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator, context) { - $R(0, this, true).each(iterator, context); - return this; - }, - - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, - - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); - -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); -function $H(object) { - return new Hash(object); -}; - -var Hash = Class.create(Enumerable, (function() { - - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - return key + '=' + encodeURIComponent(String.interpret(value)); - } - - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - set: function(key, value) { - return this._object[key] = value; - }, - - get: function(key) { - // simulating poorly supported hasOwnProperty - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - }, - - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, - - toObject: function() { - return Object.clone(this._object); - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, - - merge: function(object) { - return this.clone().update(object); - }, - - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, - - toQueryString: function() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return results.concat(values.map(toQueryPair.curry(key))); - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - }, - - inspect: function() { - return '#<Hash:{' + this.map(function(pair) { - return pair.map(Object.inspect).join(': '); - }).join(', ') + '}>'; - }, - - toJSON: function() { - return Object.toJSON(this.toObject()); - }, - - clone: function() { - return new Hash(this); - } - } -})()); - -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - while (this.include(value)) { - iterator(value); - value = value.succ(); - } - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -}; - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -}; - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); - -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isString(this.options.parameters)) - this.options.parameters = this.options.parameters.toQueryParams(); - else if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); - -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - var params = Object.clone(this.options.parameters); - - if (!['get', 'post'].include(this.method)) { - // simulate other verbs over post - params['_method'] = this.method; - this.method = 'post'; - } - - this.parameters = params; - - if (params = Object.toQueryString(params)) { - // when GET, append parameters to URL - if (this.method == 'get') - this.url += (this.url.include('?') ? '&' : '?') + params; - else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - params += '&_='; - } - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - this.body = this.method == 'post' ? (this.options.postBody || params) : null; - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method == 'post') { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - // user-defined headers - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - for (var name in headers) - this.transport.setRequestHeader(name, headers[name]); - }, - - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300); - }, - - getStatus: function() { - try { - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && this.isSameOrigin() && contentType - && contentType.match(/^\s*(text|application)/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - if (state == 'Complete') { - // avoid memory leak in MSIE: clean up - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - isSameOrigin: function() { - var m = this.url.match(/^\s*https?://[^/]*/); - return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ - protocol: location.protocol, - domain: document.domain, - port: location.port ? ':' + location.port : '' - })); - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Response = Class.create({ - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if(readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - status: 0, - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - getHeader: Ajax.Request.prototype.getHeader, - - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - json = decodeURIComponent(escape(json)); - try { - return json.evalJSON(this.request.options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - } -}); - -Ajax.Updater = Class.create(Ajax.Request, { - initialize: function($super, container, url, options) { - this.container = { - success: (container.success || container), - failure: (container.failure || (container.success ? null : container)) - }; - - options = Object.clone(options); - var onComplete = options.onComplete; - options.onComplete = (function(response, json) { - this.updateContent(response.responseText); - if (Object.isFunction(onComplete)) onComplete(response, json); - }).bind(this); - - $super(url, options); - }, - - updateContent: function(responseText) { - var receiver = this.container[this.success() ? 'success' : 'failure'], - options = this.options; - - if (!options.evalScripts) responseText = responseText.stripScripts(); - - if (receiver = $(receiver)) { - if (options.insertion) { - if (Object.isString(options.insertion)) { - var insertion = { }; insertion[options.insertion] = responseText; - receiver.insert(insertion); - } - else options.insertion(receiver, responseText); - } - else receiver.update(responseText); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.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 || { }); - if (element) this.Element.prototype = element.prototype; -}).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 = $(element); - element.style.display = 'none'; - return element; - }, - - show: function(element) { - element = $(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, insert, tagName, childNodes; - - for (var position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - insert = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - insert(element, content); - continue; - } - - content = Object.toHTML(content); - - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - - if (position == 'top' || position == 'after') childNodes.reverse(); - childNodes.each(insert.curry(element)); - - 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).select("*"); - }, - - 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 Object.isNumber(expression) ? ancestors[expression] : - Selector.findElement(ancestors, expression, index); - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? element.descendants()[expression] : - Element.select(element, expression)[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); - return Object.isNumber(expression) ? previousSiblings[expression] : - Selector.findElement(previousSiblings, expression, index); - }, - - next: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); - return Object.isNumber(expression) ? nextSiblings[expression] : - Selector.findElement(nextSiblings, expression, index); - }, - - 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); - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (ancestor.contains) - return ancestor.contains(element) && ancestor !== element; - - while (element = element.parentNode) - if (element == ancestor) 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 || value == 'auto') { - 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 (Prototype.Browser.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.toUpperCase() == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (element.getStyle('position') == 'absolute') return element; - // 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 element; - // 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 && (element.tagName.toUpperCase() == '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 (Prototype.Browser.Opera) { - Element.Methods.getStyle = Element.Methods.getStyle.wrap( - function(proceed, element, style) { - switch (style) { - case 'left': case 'top': case 'right': case 'bottom': - if (proceed(element, 'position') === 'static') return null; - case 'height': case 'width': - // returns '0px' for hidden elements; we want it to return null - if (!Element.visible(element)) return null; - - // returns the border-box dimensions rather than the content-box - // dimensions, so we subtract padding and borders from the value - var dim = parseInt(proceed(element, style), 10); - - if (dim !== element['offset' + style.capitalize()]) - return dim + 'px'; - - var properties; - if (style === 'height') { - properties = ['border-top-width', 'padding-top', - 'padding-bottom', 'border-bottom-width']; - } - else { - properties = ['border-left-width', 'padding-left', - 'padding-right', 'border-right-width']; - } - return properties.inject(dim, function(memo, property) { - var val = proceed(element, property); - return val === null ? memo : memo - parseInt(val, 10); - }) + 'px'; - default: return proceed(element, style); - } - } - ); - - Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( - function(proceed, element, attribute) { - if (attribute === 'title') return element.title; - return proceed(element, attribute); - } - ); -} - -else if (Prototype.Browser.IE) { - // IE doesn't report offsets correctly for static elements, so we change them - // to "relative" to get the values, then change them back. - Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( - function(proceed, element) { - element = $(element); - // IE throws an error if element is not in document - try { element.offsetParent } - catch(e) { return $(document.body) } - 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; - } - ); - - $w('positionedOffset viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - try { element.offsetParent } - catch(e) { return Element._returnOffset(0,0) } - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - // Trigger hasLayout on the offset parent so that IE6 reports - // accurate offsetTop and offsetLeft values for position: fixed. - var offsetParent = element.getOffsetParent(); - if (offsetParent && offsetParent.getStyle('position') === 'fixed') - offsetParent.setStyle({ zoom: 1 }); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( - function(proceed, element) { - try { element.offsetParent } - catch(e) { return Element._returnOffset(0,0) } - return proceed(element); - } - ); - - 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.extend({ - cellpadding: 'cellPadding', - cellspacing: 'cellSpacing' - }, 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 frameBorder').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.toUpperCase() == '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 Element#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 ('outerHTML' in document.createElement('div')) { - 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]; - if (t) { - div.innerHTML = t[0] + html + t[1]; - t[2].times(function() { div = div.firstChild }); - } else div.innerHTML = html; - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - top: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - bottom: function(element, node) { - element.appendChild(node); - }, - after: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - 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() { - 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.toUpperCase(), 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 = { }, B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - if (B.WebKit && !document.evaluate) { - // Safari <3.0 needs self.innerWidth/Height - dimensions[d] = self['inner' + D]; - } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { - // Opera <9.5 needs document.body.clientWidth/Height - dimensions[d] = document.body['client' + D] - } else { - dimensions[d] = document.documentElement['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(); - - if (this.shouldUseSelectorsAPI()) { - this.mode = 'selectorsAPI'; - } else if (this.shouldUseXPath()) { - this.mode = 'xpath'; - this.compileXPathMatcher(); - } else { - this.mode = "normal"; - 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(e)) - return false; - - return true; - }, - - shouldUseSelectorsAPI: function() { - if (!Prototype.BrowserFeatures.SelectorsAPI) return false; - - if (!Selector._div) Selector._div = new Element('div'); - - // Make sure the browser treats the selector as valid. Test on an - // isolated element to minimize cost of this check. - try { - Selector._div.querySelector(this.expression); - } catch(e) { - return false; - } - - return true; - }, - - compileMatcher: function() { - 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; - var e = this.expression, results; - - switch (this.mode) { - case 'selectorsAPI': - // querySelectorAll queries document-wide, then filters to descendants - // of the context element. That's not what we want. - // Add an explicit context to the selector if necessary. - if (root !== document) { - var oldId = root.id, id = $(root).identify(); - e = "#" + id + " " + e; - } - - results = $A(root.querySelectorAll(e)).map(Element.extend); - root.id = oldId; - - return results; - case 'xpath': - return document._getElementsByXPath(this.xpath, root); - default: - 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)]", - 'checked': "[@checked]", - 'disabled': "[(@disabled) and (@type!='hidden')]", - 'enabled': "[not(@disabled) and (@type!='hidden')]", - '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); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); 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]+:)?[\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 nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); - } - }, - - 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) { - var _true = Prototype.emptyFunction; - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = _true; - return nodes; - }, - - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = 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._countedByPrototype = Prototype.emptyFunction; - 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._countedByPrototype)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) 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])._countedByPrototype) { - n._countedByPrototype = Prototype.emptyFunction; - 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) { - var uTagName = 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() === uTagName) 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, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - 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, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - 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._countedByPrototype) { - 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) 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._countedByPrototype) 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 && (!node.type || node.type !== 'hidden')) - 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 == v || nv && nv.startsWith(v); }, - '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, - '*=': function(nv, v) { return nv == v || nv && nv.include(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() + '-'); } - }, - - split: function(expression) { - var expressions = []; - expression.scan(/(([\w#:.~>+()\s-]+|*|[.*?])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - return expressions; - }, - - matchElements: function(elements, expression) { - var matches = $$(expression), h = Selector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._countedByPrototype) 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) { - expressions = Selector.split(expressions.join(',')); - 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) { - Object.extend(Selector.handlers, { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - if (node.tagName !== "!") a.push(node); - return a; - }, - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML. - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; - } - }); -} - -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 != 'file' && (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.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, value) { - if (Object.isUndefined(value)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, currentValue, single = !Object.isArray(value); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - currentValue = this.optionValue(opt); - if (single) { - if (currentValue == value) { - opt.selected = true; - return; - } - } - else opt.selected = value.include(currentValue); - } - } - }, - - 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) { - event = Event.extend(event); - - var node = event.target, - type = event.type, - currentTarget = event.currentTarget; - - if (currentTarget && currentTarget.tagName) { - // Firefox screws up the "click" event when moving between radio buttons - // via arrow keys. It also screws up the "load" and "error" events on images, - // reporting the document as the target instead of the original image. - if (type === 'load' || type === 'error' || - (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' - && currentTarget.type === 'radio')) - node = currentTarget; - } - if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; - return Element.extend(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) { - var docElement = document.documentElement, - body = document.body || { scrollLeft: 0, scrollTop: 0 }; - return { - x: event.pageX || (event.clientX + - (docElement.scrollLeft || body.scrollLeft) - - (docElement.clientLeft || 0)), - y: event.pageY || (event.clientY + - (docElement.scrollTop || body.scrollTop) - - (docElement.clientTop || 0)) - }; - }, - - 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._prototypeEventID) return element._prototypeEventID[0]; - arguments.callee.id = arguments.callee.id || 1; - return element._prototypeEventID = [++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; - } - - - // Internet Explorer needs to remove event handlers on page unload - // in order to avoid memory leaks. - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } - - // Safari has a dummy event handler on page unload so that it won't - // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" - // object when page is returned to via the back button using its bfcache. - if (Prototype.Browser.WebKit) { - window.addEventListener('unload', Prototype.emptyFunction, false); - } - - 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; - - var event; - if (document.createEvent) { - event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - 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(), - loaded: false -}); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ - - var timer; - - function fireContentLoadedEvent() { - if (document.loaded) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); - document.loaded = 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
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jason Guiditta jguiditt@redhat.com
We have never used this library, and should have excised this code long ago.
ACK. Another good candidate for pushing right away
Cheers, Mark.
On 07/28/11 - 10:13:13AM, Mark McLoughlin wrote:
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jason Guiditta jguiditt@redhat.com
We have never used this library, and should have excised this code long ago.
ACK. Another good candidate for pushing right away
Thanks, pushed.
From: Jason Guiditta jguiditt@redhat.com
We have these in compressed form, no real need for these copies in src control. --- src/public/javascripts/ui.core.js | 237 --------------------- src/public/javascripts/ui.slider.js | 386 ----------------------------------- 2 files changed, 0 insertions(+), 623 deletions(-) delete mode 100644 src/public/javascripts/ui.core.js delete mode 100644 src/public/javascripts/ui.slider.js
diff --git a/src/public/javascripts/ui.core.js b/src/public/javascripts/ui.core.js deleted file mode 100644 index 5693359..0000000 --- a/src/public/javascripts/ui.core.js +++ /dev/null @@ -1,237 +0,0 @@ -/* - * jQuery UI @VERSION - * - * Copyright (c) 2008 Paul Bakaus (ui.jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI - * - * $Date: 2008-05-04 16:52:15 +0200 (So, 04 Mai 2008) $ - * $Rev: 5419 $ - */ -;(function($) { - - $.ui = { - plugin: { - add: function(module, option, set) { - var proto = $.ui[module].prototype; - for(var i in set) { - proto.plugins[i] = proto.plugins[i] || []; - proto.plugins[i].push([option, set[i]]); - } - }, - call: function(instance, name, args) { - var set = instance.plugins[name]; - if(!set) { return; } - - for (var i = 0; i < set.length; i++) { - if (instance.options[set[i][0]]) { - set[i][1].apply(instance.element, args); - } - } - } - }, - cssCache: {}, - css: function(name) { - if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; } - var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body'); - - //if (!$.browser.safari) - //tmp.appendTo('body'); - - //Opera and Safari set width and height to 0px instead of auto - //Safari returns rgba(0,0,0,0) when bgcolor is not set - $.ui.cssCache[name] = !!( - (!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || - !(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba(0, 0, 0, 0)/).test(tmp.css('backgroundColor'))) - ); - try { $('body').get(0).removeChild(tmp.get(0)); } catch(e){} - return $.ui.cssCache[name]; - }, - disableSelection: function(e) { - e.unselectable = "on"; - e.onselectstart = function() { return false; }; - if (e.style) { e.style.MozUserSelect = "none"; } - }, - enableSelection: function(e) { - e.unselectable = "off"; - e.onselectstart = function() { return true; }; - if (e.style) { e.style.MozUserSelect = ""; } - }, - hasScroll: function(e, a) { - var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false; - if (e[scroll] > 0) return true; e[scroll] = 1; - has = e[scroll] > 0 ? true : false; e[scroll] = 0; - return has; - } - }; - - - /** jQuery core modifications and additions **/ - - var _remove = $.fn.remove; - $.fn.remove = function() { - $("*", this).add(this).trigger("remove"); - return _remove.apply(this, arguments ); - }; - - // $.widget is a factory to create jQuery plugins - // taking some boilerplate code out of the plugin code - // created by Scott González and Jörn Zaefferer - function getter(namespace, plugin, method) { - var methods = $[namespace][plugin].getter || []; - methods = (typeof methods == "string" ? methods.split(/,?\s+/) : methods); - return ($.inArray(method, methods) != -1); - }; - - var widgetPrototype = { - init: function() {}, - destroy: function() {}, - - getData: function(e, key) { - return this.options[key]; - }, - setData: function(e, key, value) { - this.options[key] = value; - }, - - enable: function() { - this.setData(null, 'disabled', false); - }, - disable: function() { - this.setData(null, 'disabled', true); - } - }; - - $.widget = function(name, prototype) { - var namespace = name.split(".")[0]; - name = name.split(".")[1]; - // create plugin method - $.fn[name] = function(options, data) { - var isMethodCall = (typeof options == 'string'), - args = arguments; - - if (isMethodCall && getter(namespace, name, options)) { - var instance = $.data(this[0], name); - return (instance ? instance[options](data) : undefined); - } - - return this.each(function() { - var instance = $.data(this, name); - if (!instance) { - $.data(this, name, new $[namespace][name](this, options)); - } else if (isMethodCall) { - instance[options].apply(instance, $.makeArray(args).slice(1)); - } - }); - }; - - // create widget constructor - $[namespace][name] = function(element, options) { - var self = this; - - this.options = $.extend({}, $[namespace][name].defaults, options); - this.element = $(element) - .bind('setData.' + name, function(e, key, value) { - return self.setData(e, key, value); - }) - .bind('getData.' + name, function(e, key) { - return self.getData(e, key); - }) - .bind('remove', function() { - return self.destroy(); - }); - this.init(); - }; - - // add widget prototype - $[namespace][name].prototype = $.extend({}, widgetPrototype, prototype); - }; - - - /** Mouse Interaction Plugin **/ - - $.widget("ui.mouse", { - init: function() { - var self = this; - - this.element - .bind('mousedown.mouse', function() { return self.click.apply(self, arguments); }) - .bind('mouseup.mouse', function() { (self.timer && clearInterval(self.timer)); }) - .bind('click.mouse', function() { if(self.initialized) { self.initialized = false; return false; } }); - //Prevent text selection in IE - if ($.browser.msie) { - this.unselectable = this.element.attr('unselectable'); - this.element.attr('unselectable', 'on'); - } - }, - destroy: function() { - this.element.unbind('.mouse').removeData("mouse"); - ($.browser.msie && this.element.attr('unselectable', this.unselectable)); - }, - trigger: function() { return this.click.apply(this, arguments); }, - click: function(e) { - - if( e.which != 1 //only left click starts dragging - || $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements - || (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition - ) { return true; } - - var self = this; - this.initialized = false; - var initialize = function() { - self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position - $(document).bind('mouseup.mouse', function() { return self.stop.apply(self, arguments); }); - $(document).bind('mousemove.mouse', function() { return self.drag.apply(self, arguments); }); - - if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) { - (self.options.start && self.options.start.call(self.options.executor || self, e, self.element)); - (self.options.drag && self.options.drag.call(self.options.executor || self, e, this.element)); //This is actually not correct, but expected - self.initialized = true; - } - }; - - if(this.options.delay) { - if(this.timer) { clearInterval(this.timer); } - this.timer = setTimeout(initialize, this.options.delay); - } else { - initialize(); - } - - return false; - - }, - stop: function(e) { - - if(!this.initialized) { - return $(document).unbind('mouseup.mouse').unbind('mousemove.mouse'); - } - - (this.options.stop && this.options.stop.call(this.options.executor || this, e, this.element)); - - $(document).unbind('mouseup.mouse').unbind('mousemove.mouse'); - return false; - - }, - drag: function(e) { - - var o = this.options; - if ($.browser.msie && !e.button) { - return this.stop.call(this, e); // IE mouseup check - } - - if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) { - (o.start && o.start.call(o.executor || this, e, this.element)); - this.initialized = true; - } else { - if(!this.initialized) { return false; } - } - - (o.drag && o.drag.call(this.options.executor || this, e, this.element)); - return false; - - } - }); - -})(jQuery); diff --git a/src/public/javascripts/ui.slider.js b/src/public/javascripts/ui.slider.js deleted file mode 100644 index 6c49199..0000000 --- a/src/public/javascripts/ui.slider.js +++ /dev/null @@ -1,386 +0,0 @@ -/* - * jQuery UI Slider - * - * Copyright (c) 2008 Paul Bakaus - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Slider - * - * Depends: - * ui.core.js - * - * Revision: $Id: ui.slider.js 5452 2008-05-05 16:42:08Z rdworth $ - */ -;(function($) { - - $.widget("ui.slider", { - init: function() { - var self = this; - this.element.addClass("ui-slider"); - this.initBoundaries(); - - // Initialize mouse and key events for interaction - this.handle = $(this.options.handle, this.element); - if (!this.handle.length) { - self.handle = self.generated = $(self.options.handles || [0]).map(function() { - var handle = $("<div/>").addClass("ui-slider-handle").appendTo(self.element); - if (this.id) - handle.attr("id", this.id); - return handle[0]; - }); - } - $(this.handle) - .mouse({ - executor: this, - delay: this.options.delay, - distance: this.options.distance, - dragPrevention: this.options.prevention ? this.options.prevention.toLowerCase().split(',') : ['input','textarea','button','select','option'], - start: this.start, - stop: this.stop, - drag: this.drag, - condition: function(e, handle) { - if(!this.disabled) { - if(this.currentHandle) this.blur(this.currentHandle); - this.focus(handle,1); - return !this.disabled; - } - } - }) - .wrap('<a href="javascript:void(0)" style="cursor:default;"></a>') - .parent() - .bind('focus', function(e) { self.focus(this.firstChild); }) - .bind('blur', function(e) { self.blur(this.firstChild); }) - .bind('keydown', function(e) { - if(/(37|38|39|40)/.test(e.keyCode)) { - self.moveTo({ - x: /(37|39)/.test(e.keyCode) ? (e.keyCode == 37 ? '-' : '+') + '=' + self.oneStep(1) : null, - y: /(38|40)/.test(e.keyCode) ? (e.keyCode == 38 ? '-' : '+') + '=' + self.oneStep(2) : null - }, this.firstChild); - } - }) - ; - - // Prepare dynamic properties for later use - this.actualSize = { width: this.element.outerWidth() , height: this.element.outerHeight() }; - - // Bind the click to the slider itself - this.element.bind('mousedown.slider', function(e) { - self.click.apply(self, [e]); - self.currentHandle.data("mouse").trigger(e); - self.firstValue = self.firstValue + 1; //This is for always triggering the change event - }); - - // Move the first handle to the startValue - $.each(this.options.handles || [], function(index, handle) { - self.moveTo(handle.start, index, true); - }); - if (!isNaN(this.options.startValue)) - this.moveTo(this.options.startValue, 0, true); - - this.previousHandle = $(this.handle[0]); //set the previous handle to the first to allow clicking before selecting the handle - if(this.handle.length == 2 && this.options.range) this.createRange(); - }, - - setData: function(event, key, value) { - this.options[key] = value; - if (/min|max|steps/.test(key)) { - this.initBoundaries(); - } - }, - - initBoundaries: function() { - var element = this.element[0]; - var o = this.options; - $.extend(o, { - axis: o.axis || (element.offsetWidth < element.offsetHeight ? 'vertical' : 'horizontal'), - max: !isNaN(parseInt(o.max,10)) ? { x: parseInt(o.max, 10), y: parseInt(o.max, 10) } : ({ x: o.max && o.max.x || 100, y: o.max && o.max.y || 100 }), - min: !isNaN(parseInt(o.min,10)) ? { x: parseInt(o.min, 10), y: parseInt(o.min, 10) } : ({ x: o.min && o.min.x || 0, y: o.min && o.min.y || 0 }) - }); - //Prepare the real maxValue - o.realMax = { - x: o.max.x - o.min.x, - y: o.max.y - o.min.y - }; - //Calculate stepping based on steps - o.stepping = { - x: o.stepping && o.stepping.x || parseInt(o.stepping, 10) || (o.steps ? o.realMax.x/(o.steps.x || parseInt(o.steps, 10) || o.realMax.x) : 0), - y: o.stepping && o.stepping.y || parseInt(o.stepping, 10) || (o.steps ? o.realMax.y/(o.steps.y || parseInt(o.steps, 10) || o.realMax.y) : 0) - }; - }, - plugins: {}, - createRange: function() { - this.rangeElement = $('<div></div>') - .addClass('ui-slider-range') - .css({ position: 'absolute' }) - .appendTo(this.element); - this.updateRange(); - }, - updateRange: function() { - var prop = this.options.axis == "vertical" ? "top" : "left"; - var size = this.options.axis == "vertical" ? "height" : "width"; - this.rangeElement.css(prop, parseInt($(this.handle[0]).css(prop),10) + this.handleSize(0, this.options.axis == "vertical" ? 2 : 1)/2); - this.rangeElement.css(size, parseInt($(this.handle[1]).css(prop),10) - parseInt($(this.handle[0]).css(prop),10)); - }, - getRange: function() { - return this.rangeElement ? this.convertValue(parseInt(this.rangeElement.css(this.options.axis == "vertical" ? "height" : "width"),10)) : null; - }, - ui: function(e) { - return { - instance: this, - options: this.options, - handle: this.currentHandle, - value: this.options.axis != "both" || !this.options.axis ? Math.round(this.value(null,this.options.axis == "vertical" ? 2 : 1)) : { - x: Math.round(this.value(null,1)), - y: Math.round(this.value(null,2)) - }, - range: this.getRange() - }; - }, - propagate: function(n,e) { - $.ui.plugin.call(this, n, [e, this.ui()]); - this.element.triggerHandler(n == "slide" ? n : "slide"+n, [e, this.ui()], this.options[n]); - }, - destroy: function() { - this.element - .removeClass("ui-slider ui-slider-disabled") - .removeData("slider") - .unbind(".slider"); - this.handle.mouse("destroy"); - this.generated && this.generated.remove(); - }, - enable: function() { - this.element.removeClass("ui-slider-disabled"); - this.disabled = false; - }, - disable: function() { - this.element.addClass("ui-slider-disabled"); - this.disabled = true; - }, - focus: function(handle,hard) { - this.currentHandle = $(handle).addClass('ui-slider-handle-active'); - if (hard) - this.currentHandle.parent()[0].focus(); - }, - blur: function(handle) { - $(handle).removeClass('ui-slider-handle-active'); - if(this.currentHandle && this.currentHandle[0] == handle) { this.previousHandle = this.currentHandle; this.currentHandle = null; }; - }, - value: function(handle, axis) { - if(this.handle.length == 1) this.currentHandle = this.handle; - if(!axis) axis = this.options.axis == "vertical" ? 2 : 1; - - var value = ((parseInt($(handle != undefined && handle !== null ? this.handle[handle] || handle : this.currentHandle).css(axis == 1 ? "left" : "top"),10) / (this.actualSize[axis == 1 ? "width" : "height"] - this.handleSize(handle,axis))) * this.options.realMax[axis == 1 ? "x" : "y"]) + this.options.min[axis == 1 ? "x" : "y"]; - - var o = this.options; - if (o.stepping[axis == 1 ? "x" : "y"]) { - value = Math.round(value / o.stepping[axis == 1 ? "x" : "y"]) * o.stepping[axis == 1 ? "x" : "y"]; - } - return value; - }, - convertValue: function(value,axis) { - if(!axis) axis = this.options.axis == "vertical" ? 2 : 1; - return this.options.min[axis == 1 ? "x" : "y"] + (value / (this.actualSize[axis == 1 ? "width" : "height"] - this.handleSize(null,axis))) * this.options.realMax[axis == 1 ? "x" : "y"]; - }, - translateValue: function(value,axis) { - if(!axis) axis = this.options.axis == "vertical" ? 2 : 1; - return ((value - this.options.min[axis == 1 ? "x" : "y"]) / this.options.realMax[axis == 1 ? "x" : "y"]) * (this.actualSize[axis == 1 ? "width" : "height"] - this.handleSize(null,axis)); - }, - handleSize: function(handle,axis) { - if(!axis) axis = this.options.axis == "vertical" ? 2 : 1; - return $(handle != undefined && handle !== null ? this.handle[handle] : this.currentHandle)[0][axis == 1 ? "offsetWidth" : "offsetHeight"]; - }, - click: function(e) { - // This method is only used if: - // - The user didn't click a handle - // - The Slider is not disabled - // - There is a current, or previous selected handle (otherwise we wouldn't know which one to move) - - var pointer = [e.pageX,e.pageY]; - - var clickedHandle = false; - this.handle.each(function() { - if(this == e.target) - clickedHandle = true; - }); - if (clickedHandle || this.disabled || !(this.currentHandle || this.previousHandle)) - return; - - // If a previous handle was focussed, focus it again - if (!this.currentHandle && this.previousHandle) - this.focus(this.previousHandle, true); - - // Move focussed handle to the clicked position - this.offset = this.element.offset(); - - // propagate only for distance > 0, otherwise propagation is done my drag - this.moveTo({ - y: this.convertValue(e.pageY - this.offset.top - this.currentHandle.outerHeight()/2), - x: this.convertValue(e.pageX - this.offset.left - this.currentHandle.outerWidth()/2) - }, null, !this.options.distance); - }, - start: function(e, handle) { - - var o = this.options; - - // This is a especially ugly fix for strange blur events happening on mousemove events - if (!this.currentHandle) - this.focus(this.previousHandle, true); - - this.offset = this.element.offset(); - this.handleOffset = this.currentHandle.offset(); - this.clickOffset = { top: e.pageY - this.handleOffset.top, left: e.pageX - this.handleOffset.left }; - this.firstValue = this.value(); - - this.propagate('start', e); - return false; - - }, - stop: function(e) { - this.propagate('stop', e); - if (this.firstValue != this.value()) - this.propagate('change', e); - this.focus(this.currentHandle, true); //This is a especially ugly fix for strange blur events happening on mousemove events - return false; - }, - - oneStep: function(axis) { - if(!axis) axis = this.options.axis == "vertical" ? 2 : 1; - return this.options.stepping[axis == 1 ? "x" : "y"] ? this.options.stepping[axis == 1 ? "x" : "y"] : (this.options.realMax[axis == 1 ? "x" : "y"] / this.actualSize[axis == 1 ? "width" : "height"]) * 5; - }, - - translateRange: function(value,axis) { - if (this.rangeElement) { - if (this.currentHandle[0] == this.handle[0] && value >= this.translateValue(this.value(1),axis)) - value = this.translateValue(this.value(1,axis) - this.oneStep(axis), axis); - if (this.currentHandle[0] == this.handle[1] && value <= this.translateValue(this.value(0),axis)) - value = this.translateValue(this.value(0,axis) + this.oneStep(axis)); - } - if (this.options.handles) { - var handle = this.options.handles[this.handleIndex()]; - if (value < this.translateValue(handle.min,axis)) { - value = this.translateValue(handle.min,axis); - } else if (value > this.translateValue(handle.max,axis)) { - value = this.translateValue(handle.max,axis); - } - } - return value; - }, - - handleIndex: function() { - return this.handle.index(this.currentHandle[0]) - }, - - translateLimits: function(value,axis) { - if(!axis) axis = this.options.axis == "vertical" ? 2 : 1; - if (value >= this.actualSize[axis == 1 ? "width" : "height"] - this.handleSize(null,axis)) - value = this.actualSize[axis == 1 ? "width" : "height"] - this.handleSize(null,axis); - if (value <= 0) - value = 0; - return value; - }, - - drag: function(e, handle) { - - var o = this.options; - var position = { top: e.pageY - this.offset.top - this.clickOffset.top, left: e.pageX - this.offset.left - this.clickOffset.left}; - if(!this.currentHandle) this.focus(this.previousHandle, true); //This is a especially ugly fix for strange blur events happening on mousemove events - - position.left = this.translateLimits(position.left,1); - position.top = this.translateLimits(position.top,2); - - if (o.stepping.x) { - var value = this.convertValue(position.left,1); - value = Math.round(value / o.stepping.x) * o.stepping.x; - position.left = this.translateValue(value, 1); - } - if (o.stepping.y) { - var value = this.convertValue(position.top,2); - value = Math.round(value / o.stepping.y) * o.stepping.y; - position.top = this.translateValue(value, 2); - } - - position.left = this.translateRange(position.left, 1); - position.top = this.translateRange(position.top, 2); - - if(o.axis != "vertical") this.currentHandle.css({ left: position.left }); - if(o.axis != "horizontal") this.currentHandle.css({ top: position.top }); - - if (this.rangeElement) - this.updateRange(); - this.propagate('slide', e); - return false; - }, - - moveTo: function(value, handle, noPropagation) { - var o = this.options; - if (handle == undefined && !this.currentHandle && this.handle.length != 1) - return false; //If no handle has been passed, no current handle is available and we have multiple handles, return false - if (handle == undefined && !this.currentHandle) - handle = 0; //If only one handle is available, use it - if (handle != undefined) - this.currentHandle = this.previousHandle = $(this.handle[handle] || handle); - - - - if(value.x !== undefined && value.y !== undefined) { - var x = value.x; - var y = value.y; - } else { - var x = value, y = value; - } - - if(x && x.constructor != Number) { - var me = /^-=/.test(x), pe = /^+=/.test(x); - if (me) { - x = this.value(null,1) - parseInt(x.replace('-=', ''), 10); - } else if (pe) { - x = this.value(null,1) + parseInt(x.replace('+=', ''), 10); - } - } - - if(y && y.constructor != Number) { - var me = /^-=/.test(y), pe = /^+=/.test(y); - if (me) { - y = this.value(null,2) - parseInt(y.replace('-=', ''), 10); - } else if (pe) { - y = this.value(null,2) + parseInt(y.replace('+=', ''), 10); - } - } - - if(o.axis != "vertical" && x) { - if(o.stepping.x) x = Math.round(x / o.stepping.x) * o.stepping.x; - x = this.translateValue(x, 1); - x = this.translateLimits(x, 1); - x = this.translateRange(x, 1); - this.currentHandle.css({ left: x }); - } - - if(o.axis != "horizontal" && y) { - if(o.stepping.y) y = Math.round(y / o.stepping.y) * o.stepping.y; - y = this.translateValue(y, 2); - y = this.translateLimits(y, 2); - y = this.translateRange(y, 2); - this.currentHandle.css({ top: y }); - } - - if (this.rangeElement) - this.updateRange(); - - if (!noPropagation) { - this.propagate('start', null); - this.propagate('stop', null); - this.propagate('change', null); - this.propagate("slide", null); - } - } - }); - - $.ui.slider.getter = "value"; - - $.ui.slider.defaults = { - handle: ".ui-slider-handle", - distance: 1 - }; - -})(jQuery);
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jason Guiditta jguiditt@redhat.com
We have these in compressed form, no real need for these copies in src control.
src/public/javascripts/ui.core.js | 237 --------------------- src/public/javascripts/ui.slider.js | 386 -----------------------
ACK
Cheers, Mark.
From: Jason Guiditta jguiditt@redhat.com
--- src/public/javascripts/jquery.cookie.js | 92 --- src/public/javascripts/jquery.flash.js | 288 --------- src/public/javascripts/jquery.html5form.js | 259 -------- src/public/javascripts/jquery.loadmask.min.js | 10 - src/public/javascripts/jquery.timers.js | 142 ----- src/public/javascripts/modernizr-1.5.js | 807 ------------------------- 6 files changed, 0 insertions(+), 1598 deletions(-) delete mode 100644 src/public/javascripts/jquery.cookie.js delete mode 100644 src/public/javascripts/jquery.flash.js delete mode 100644 src/public/javascripts/jquery.html5form.js delete mode 100644 src/public/javascripts/jquery.loadmask.min.js delete mode 100644 src/public/javascripts/jquery.timers.js delete mode 100644 src/public/javascripts/modernizr-1.5.js
diff --git a/src/public/javascripts/jquery.cookie.js b/src/public/javascripts/jquery.cookie.js deleted file mode 100644 index 8e8e1d9..0000000 --- a/src/public/javascripts/jquery.cookie.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Cookie plugin - * - * Copyright (c) 2006 Klaus Hartl (stilbuero.de) - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - */ - -/** - * Create a cookie with the given name and value and other optional parameters. - * - * @example $.cookie('the_cookie', 'the_value'); - * @desc Set the value of a cookie. - * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true}); - * @desc Create a cookie with all available options. - * @example $.cookie('the_cookie', 'the_value'); - * @desc Create a session cookie. - * @example $.cookie('the_cookie', null); - * @desc Delete a cookie by passing null as value. - * - * @param String name The name of the cookie. - * @param String value The value of the cookie. - * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. - * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. - * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. - * If set to null or omitted, the cookie will be a session cookie and will not be retained - * when the the browser exits. - * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). - * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). - * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will - * require a secure protocol (like HTTPS). - * @type undefined - * - * @name $.cookie - * @cat Plugins/Cookie - * @author Klaus Hartl/klaus.hartl@stilbuero.de - */ - -/** - * Get the value of a cookie with the given name. - * - * @example $.cookie('the_cookie'); - * @desc Get the value of a cookie. - * - * @param String name The name of the cookie. - * @return The value of the cookie. - * @type String - * - * @name $.cookie - * @cat Plugins/Cookie - * @author Klaus Hartl/klaus.hartl@stilbuero.de - */ -jQuery.cookie = function(name, value, options) { - if (typeof value != 'undefined') { // name and value given, set cookie - options = options || {}; - if (value === null) { - value = ''; - options.expires = -1; - } - var expires = ''; - if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { - var date; - if (typeof options.expires == 'number') { - date = new Date(); - date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); - } else { - date = options.expires; - } - expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE - } - var path = options.path ? '; path=' + options.path : ''; - var domain = options.domain ? '; domain=' + options.domain : ''; - var secure = options.secure ? '; secure' : ''; - document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); - } else { // only name given, get cookie - var cookieValue = null; - if (document.cookie && document.cookie != '') { - var cookies = document.cookie.split(';'); - for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) == (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; - } -}; \ No newline at end of file diff --git a/src/public/javascripts/jquery.flash.js b/src/public/javascripts/jquery.flash.js deleted file mode 100644 index 2608834..0000000 --- a/src/public/javascripts/jquery.flash.js +++ /dev/null @@ -1,288 +0,0 @@ -/** - * Flash (http://jquery.lukelutman.com/plugins/flash) - * A jQuery plugin for embedding Flash movies. - * - * Version 1.0 - * November 9th, 2006 - * - * Copyright (c) 2006 Luke Lutman (http://www.lukelutman.com) - * Dual licensed under the MIT and GPL licenses. - * http://www.opensource.org/licenses/mit-license.php - * http://www.opensource.org/licenses/gpl-license.php - * - * Inspired by: - * SWFObject (http://blog.deconcept.com/swfobject/) - * UFO (http://www.bobbyvandersluis.com/ufo/) - * sIFR (http://www.mikeindustries.com/sifr/) - * - * IMPORTANT: - * The packed version of jQuery breaks ActiveX control - * activation in Internet Explorer. Use JSMin to minifiy - * jQuery (see: http://jquery.lukelutman.com/plugins/flash#activex). - * - **/ -;(function(){ - -var $$; - -/** - * - * @desc Replace matching elements with a flash movie. - * @author Luke Lutman - * @version 1.0.1 - * - * @name flash - * @param Hash htmlOptions Options for the embed/object tag. - * @param Hash pluginOptions Options for detecting/updating the Flash plugin (optional). - * @param Function replace Custom block called for each matched element if flash is installed (optional). - * @param Function update Custom block called for each matched if flash isn't installed (optional). - * @type jQuery - * - * @cat plugins/flash - * - * @example $('#hello').flash({ src: 'hello.swf' }); - * @desc Embed a Flash movie. - * - * @example $('#hello').flash({ src: 'hello.swf' }, { version: 8 }); - * @desc Embed a Flash 8 movie. - * - * @example $('#hello').flash({ src: 'hello.swf' }, { expressInstall: true }); - * @desc Embed a Flash movie using Express Install if flash isn't installed. - * - * @example $('#hello').flash({ src: 'hello.swf' }, { update: false }); - * @desc Embed a Flash movie, don't show an update message if Flash isn't installed. - * -**/ -$$ = jQuery.fn.flash = function(htmlOptions, pluginOptions, replace, update) { - - // Set the default block. - var block = replace || $$.replace; - - // Merge the default and passed plugin options. - pluginOptions = $$.copy($$.pluginOptions, pluginOptions); - - // Detect Flash. - if(!$$.hasFlash(pluginOptions.version)) { - // Use Express Install (if specified and Flash plugin 6,0,65 or higher is installed). - if(pluginOptions.expressInstall && $$.hasFlash(6,0,65)) { - // Add the necessary flashvars (merged later). - var expressInstallOptions = { - flashvars: { - MMredirectURL: location, - MMplayerType: 'PlugIn', - MMdoctitle: jQuery('title').text() - } - }; - // Ask the user to update (if specified). - } else if (pluginOptions.update) { - // Change the block to insert the update message instead of the flash movie. - block = update || $$.update; - // Fail - } else { - // The required version of flash isn't installed. - // Express Install is turned off, or flash 6,0,65 isn't installed. - // Update is turned off. - // Return without doing anything. - return this; - } - } - - // Merge the default, express install and passed html options. - htmlOptions = $$.copy($$.htmlOptions, expressInstallOptions, htmlOptions); - - // Invoke $block (with a copy of the merged html options) for each element. - return this.each(function(){ - block.call(this, $$.copy(htmlOptions)); - }); - -}; -/** - * - * @name flash.copy - * @desc Copy an arbitrary number of objects into a new object. - * @type Object - * - * @example $$.copy({ foo: 1 }, { bar: 2 }); - * @result { foo: 1, bar: 2 }; - * -**/ -$$.copy = function() { - var options = {}, flashvars = {}; - for(var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - if(arg == undefined) continue; - jQuery.extend(options, arg); - // don't clobber one flash vars object with another - // merge them instead - if(arg.flashvars == undefined) continue; - jQuery.extend(flashvars, arg.flashvars); - } - options.flashvars = flashvars; - return options; -}; -/* - * @name flash.hasFlash - * @desc Check if a specific version of the Flash plugin is installed - * @type Boolean - * -**/ -$$.hasFlash = function() { - // look for a flag in the query string to bypass flash detection - if(/hasFlash=true/.test(location)) return true; - if(/hasFlash=false/.test(location)) return false; - var pv = $$.hasFlash.playerVersion().match(/\d+/g); - var rv = String([arguments[0], arguments[1], arguments[2]]).match(/\d+/g) || String($$.pluginOptions.version).match(/\d+/g); - for(var i = 0; i < 3; i++) { - pv[i] = parseInt(pv[i] || 0); - rv[i] = parseInt(rv[i] || 0); - // player is less than required - if(pv[i] < rv[i]) return false; - // player is greater than required - if(pv[i] > rv[i]) return true; - } - // major version, minor version and revision match exactly - return true; -}; -/** - * - * @name flash.hasFlash.playerVersion - * @desc Get the version of the installed Flash plugin. - * @type String - * -**/ -$$.hasFlash.playerVersion = function() { - // ie - try { - try { - // avoid fp6 minor version lookup issues - // see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-... - var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6'); - try { axo.AllowScriptAccess = 'always'; } - catch(e) { return '6,0,0'; } - } catch(e) {} - return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1]; - // other browsers - } catch(e) { - try { - if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){ - return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1]; - } - } catch(e) {} - } - return '0,0,0'; -}; -/** - * - * @name flash.htmlOptions - * @desc The default set of options for the object or embed tag. - * -**/ -$$.htmlOptions = { - height: 240, - flashvars: {}, - pluginspage: 'http://www.adobe.com/go/getflashplayer', - src: '#', - type: 'application/x-shockwave-flash', - width: 320 -}; -/** - * - * @name flash.pluginOptions - * @desc The default set of options for checking/updating the flash Plugin. - * -**/ -$$.pluginOptions = { - expressInstall: false, - update: true, - version: '6.0.65' -}; -/** - * - * @name flash.replace - * @desc The default method for replacing an element with a Flash movie. - * -**/ -$$.replace = function(htmlOptions) { - this.innerHTML = '<div class="alt">'+this.innerHTML+'</div>'; - jQuery(this) - .addClass('flash-replaced') - .prepend($$.transform(htmlOptions)); -}; -/** - * - * @name flash.update - * @desc The default method for replacing an element with an update message. - * -**/ -$$.update = function(htmlOptions) { - var url = String(location).split('?'); - url.splice(1,0,'?hasFlash=true&'); - url = url.join(''); - var msg = '<p>This content requires the Flash Player. <a href="http://www.adobe.com/go/getflashplayer">Download Flash Player</a>. Already have Flash Player? <a href="'+url+'">Click here.</a></p>'; - this.innerHTML = '<span class="alt">'+this.innerHTML+'</span>'; - jQuery(this) - .addClass('flash-update') - .prepend(msg); -}; -/** - * - * @desc Convert a hash of html options to a string of attributes, using Function.apply(). - * @example toAttributeString.apply(htmlOptions) - * @result foo="bar" foo="bar" - * -**/ -function toAttributeString() { - var s = ''; - for(var key in this) - if(typeof this[key] != 'function') - s += key+'="'+this[key]+'" '; - return s; -}; -/** - * - * @desc Convert a hash of flashvars to a url-encoded string, using Function.apply(). - * @example toFlashvarsString.apply(flashvarsObject) - * @result foo=bar&foo=bar - * -**/ -function toFlashvarsString() { - var s = ''; - for(var key in this) - if(typeof this[key] != 'function') - s += key+'='+encodeURIComponent(this[key])+'&'; - return s.replace(/&$/, ''); -}; -/** - * - * @name flash.transform - * @desc Transform a set of html options into an embed tag. - * @type String - * - * @example $$.transform(htmlOptions) - * @result <embed src="foo.swf" ... /> - * - * Note: The embed tag is NOT standards-compliant, but it - * works in all current browsers. flash.transform can be - * overwritten with a custom function to generate more - * standards-compliant markup. - * -**/ -$$.transform = function(htmlOptions) { - htmlOptions.toString = toAttributeString; - if(htmlOptions.flashvars) htmlOptions.flashvars.toString = toFlashvarsString; - return '<embed ' + String(htmlOptions) + '/>'; -}; - -/** - * - * Flash Player 9 Fix (http://blog.deconcept.com/2006/07/28/swfobject-143-released/) - * -**/ -if (window.attachEvent) { - window.attachEvent("onbeforeunload", function(){ - __flash_unloadHandler = function() {}; - __flash_savedUnloadHandler = function() {}; - }); -} - -})(); \ No newline at end of file diff --git a/src/public/javascripts/jquery.html5form.js b/src/public/javascripts/jquery.html5form.js deleted file mode 100644 index 9b54227..0000000 --- a/src/public/javascripts/jquery.html5form.js +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Html5 Form Plugin - jQuery plugin - * HTML5 form Validation form Internet Explorer & Firefox - * Version 1.1 / English - * - * written by Matias Mancini - * http://www.matiasmancini.com.ar/html5form_en.php - * - * Copyright (c) 2010 Matias Mancini (http://www.matiasmancini.com.ar) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * Built for jQuery library - * http://jquery.com - * - */ -(function($){ - $.fn.html5form = function(options){ - - $(this).each(function(){ - - //default configuration properties - var defaults = { - async : true, - method : $(this).attr('method'), - responseDiv : null, - labels : 'show', - colorOn : '#000000', - colorOff : '#a1a1a1', - action : $(this).attr('action'), - messages : false, - emptyMessage : false, - emailMessage : false, - allBrowsers : false - }; - var opts = $.extend({}, defaults, options); - - //Filters latest WebKit versions only - if(!opts.allBrowsers){ - if($.browser.webkit && parseInt($.browser.version)>=533){ - return false; - } - } - - //Private properties - var form = $(this); - var required = new Array(); - var email = new Array(); - - //Setup color & placeholder function - function fillInput(input){ - input.val(input.attr('placeholder')); - input.css('color', opts.colorOff); - } - - //Label hiding (if required) - if(opts.labels=='hide'){ - $(this).find('label').hide(); - } - - //Select event handler (just colors) - $.each($('select', this), function(){ - $(this).css('color', opts.colorOff); - $(this).change(function(){ - $(this).css('color', opts.colorOn); - }); - }); - - //For each textarea & visible input excluding button, submit, radio, checkbox and select - $.each($(':input:visible:not(:button, :submit, :radio, :checkbox, select)', form), function(i) { - - //Setting color & placeholder - fillInput($(this)); - - //Make array of required inputs - if($.browser.webkit || $.browser.opera){ - if($(this).attr('required')){ - required[i]=$(this); - } - } - else{ - if($(this).attr('required')==''){ - required[i]=$(this); - } - } - - //Make array of Email inputs - $('input').filter(this).each(function(){ - if(this.getAttribute('type')=='email'){ - email[i]=$(this); - } - }); - - //FOCUS event attach - //If input value == placeholder attribute will clear the field - //If input type == url will not - //In both cases will change the color with colorOn property - $(this).bind('focus', function(ev){ - ev.preventDefault(); - if(this.value == $(this).attr('placeholder')){ - if(this.getAttribute('type')!='url'){ - $(this).attr('value', ''); - } - } - $(this).css('color', opts.colorOn); - }); - - //BLUR event attach - //If input value == empty calls fillInput fn - //if input type == url and value == placeholder attribute calls fn too - $(this).bind('blur', function(ev){ - ev.preventDefault(); - if(this.value == ''){ - fillInput($(this)); - } - else{ - if((this.getAttribute('type')=='url') && ($(this).val()==$(this).attr('placeholder'))){ - fillInput($(this)); - } - } - }); - - //Limits content typing to TEXTAREA type fields according to attribute maxlength - $('textarea').filter(this).each(function(){ - if($(this).attr('maxlength')>0){ - $(this).keypress(function(ev){ - var cc = ev.charCode || ev.keyCode; - if(cc == 37 || cc == 39) { - return true; - } - if(cc == 8 || cc == 46) { - return true; - } - if(this.value.length >= $(this).attr('maxlength')){ - return false; - } - else{ - return true; - } - }); - } - }); - }); - $.each($(':submit', this), function() { - $(this).bind('click', function(ev){ - - var emptyInput=null; - var emailError=null; - var input = $(':input:visible:not(:button, :submit, :radio, :checkbox, select)', form); - - //Search for empty fields & value same as placeholder - //returns first input founded - //Add messages for English, Spanish and Italian Messages - $(required).each(function(key, value) { - if(value==undefined){ - return true; - } - if(($(this).val()==$(this).attr('placeholder')) || ($(this).val()=='')){ - emptyInput=$(this); - if(opts.emptyMessage){ - //Customized empty message - $(opts.responseDiv).html('<p>'+opts.emptyMessage+'</p>'); - } - else if(opts.messages=='es'){ - //Spanish empty message - $(opts.responseDiv).html('<p>El campo '+$(this).attr('title')+' es requerido.</p>'); - } - else if(opts.messages=='en'){ - //English empty message - $(opts.responseDiv).html('<p>The '+$(this).attr('title')+' field is required.</p>'); - } - else if(opts.messages=='it'){ - //Italian empty message - $(opts.responseDiv).html('<p>Il campo '+$(this).attr('title')+' é richiesto.</p>'); - } - return false; - } - return emptyInput; - }); - - //check email type inputs with regular expression - //return first input founded - $(email).each(function(key, value) { - if(value==undefined){ - return true; - } - if($(this).val().search(/[\w-.]{3,}@([\w-]{2,}.)*([\w-]{2,}.)[\w-]{2,4}/i)){ - emailError=$(this); - return false; - } - return emailError; - }); - - //Submit form ONLY if emptyInput & emailError are null - //if async property is set to false, skip ajax - if(!emptyInput && !emailError){ - - //Clear all empty value fields before Submit - $(input).each(function(){ - if($(this).val()==$(this).attr('placeholder')){ - $(this).val(''); - } - }); - //Submit data by Ajax - if(opts.async){ - var formData=$(form).serialize(); - $.ajax({ - url : opts.action, - type : opts.method, - data : formData, - success : function(data){ - if(opts.responseDiv){ - $(opts.responseDiv).html(data); - } - //Reset form - $(input).val(''); - $.each(form[0], function(){ - fillInput($(this).not(':hidden, :button, :submit, :radio, :checkbox, select')); - $('select', form).each(function(){ - $(this).css('color', opts.colorOff); - $(this).children('option:eq(0)').attr('selected', 'selected'); - }); - $(':radio, :checkbox', form).removeAttr('checked'); - }); - } - }); - } - else{ - $(form).submit(); - } - }else{ - if(emptyInput){ - $(emptyInput).focus().select(); - } - else if(emailError){ - //Customized email error messages (Spanish, English, Italian) - if(opts.emailMessage){ - $(opts.responseDiv).html('<p>'+opts.emailMessage+'</p>'); - } - else if(opts.messages=='es'){ - $(opts.responseDiv).html('<p>Ingrese una dirección de correo válida por favor.</p>'); - } - else if(opts.messages=='en'){ - $(opts.responseDiv).html('<p>Please type a valid email address.</p>'); - } - else if(opts.messages=='it'){ - $(opts.responseDiv).html("<p>L'indirizzo e-mail non é valido.</p>"); - } - $(emailError).select(); - }else{ - alert('Unknown Error'); - } - } - return false; - }); - }); - }); - } -})(jQuery); diff --git a/src/public/javascripts/jquery.loadmask.min.js b/src/public/javascripts/jquery.loadmask.min.js deleted file mode 100644 index 8581728..0000000 --- a/src/public/javascripts/jquery.loadmask.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) 2009 Sergiy Kovalchuk (serg472@gmail.com) - * - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * Following code is based on Element.mask() implementation from ExtJS framework (http://extjs.com/) - * - */ -(function(a){a.fn.mask=function(c,b){a(this).each(function(){if(b!==undefined&&b>0){var d=a(this);d.data("_mask_timeout",setTimeout(function(){a.maskElement(d,c)},b))}else{a.maskElement(a(this),c)}})};a.fn.unmask=function(){a(this).each(function(){a.unmaskElement(a(this))})};a.fn.isMasked=function(){return this.hasClass("masked")};a.maskElement=function(d,c){if(d.data("_mask_timeout")!==undefined){clearTimeout(d.data("_mask_timeout"));d.removeData("_mask_timeout")}if(d.isMasked()){a.unmaskElement(d)}if(d.css("position")=="static"){d.addClass("masked-relative")}d.addClass("masked");var e=a('<div class="loadmask"></div>');if(navigator.userAgent.toLowerCase().indexOf("msie")>-1){e.height(d.height()+parseInt(d.css("padding-top"))+parseInt(d.css("padding-bottom")));e.width(d.width()+parseInt(d.css("padding-left"))+parseInt(d.css("padding-right")))}if(navigator.userAgent.toLowerCase().indexOf("msie 6")>-1){d.find("select").addClass("masked-hidden")}d.append(e);if(c!==undefined){v! ar b=a('<div class="loadmask-msg" style="display:none;"></div>');b.append("<div>"+c+"</div>");d.append(b);b.css("top",Math.round(d.height()/2-(b.height()-parseInt(b.css("padding-top"))-parseInt(b.css("padding-bottom")))/2)+"px");b.css("left",Math.round(d.width()/2-(b.width()-parseInt(b.css("padding-left"))-parseInt(b.css("padding-right")))/2)+"px");b.show()}};a.unmaskElement=function(b){if(b.data("_mask_timeout")!==undefined){clearTimeout(b.data("_mask_timeout"));b.removeData("_mask_timeout")}b.find(".loadmask-msg,.loadmask").remove();b.removeClass("masked");b.removeClass("masked-relative");b.find("select").removeClass("masked-hidden")}})(jQuery); diff --git a/src/public/javascripts/jquery.timers.js b/src/public/javascripts/jquery.timers.js deleted file mode 100644 index 406de7e..0000000 --- a/src/public/javascripts/jquery.timers.js +++ /dev/null @@ -1,142 +0,0 @@ -jQuery.fn.extend({ - everyTime: function(interval, label, fn, times, belay) { - return this.each(function() { - jQuery.timer.add(this, interval, label, fn, times, belay); - }); - }, - oneTime: function(interval, label, fn) { - return this.each(function() { - jQuery.timer.add(this, interval, label, fn, 1); - }); - }, - stopTime: function(label, fn) { - return this.each(function() { - jQuery.timer.remove(this, label, fn); - }); - } -}); - -jQuery.extend({ - timer: { - guid: 1, - global: {}, - regex: /^([0-9]+)\s*(.*s)?$/, - powers: { - // Yeah this is major overkill... - 'ms': 1, - 'cs': 10, - 'ds': 100, - 's': 1000, - 'das': 10000, - 'hs': 100000, - 'ks': 1000000 - }, - timeParse: function(value) { - if (value == undefined || value == null) - return null; - var result = this.regex.exec(jQuery.trim(value.toString())); - if (result[2]) { - var num = parseInt(result[1], 10); - var mult = this.powers[result[2]] || 1; - return num * mult; - } else { - return value; - } - }, - add: function(element, interval, label, fn, times, belay) { - var counter = 0; - - if (jQuery.isFunction(label)) { - if (!times) - times = fn; - fn = label; - label = interval; - } - - interval = jQuery.timer.timeParse(interval); - - if (typeof interval != 'number' || isNaN(interval) || interval <= 0) - return; - - if (times && times.constructor != Number) { - belay = !!times; - times = 0; - } - - times = times || 0; - belay = belay || false; - - if (!element.$timers) - element.$timers = {}; - - if (!element.$timers[label]) - element.$timers[label] = {}; - - fn.$timerID = fn.$timerID || this.guid++; - - var handler = function() { - if (belay && this.inProgress) - return; - this.inProgress = true; - if ((++counter > times && times !== 0) || fn.call(element, counter) === false) - jQuery.timer.remove(element, label, fn); - this.inProgress = false; - }; - - handler.$timerID = fn.$timerID; - - if (!element.$timers[label][fn.$timerID]) - element.$timers[label][fn.$timerID] = window.setInterval(handler,interval); - - if ( !this.global[label] ) - this.global[label] = []; - this.global[label].push( element ); - - }, - remove: function(element, label, fn) { - var timers = element.$timers, ret; - - if ( timers ) { - - if (!label) { - for ( label in timers ) - this.remove(element, label, fn); - } else if ( timers[label] ) { - if ( fn ) { - if ( fn.$timerID ) { - window.clearInterval(timers[label][fn.$timerID]); - delete timers[label][fn.$timerID]; - } - } else { - for ( var fn in timers[label] ) { - window.clearInterval(timers[label][fn]); - delete timers[label][fn]; - } - } - - for ( ret in timers[label] ) break; - if ( !ret ) { - ret = null; - delete timers[label]; - } - } - - for ( ret in timers ) break; - if ( !ret ) - element.$timers = null; - } - } - } -}); - -if (jQuery.browser.msie) - jQuery(window).one("unload", function() { - var global = jQuery.timer.global; - for ( var label in global ) { - var els = global[label], i = els.length; - while ( --i ) - jQuery.timer.remove(els[i], label); - } - }); - - diff --git a/src/public/javascripts/modernizr-1.5.js b/src/public/javascripts/modernizr-1.5.js deleted file mode 100644 index e41ebbc..0000000 --- a/src/public/javascripts/modernizr-1.5.js +++ /dev/null @@ -1,807 +0,0 @@ -/*! - * Modernizr JavaScript library 1.5 - * http://www.modernizr.com/ - * - * Copyright (c) 2009-2010 Faruk Ates - http://farukat.es/ - * Dual-licensed under the BSD and MIT licenses. - * http://www.modernizr.com/license/ - * - * Featuring major contributions by - * Paul Irish - http://paulirish.com - */ - -/* - * Modernizr is a script that will detect native CSS3 and HTML5 features - * available in the current UA and provide an object containing all - * features with a true/false value, depending on whether the UA has - * native support for it or not. - * - * In addition to that, Modernizr will add classes to the <html> - * element of the page, one for each cutting-edge feature. If the UA - * supports it, a class like "cssgradients" will be added. If not, - * the class name will be "no-cssgradients". This allows for simple - * if-conditionals in CSS styling, making it easily to have fine - * control over the look and feel of your website. - * - * @author Faruk Ates - * @copyright (c) 2009-2010 Faruk Ates. - * - * @contributor Paul Irish - * @contributor Ben Alman - */ - -window.Modernizr = (function(window,doc,undefined){ - - var version = '1.5', - - ret = {}, - - /** - * enableHTML5 is a private property for advanced use only. If enabled, - * it will make Modernizr.init() run through a brief while() loop in - * which it will create all HTML5 elements in the DOM to allow for - * styling them in Internet Explorer, which does not recognize any - * non-HTML4 elements unless created in the DOM this way. - * - * enableHTML5 is ON by default. - */ - enableHTML5 = true, - - - /** - * fontfaceCheckDelay is the ms delay before the @font-face test is - * checked a second time. This is neccessary because both Gecko and - * WebKit do not load data: URI font data synchronously. - * https://bugzilla.mozilla.org/show_bug.cgi?id=512566 - * The check will be done again at fontfaceCheckDelay*2 and then - * a fourth time at window's load event. - * If you need to query for @font-face support, send a callback to: - * Modernizr._fontfaceready(fn); - * The callback is passed the boolean value of Modernizr.fontface - */ - fontfaceCheckDelay = 75, - - - docElement = doc.documentElement, - - /** - * Create our "modernizr" element that we do most feature tests on. - */ - mod = 'modernizr', - m = doc.createElement( mod ), - m_style = m.style, - - /** - * Create the input element for various Web Forms feature tests. - */ - f = doc.createElement( 'input' ), - - // Reused strings, stored here to allow better minification - - canvas = 'canvas', - canvastext = 'canvastext', - rgba = 'rgba', - hsla = 'hsla', - multiplebgs = 'multiplebgs', - backgroundsize = 'backgroundsize', - borderimage = 'borderimage', - borderradius = 'borderradius', - boxshadow = 'boxshadow', - opacity = 'opacity', - cssanimations = 'cssanimations', - csscolumns = 'csscolumns', - cssgradients = 'cssgradients', - cssreflections = 'cssreflections', - csstransforms = 'csstransforms', - csstransforms3d = 'csstransforms3d', - csstransitions = 'csstransitions', - fontface = 'fontface', - geolocation = 'geolocation', - video = 'video', - audio = 'audio', - input = 'input', - inputtypes = input + 'types', - // inputtypes is an object of its own containing individual tests for - // various new input types, such as search, range, datetime, etc. - - svg = 'svg', - smil = 'smil', - svgclippaths = svg+'clippaths', - - background = 'background', - backgroundColor = background + 'Color', - canPlayType = 'canPlayType', - - // FF gets really angry if you name local variables as these, but camelCased. - localstorage = 'localStorage', - sessionstorage = 'sessionStorage', - applicationcache = 'applicationCache', - - webWorkers = 'webworkers', - hashchange = 'hashchange', - crosswindowmessaging = 'crosswindowmessaging', - historymanagement = 'historymanagement', - draganddrop = 'draganddrop', - websqldatabase = 'websqldatabase', - indexedDB = 'indexedDB', - websockets = 'websockets', - smile = ':)', - - // IE7 gets mad if you name a local variable `toString` - tostring = Object.prototype.toString, - - // list of property values to set for css tests. see ticket #21 - prefixes = ' -o- -moz- -ms- -webkit- -khtml- '.split(' '), - - tests = {}, - inputs = {}, - attrs = {}, - - classes = [], - - /** - * isEventSupported determines if a given element supports the given event - * function from http://yura.thinkweb2.com/isEventSupported/ - */ - isEventSupported = (function(){ - - var TAGNAMES = { - 'select':'input','change':'input', - 'submit':'form','reset':'form', - 'error':'img','load':'img','abort':'img' - }, - cache = { }; - - function isEventSupported(eventName, element) { - var canCache = (arguments.length == 1); - - // only return cached result when no element is given - if (canCache && cache[eventName]) { - return cache[eventName]; - } - - element = element || document.createElement(TAGNAMES[eventName] || 'div'); - eventName = 'on' + eventName; - - // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize" - // `in` "catches" those - var isSupported = (eventName in element); - - if (!isSupported && element.setAttribute) { - element.setAttribute(eventName, 'return;'); - isSupported = typeof element[eventName] == 'function'; - } - - element = null; - return canCache ? (cache[eventName] = isSupported) : isSupported; - } - - return isEventSupported; - })(); - - - var _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty; - if (typeof _hasOwnProperty !== 'undefined' && typeof _hasOwnProperty.call !== 'undefined') { - hasOwnProperty = function (object, property) { - return _hasOwnProperty.call(object, property); - }; - } - else { - hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ - return ((property in object) && typeof object.constructor.prototype[property] === 'undefined'); - }; - } - - /** - * set_css applies given styles to the Modernizr DOM node. - */ - function set_css( str ) { - m_style.cssText = str; - } - - /** - * set_css_all extrapolates all vendor-specific css strings. - */ - function set_css_all( str1, str2 ) { - return set_css(prefixes.join(str1 + ';') + ( str2 || '' )); - } - - /** - * contains returns a boolean for if substr is found within str. - */ - function contains( str, substr ) { - return (''+str).indexOf( substr ) !== -1; - } - - /** - * test_props is a generic CSS / DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - * A supported CSS property returns empty string when its not yet set. - */ - function test_props( props, callback ) { - for ( var i in props ) { - if ( m_style[ props[i] ] !== undefined && ( !callback || callback( props[i], m ) ) ) { - return true; - } - } - } - - /** - * test_props_all tests a list of DOM properties we want to check against. - * We specify literally ALL possible (known and/or likely) properties on - * the element including the non-vendor prefixed one, for forward- - * compatibility. - */ - function test_props_all( prop, callback ) { - var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1), - - // following spec is to expose vendor-specific style properties as: - // elem.style.WebkitBorderRadius - // and the following would be incorrect: - // elem.style.webkitBorderRadius - // Webkit and Mozilla are nice enough to ghost their properties in the lowercase - // version but Opera does not. - - // see more here: http://github.com/Modernizr/Modernizr/issues/issue/21 - props = [ - prop, - 'Webkit' + uc_prop, - 'Moz' + uc_prop, - 'O' + uc_prop, - 'ms' + uc_prop, - 'Khtml' + uc_prop - ]; - - return !!test_props( props, callback ); - } - - - /** - * Tests - */ - - tests[canvas] = function() { - return !!doc.createElement( canvas ).getContext; - }; - - tests[canvastext] = function() { - return !!(tests[canvas]() && typeof doc.createElement( canvas ).getContext('2d').fillText == 'function'); - }; - - /** - * The Modernizr.touch test only indicates if the browser supports - * touch events, which does not necessarily reflect a touchscreen - * device, as evidenced by tablets running Windows 7 or, alas, - * the Palm Pre / WebOS (touch) phones. - * Additionally, chrome used to lie about its support on this, but that - * has since been recitifed: http://crbug.com/36415 - * Because there is no way to reliably detect Chrome's false positive - * without UA sniffing we have removed this test from Modernizr. We - * hope to add it in after Chrome 5 has been sunsetted. - * See also http://github.com/Modernizr/Modernizr/issues#issue/84 - - tests[touch] = function() { - - return !!('ontouchstart' in window); - - }; - */ - - /** - * geolocation tests for the new Geolocation API specification. - * This test is a standards compliant-only test; for more complete - * testing, including a Google Gears fallback, please see: - * http://code.google.com/p/geo-location-javascript/ - * or view a fallback solution using google's geo API: - * http://gist.github.com/366184 - */ - tests[geolocation] = function() { - return !!navigator.geolocation; - }; - - tests[crosswindowmessaging] = function() { - return !!window.postMessage; - }; - - tests[websqldatabase] = function() { - var result = !!window.openDatabase; - if (result){ - try { - result = !!openDatabase("testdb", "1.0", "html5 test db", 200000); - } catch(err) { - result = false; - } - } - return result; - }; - - tests[indexedDB] = function(){ - return !!window[indexedDB]; - }; - - // documentMode logic from YUI to filter out IE8 Compat Mode - // which false positives. - tests[hashchange] = function() { - return isEventSupported(hashchange, window) && ( document.documentMode === undefined || document.documentMode > 7 ); - }; - - tests[historymanagement] = function() { - return !!(window.history && history.pushState); - }; - - tests[draganddrop] = function() { - return isEventSupported('drag') - && isEventSupported('dragstart') - && isEventSupported('dragenter') - && isEventSupported('dragover') - && isEventSupported('dragleave') - && isEventSupported('dragend') - && isEventSupported('drop'); - }; - - - tests[websockets] = function(){ - return ('WebSocket' in window); - }; - - - // http://css-tricks.com/rgba-browser-support/ - tests[rgba] = function() { - // Set an rgba() color and check the returned value - - set_css( background + '-color:rgba(150,255,150,.5)' ); - - return contains( m_style[backgroundColor], rgba ); - }; - - tests[hsla] = function() { - // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally - - set_css( background + '-color:hsla(120,40%,100%,.5)' ); - - return contains( m_style[backgroundColor], rgba ); - }; - - tests[multiplebgs] = function() { - // Setting multiple images AND a color on the background shorthand property - // and then querying the style.background property value for the number of - // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! - - set_css( background + ':url(//:),url(//:),red url(//:)' ); - - // If the UA supports multiple backgrounds, there should be three occurrences - // of the string "url(" in the return value for elem_style.background - - return new RegExp("(url\s*\(.*?){3}").test(m_style[background]); - }; - - - // In testing support for a given CSS property, it's legit to test: - // elem.style[styleName] !== undefined - // If the property is supported it will return an empty string, - // if unsupported it will return undefined. - // We'll take advantage of this quick test and skip setting a style - // on our modernizr element, but instead just testing undefined vs - // empty string. - // The legacy set_css_all calls will remain in the source - // (however, commented) in for clarity, yet functionally they are - // no longer needed. - - - tests[backgroundsize] = function() { - return test_props_all( background + 'Size' ); - }; - - tests[borderimage] = function() { - // set_css_all( 'border-image:url(m.png) 1 1 stretch' ); - return test_props_all( 'borderImage' ); - }; - - - // super comprehensive table about all the unique implementations of - // border-radius: http://muddledramblings.com/table-of-css3-border-radius-compliance - - tests[borderradius] = function() { - // set_css_all( 'border-radius:10px' ); - return test_props_all( 'borderRadius', '', function( prop ) { - return contains( prop, 'orderRadius' ); - }); - }; - - - tests[boxshadow] = function() { - // set_css_all( 'box-shadow:#000 1px 1px 3px' ); - return test_props_all( 'boxShadow' ); - }; - - - tests[opacity] = function() { - // Browsers that actually have CSS Opacity implemented have done so - // according to spec, which means their return values are within the - // range of [0.0,1.0] - including the leading zero. - - set_css_all( 'opacity:.5' ); - - return contains( m_style[opacity], '0.5' ); - }; - - - tests[cssanimations] = function() { - // set_css_all( 'animation:"animate" 2s ease 2', 'position:relative' ); - return test_props_all( 'animationName' ); - }; - - - tests[csscolumns] = function() { - // set_css_all( 'column-count:3' ); - return test_props_all( 'columnCount' ); - }; - - - tests[cssgradients] = function() { - /** - * For CSS Gradients syntax, please see: - * http://webkit.org/blog/175/introducing-css-gradients/ - * https://developer.mozilla.org/en/CSS/-moz-linear-gradient - * https://developer.mozilla.org/en/CSS/-moz-radial-gradient - * http://dev.w3.org/csswg/css3-images/#gradients- - */ - - var str1 = background + '-image:', - str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', - str3 = 'linear-gradient(left top,#9f9, white);'; - - set_css( - (str1 + prefixes.join(str2 + str1) + prefixes.join(str3 + str1)).slice(0,-str1.length) - ); - - return contains( m_style.backgroundImage, 'gradient' ); - }; - - - tests[cssreflections] = function() { - // set_css_all( 'box-reflect:right 1px' ); - return test_props_all( 'boxReflect' ); - }; - - - tests[csstransforms] = function() { - // set_css_all( 'transform:rotate(3deg)' ); - return !!test_props([ 'transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]); - }; - - - tests[csstransforms3d] = function() { - // set_css_all( 'perspective:500' ); - - var ret = !!test_props([ 'perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective' ]); - - // webkit has 3d transforms disabled for chrome, though - // it works fine in safari on leopard and snow leopard - // as a result, it 'recognizes' the syntax and throws a false positive - // thus we must do a more thorough check: - if (ret){ - var st = document.createElement('style'), - div = doc.createElement('div'); - - // webkit allows this media query to succeed only if the feature is enabled. - // "@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){#modernizr{height:3px}}" - st.textContent = '@media ('+prefixes.join('transform-3d),(')+'modernizr){#modernizr{height:3px}}'; - doc.getElementsByTagName('head')[0].appendChild(st); - div.id = 'modernizr'; - docElement.appendChild(div); - - ret = div.offsetHeight === 3; - - st.parentNode.removeChild(st); - div.parentNode.removeChild(div); - } - return ret; - }; - - - tests[csstransitions] = function() { - // set_css_all( 'transition:all .5s linear' ); - return test_props_all( 'transitionProperty' ); - }; - - - // @font-face detection routine created by Paul Irish - paulirish.com - // Merged into Modernizr with approval. Read more about Paul's work here: - // http://paulirish.com/2009/font-face-feature-detection/ - tests[fontface] = function(){ - - var fontret; - if (/*@cc_on@if(@_jscript_version>=5)!@end@*/0) fontret = true; - - else { - - // Create variables for dedicated @font-face test - var st = doc.createElement('style'), - spn = doc.createElement('span'), - size, isFakeBody = false, body = doc.body, - callback, isCallbackCalled; - - // The following is a font-face + glyph definition for the . character: - st.textContent = "@font-face{font-family:testfont;src:url('data:font/ttf;base64,AAEAAAAMAIAAAwBAT1MvMliohmwAAADMAAAAVmNtYXCp5qrBAAABJAAAANhjdnQgACICiAAAAfwAAAAEZ2FzcP//AAMAAAIAAAAACGdseWYv5OZoAAACCAAAANxoZWFk69bnvwAAAuQAAAA2aGhlYQUJAt8AAAMcAAAAJGhtdHgGDgC4AAADQAAAABRsb2NhAIQAwgAAA1QAAAAMbWF4cABVANgAAANgAAAAIG5hbWUgXduAAAADgAAABPVwb3N03NkzmgAACHgAAAA4AAECBAEsAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAACAAMDAAAAAAAAgAACbwAAAAoAAAAAAAAAAFBmRWQAAAAgqS8DM/8zAFwDMwDNAAAABQAAAAAAAAAAAAMAAAADAAAAHAABAAAAAABGAAMAAQAAAK4ABAAqAAAABgAEAAEAAgAuqQD//wAAAC6pAP///9ZXAwAAAAAAAAACAAAABgBoAAAAAAAvAAEAAAAAAAAAAAAAAAAAAAABAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEACoAAAAGAAQAAQACAC6pAP//AAAALqkA////1lcDAAAAAAAAAAIAAAAiAogAAAAB//8AAgACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAACAFUAAAIRAc0ADwAfAAATFRQWOwEyNj0BNCYrASIGARQGKwEiJj0BNDY7ATIWFX8aIvAiGhoi8CIaAZIoN/43KCg3/j! coAWD0JB4eJPQkHh7++EY2NkbVRjY2RgAAAAABAEH/+QCdAEEACQAANjQ2MzIWFAYjIkEeEA8fHw8QDxwWFhwWAAAAAQAAAAIAAIuYbWpfDzz1AAsEAAAAAADFn9IuAAAAAMWf0i797/8zA4gDMwAAAAgAAgAAAAAAAAABAAADM/8zAFwDx/3v/98DiAABAAAAAAAAAAAAAAAAAAAABQF2ACIAAAAAAVUAAAJmAFUA3QBBAAAAKgAqACoAWgBuAAEAAAAFAFAABwBUAAQAAgAAAAEAAQAAAEAALgADAAMAAAAQAMYAAQAAAAAAAACLAAAAAQAAAAAAAQAhAIsAAQAAAAAAAgAFAKwAAQAAAAAAAwBDALEAAQAAAAAABAAnAPQAAQAAAAAABQAKARsAAQAAAAAABgAmASUAAQAAAAAADgAaAUsAAwABBAkAAAEWAWUAAwABBAkAAQBCAnsAAwABBAkAAgAKAr0AAwABBAkAAwCGAscAAwABBAkABABOA00AAwABBAkABQAUA5sAAwABBAkABgBMA68AAwABBAkADgA0A/tDb3B5cmlnaHQgMjAwOSBieSBEYW5pZWwgSm9obnNvbi4gIFJlbGVhc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgT3BlbiBGb250IExpY2Vuc2UuIEtheWFoIExpIGdseXBocyBhcmUgcmVsZWFzZWQgdW5kZXIgdGhlIEdQTCB2ZXJzaW9uIDMuYmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhTGlnaHRiYWVjMmE5MmJmZmU1MDMyIC0gc3Vic2V0IG9mIEZvbnRGb3JnZSAyLjAgOiBKdXJhIExpZ2h0IDogMjMtMS0yMDA5YmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhIExpZ2h0VmVyc2lvbiAyIGJhZWMyYTkyYmZmZTUwMzIgLSBzdWJzZXQgb2! YgSnVyYUxpZ2h0aHR0cDovL3NjcmlwdHMuc2lsLm9yZy9PRkwAQwBvAHAAeQByAGkAZwBo AHQAIAAyADAAMAA5ACAAYgB5ACAARABhAG4AaQBlAGwAIABKAG8AaABuAHMAbwBuAC4AIAAgAFIAZQBsAGUAYQBzAGUAZAAgAHUAbgBkAGUAcgAgAHQAaABlACAAdABlAHIAbQBzACAAbwBmACAAdABoAGUAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUALgAgAEsAYQB5AGEAaAAgAEwAaQAgAGcAbAB5AHAAaABzACAAYQByAGUAIAByAGUAbABlAGEAcwBlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAEcAUABMACAAdgBlAHIAcwBpAG8AbgAgADMALgBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQBMAGkAZwBoAHQAYgBhAGUAYwAyAGEAOQAyAGIAZgBmAGUANQAwADMAMgAgAC0AIABzAHUAYgBzAGUAdAAgAG8AZgAgAEYAbwBuAHQARgBvAHIAZwBlACAAMgAuADAAIAA6ACAASgB1AHIAYQAgAEwAaQBnAGgAdAAgADoAIAAyADMALQAxAC0AMgAwADAAOQBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQAgAEwAaQBnAGgAdABWAGUAcgBzAGkAbwBuACAAMgAgAGIAYQBlAGMAMgBhADkAMgBiAGYAZgBlADUAMAAzADIAIAAtACAAcwB1AGIAcwBlAHQAIABvAGYAIABKAHUAcgBhAEwAaQBnAGgAdABoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAAAAAgAAAAAAAP+BADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQACA! QIAEQt6ZXJva2F5YWhsaQ==')}"; - doc.getElementsByTagName('head')[0].appendChild(st); - - // we don't use `serif` and we don't use `monospace` - // http://github.com/Modernizr/Modernizr/issues/closed#issue/39 - // http://neugierig.org/software/chromium/notes/2009/09/monospace-fonts-workaro... - spn.setAttribute('style','font:99px _,arial,helvetica;position:absolute;visibility:hidden'); - - if (!body){ - body = docElement.appendChild(doc.createElement(fontface)); - isFakeBody = true; - } - - // the data-uri'd font only has the . glyph; which is 3 pixels wide. - spn.innerHTML = '........'; - spn.id = 'fonttest'; - - body.appendChild(spn); - size = spn.offsetWidth*spn.offsetHeight; - spn.style.font = '99px testfont,_,arial,helvetica'; - - // needed for the CSSFontFaceRule false positives (ff3, chrome, op9) - fontret = size !== spn.offsetWidth*spn.offsetHeight; - - function delayedCheck(){ - if (!body.parentNode) return; - fontret = ret[fontface] = size !== spn.offsetWidth*spn.offsetHeight; - docElement.className = docElement.className.replace(/(no-)?fontface\b/,'') + (fontret ? ' ' : ' no-') + fontface; - } - - setTimeout(delayedCheck,fontfaceCheckDelay); - setTimeout(delayedCheck,fontfaceCheckDelay*2); - addEventListener('load',function(){ - delayedCheck(); - (isCallbackCalled = true) && callback && callback(fontret); - setTimeout(function(){ - if (!isFakeBody) body = spn; - body.parentNode.removeChild(body); - st.parentNode.removeChild(st); - }, 50); - },false); - } - - // allow for a callback - ret._fontfaceready = function(fn){ - (isCallbackCalled || fontret) ? fn(fontret) : (callback = fn); - } - - return fontret || size !== spn.offsetWidth; - - }; - - - // These tests evaluate support of the video/audio elements, as well as - // testing what types of content they support. - // - // we're using the Boolean constructor here, so that we can extend the value - // e.g. Modernizr.video // true - // Modernizr.video.ogg // 'probably' - // - // codec values from : http://github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 - // thx to NielsLeenheer and zcorpan - - tests[video] = function() { - var elem = doc.createElement(video), - bool = !!elem[canPlayType]; - - if (bool){ - bool = new Boolean(bool); - bool.ogg = elem[canPlayType]('video/ogg; codecs="theora"'); - bool.h264 = elem[canPlayType]('video/mp4; codecs="avc1.42E01E"'); - bool.webm = elem[canPlayType]('video/webm; codecs="vp8, vorbis"'); - } - return bool; - }; - - tests[audio] = function() { - var elem = doc.createElement(audio), - bool = !!elem[canPlayType]; - - if (bool){ - bool = new Boolean(bool); - bool.ogg = elem[canPlayType]('audio/ogg; codecs="vorbis"'); - bool.mp3 = elem[canPlayType]('audio/mpeg;'); - - // mimetypes accepted: - // https://developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_vi... - // http://bit.ly/iphoneoscodecs - bool.wav = elem[canPlayType]('audio/wav; codecs="1"'); - bool.m4a = elem[canPlayType]('audio/x-m4a;') || elem[canPlayType]('audio/aac;'); - } - return bool; - }; - - - // both localStorage and sessionStorage are - // tested in this method because otherwise Firefox will - // throw an error: https://bugzilla.mozilla.org/show_bug.cgi?id=365772 - // if cookies are disabled - - // FWIW miller device resolves to [object Storage] in all supporting browsers - // except for IE who does [object Object] - - // IE8 Compat mode supports these features completely: - // http://www.quirksmode.org/dom/html5.html - - tests[localstorage] = function() { - return ('localStorage' in window) && window[localstorage] !== null; - }; - - tests[sessionstorage] = function() { - // try/catch required for pissy FF behavior - try { - return ('sessionStorage' in window) && window[sessionstorage] !== null; - } catch(e){ - return false; - } - }; - - - tests[webWorkers] = function () { - return !!window.Worker; - }; - - - tests[applicationcache] = function() { - var cache = window[applicationcache]; - return !!(cache && (typeof cache.status != 'undefined') && (typeof cache.update == 'function') && (typeof cache.swapCache == 'function')); - }; - - - // thanks to Erik Dahlstrom - tests[svg] = function(){ - return !!doc.createElementNS && !!doc.createElementNS( "http://www.w3.org/2000/svg", "svg").createSVGRect; - }; - - // thanks to F1lt3r and lucideer - // http://github.com/Modernizr/Modernizr/issues#issue/35 - tests[smil] = function(){ - return !!doc.createElementNS && /SVG/.test(tostring.call(doc.createElementNS('http://www.w3.org/2000/svg%27,%27animate'))); - }; - - tests[svgclippaths] = function(){ - // returns a false positive in saf 3.2? - return !!doc.createElementNS && /SVG/.test(tostring.call(doc.createElementNS('http://www.w3.org/2000/svg%27,%27clipPath'))); - }; - - - // input features and input types go directly onto the ret object, bypassing the tests loop. - // hold this guy to execute in a moment. - function webforms(){ - - // Run through HTML5's new input attributes to see if the UA understands any. - // We're using f which is the <input> element created early on - // Mike Taylr has created a comprehensive resource for testing these attributes - // when applied to all input types: - // http://miketaylr.com/code/input-type-attr.html - // spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-elemen... - ret[input] = (function(props) { - for (var i = 0,len=props.length;i<len;i++) { - attrs[ props[i] ] = !!(props[i] in f); - } - return attrs; - })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - - // Run through HTML5's new input types to see if the UA understands any. - // This is put behind the tests runloop because it doesn't return a - // true/false like all the other tests; instead, it returns an object - // containing each input type with its corresponding true/false value - - // Big thx to @miketaylr for the html5 forms expertise. http://miketaylr.com/ - ret[inputtypes] = (function(props) { - for (var i = 0,bool,len=props.length;i<len;i++) { - f.setAttribute('type', props[i]); - bool = f.type !== 'text'; - - // chrome likes to falsely purport support, so we feed it a textual value - // if that doesnt succeed then we know there's a custom UI - if (bool){ - - f.value = smile; - - /* Safari 4 is allowing the smiley as a value, and incorrecty failing.. - the test fixes for webkit only, but breaks Opera.. - if (/range/.test(f.type)){ - bool = test_props_all('appearance',function(prop,m){ return m_style[prop] !== 'textfield' }) - } - */ - - if (/tel|search/.test(f.type)){ - // spec doesnt define any special parsing or detectable UI - // behaviors so we pass these through as true - - } else if (/url|email/.test(f.type)) { - // real url and email support comes with prebaked validation. - bool = f.checkValidity && f.checkValidity() === false; - - } else { - bool = f.value != smile; - } - } - - inputs[ props[i] ] = !!bool; - } - return inputs; - })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - - } - - - - // end of test definitions - - - // Run through all tests and detect their support in the current UA. - // todo: hypothetically we could be doing an array of tests and use a basic loop here. - for ( var feature in tests ) { - if ( hasOwnProperty( tests, feature ) ) { - // run the test, throw the return value into the Modernizr, - // then based on that boolean, define an appropriate className - // and push it into an array of classes we'll join later. - classes.push( ( ( ret[ feature.toLowerCase() ] = tests[ feature ]() ) ? '' : 'no-' ) + feature.toLowerCase() ); - } - } - - // input tests need to run. - if (!ret[input]) webforms(); - - - - - - - /** - * Addtest allows the user to define their own feature tests - * the result will be added onto the Modernizr object, - * as well as an appropriate className set on the html element - * - * @param feature - String naming the feature - * @param test - Function returning true if feature is supported, false if not - */ - ret.addTest = function (feature, test) { - feature = feature.toLowerCase(); - - if (ret[ feature ]) { - return; // quit if you're trying to overwrite an existing test - } - test = !!(test()); - docElement.className += ' ' + (test ? '' : 'no-') + feature; - ret[ feature ] = test; - return ret; // allow chaining. - }; - - /** - * Reset m.style.cssText to nothing to reduce memory footprint. - */ - set_css( '' ); - m = f = null; - - // Enable HTML 5 elements for styling in IE. - // fyi: jscript version does not reflect trident version - // therefore ie9 in ie7 mode will still have a jScript v.9 - if ( enableHTML5 && (function(){ var elem = doc.createElement("div"); - elem.innerHTML = "<elem></elem>"; - return elem.childNodes.length !== 1; })()) { - // iepp v1.5.1 MIT @jon_neal http://code.google.com/p/ie-print-protector/ - (function(p,e){function q(a,b){if(g[a])g[a].styleSheet.cssText+=b;else{var c=r[l],d=e[j]("style");d.media=a;c.insertBefore(d,c[l]);g[a]=d;q(a,b)}}function s(a,b){for(var c=new RegExp("\b("+m+")\b(?!.*[;}])","gi"),d=function(k){return".iepp_"+k},h=-1;++h<a.length;){b=a[h].media||b;s(a[h].imports,b);q(b,a[h].cssText.replace(c,d))}}function t(){for(var a,b=e.getElementsByTagName("*"),c,d,h=new RegExp("^"+m+"$","i"),k=-1;++k<b.length;)if((a=b[k])&&(d=a.nodeName.match(h))){c=new RegExp("^\s*<"+d+"(.*)\/"+d+">\s*$","i");i.innerHTML=a.outerHTML.replace(/\r|\n/g," ").replace(c,a.currentStyle.display=="block"?"<div$1/div>":"<span$1/span>");c=i.childNodes[0];c.className+=" iepp_"+d;c=f[f.length]=[a,c];a.parentNode.replaceChild(c[1],c[0])}s(e.styleSheets,"all")}function u(){for(var a=-1,b;++a<f.length;)f[a][1].parentNode.replaceChild(f[a][0],f[a][1]);for(b in g)r[l].removeChild(g[b]);g={};f=[]}for(var r=e.documentElement,i=e.createDocumentFragment(),g={},m="abbr|article|a! side|audio|canvas|command|datalist|details|figure|figcaption|footer|header|hgroup|keygen|mark|meter|nav|output|progress|section|source|summary|time|video",n=m.split("|"),f=[],o=-1,l="firstChild",j="createElement";++o<n.length;){e[j](n[o]);i[j](n[o])}i=i.appendChild(e[j]("div"));p.attachEvent("onbeforeprint",t);p.attachEvent("onafterprint",u)})(this,doc); - } - - // Assign private properties to the return object with prefix - ret._enableHTML5 = enableHTML5; - ret._version = version; - - // Remove "no-js" class from <html> element, if it exists: - docElement.className=docElement.className.replace(/\bno-js\b/,'') + ' js'; - - // Add the new classes to the <html> element. - docElement.className += ' ' + classes.join( ' ' ); - - return ret; - -})(this,this.document);
On Wed, 2011-07-27 at 04:35 -0400, Chris Lalancette wrote:
From: Jason Guiditta jguiditt@redhat.com
src/public/javascripts/jquery.cookie.js | 92 --- src/public/javascripts/jquery.flash.js | 288 --------- src/public/javascripts/jquery.timers.js | 142 -----
These are really old and look unused
src/public/javascripts/jquery.html5form.js | 259 -------- src/public/javascripts/jquery.loadmask.min.js | 10 - src/public/javascripts/modernizr-1.5.js | 807
These were used by the old UI
ACK
Cheers, Mark.
Signed-off-by: Chris Lalancette clalance@redhat.com --- aeolus-conductor.spec.in | 20 ++++++++++++-------- 1 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in index 0792898..8ec3c92 100644 --- a/aeolus-conductor.spec.in +++ b/aeolus-conductor.spec.in @@ -19,23 +19,25 @@ Source0: aeolus-conductor-%{version}.tar.gz
Requires: ruby >= 1.8.1 Requires: ruby(abi) = 1.8 -Requires: rubygem(rails) >= 2.1.1 -Requires: rubygem(haml) +Requires: rubygem(rails) >= 3.0.5 +Requires: rubygem(haml) >= 3.1 Requires: rubygem(nokogiri) >= 1.4.0 Requires: rubygem(will_paginate) Requires: rubygem(parseconfig) -Requires: rubygem(authlogic) +Requires: rubygem(authlogic) >= 3.0.2 Requires: rubygem(deltacloud-client) >= 0.0.9.8 -Requires: rubygem(compass) +Requires: rubygem(compass) >= 0.10.2 Requires: rubygem(compass-960-plugin) Requires: rubygem(simple-navigation) Requires: rubygem(typhoeus) -Requires: rubygem(rest-client) +Requires: rubygem(rest-client) >= 1.6.1 Requires: rubygem(builder) Requires: rubygem(json) Requires: rubygem(rack-restful_submit) Requires: rubygem(net-scp) Requires: rubygem(uuidtools) +Requires: rubygem(sqlite3) +Requires: rubygem(pg) Requires: postgresql Requires: postgresql-server Requires: ruby-postgres @@ -76,14 +78,16 @@ Summary: Aeolus Conductor development and testing files Group: Applications/Internet Requires: %{name} = %{version}-%{release} Requires: rubygem(cucumber) +Requires: rubygem(cucumber-rails) Requires: rubygem(rspec) Requires: rubygem(timecop) Requires: rubygem(cucumber-rails) -Requires: rubygem(rspec-rails) -Requires: rubygem(webrat) -Requires: rubygem(database_cleaner) +Requires: rubygem(rspec-rails) >= 2.0.1 +Requires: rubygem(webrat) >= 0.7.2 +Requires: rubygem(database_cleaner) >= 0.5.0 Requires: rubygem(factory_girl) Requires: rubygem(vcr) +Requires: rubygem(factory_girl_rails)
%description devel Tests and other development tools for the Aeolus Conductor.
From: Matt Wagner matt.wagner@redhat.com
Rails 3 removed some of the routing and filter-related methods viewstate was relying on. The code for adding the viewstate routes needed to be changed considerably. --- src/lib/viewstate.rb | 69 +++++++++++++++++++++++++------------------------ 1 files changed, 35 insertions(+), 34 deletions(-)
diff --git a/src/lib/viewstate.rb b/src/lib/viewstate.rb index 77e5c36..58ee3cc 100644 --- a/src/lib/viewstate.rb +++ b/src/lib/viewstate.rb @@ -12,48 +12,49 @@ module ActionController end
def setup_viewstate_handlers - unless self.filter_chain.include? :handle_viewstate + unless self.before_filter.include? :handle_viewstate before_filter :handle_viewstate, :only => self.default_viewstates.keys else # Don't append a new filter; update the existing one instead - filter_index = self.filter_chain.index :handle_viewstate - filter = self.filter_chain[filter_index] + filter_index = self.before_filter.index :handle_viewstate + filter = self.before_filter[filter_index] filter.options[:only] = Set.new(self.default_viewstates.keys) end end
def setup_viewstate_routes(action) - self.send(:define_method, :get_viewstate) { get_viewstate_body(action) } - self.send(:define_method, :put_viewstate) { put_viewstate_body(action) } - self.send(:define_method, :post_viewstate) { post_viewstate_body(action) } - self.send(:define_method, :delete_viewstate) { delete_viewstate_body(action) } - - route_url = "#{controller_name}/#{action}/viewstate/:id" - return if ActionController::Routing::Routes.routes.any? {|r| r.to_s.include? route_url } - - get_viewstate_route = ActionController::Routing::Routes.builder.build(route_url, - :controller => controller_name, - :action => 'get_viewstate', - :conditions => {:method => :get}) - ActionController::Routing::Routes.routes.insert(0, get_viewstate_route) - - put_viewstate_route = ActionController::Routing::Routes.builder.build(route_url, - :controller => controller_name, - :action => 'put_viewstate', - :conditions => {:method => :put}) - ActionController::Routing::Routes.routes.insert(0, put_viewstate_route) - - post_viewstate_route = ActionController::Routing::Routes.builder.build(route_url, - :controller => controller_name, - :action => 'post_viewstate', - :conditions => {:method => :post}) - ActionController::Routing::Routes.routes.insert(0, post_viewstate_route) - - delete_viewstate_route = ActionController::Routing::Routes.builder.build(route_url, - :controller => controller_name, - :action => 'delete_viewstate', - :conditions => {:method => :delete}) - ActionController::Routing::Routes.routes.insert(0, delete_viewstate_route) + @@viewstate_routes ||= [] + self.send(:define_method, "get_viewstate_#{action}") { get_viewstate_body(action) } + self.send(:define_method, "put_viewstate_#{action}") { put_viewstate_body(action) } + self.send(:define_method, "post_viewstate_#{action}") { post_viewstate_body(action) } + self.send(:define_method, "delete_viewstate_#{action}") { delete_viewstate_body(action) } + + route_url = "#{controller_name}/#{action}/viewstate(/:id)" + routes = Conductor::Application.routes.routes + return if routes.any? {|r| r.to_s.include? route_url } + + [:get, :put, :post, :delete].each do |method| + @@viewstate_routes << { :url => route_url, :method => method, + :controller => controller_name, :action => "#{method}_viewstate_#{action}" } + end + @@viewstate_routes.uniq! + + begin + route_set = Conductor::Application.routes + route_set.disable_clear_and_finalize = true + route_set.clear! + route_set.draw do + @@viewstate_routes.each do |route| + match(route[:url], :via => route[:method], + :controller => route[:controller], + :action => route[:action]) + end + end + Conductor::Application.routes_reloader.paths.each { |path| load(path) } + ActiveSupport.on_load(:action_controller) { route_set.finalize! } + ensure + route_set.disable_clear_and_finalize = false + end end end
From: Matt Wagner matt.wagner@redhat.com
--- src/config/routes.rb | 86 ++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/src/config/routes.rb b/src/config/routes.rb index 2589742..f70b525 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -56,6 +56,7 @@ Conductor::Application.routes.draw do # match ':controller(/:action(/:id(.:format)))'
#Do we still need this one? => resource :user_session + resource :user_session match 'login', :to => 'user_sessions#new', :as => 'login' match 'logout', :to => 'user_sessions#destroy', :as => 'logout' match 'register', :to => 'users#new', :as => 'register' @@ -75,29 +76,82 @@ Conductor::Application.routes.draw do end
resources :pools, :collection => { :multi_destroy => :delete } - resources :deployments, :collection => { :multi_stop => :get, :launch_new => :get, :check_name => :get } - resources :instances, :collection => {:start => :get, :multi_stop => :get, :remove_failed => :get, :can_start => :get, :can_create => :get }, :member => {:key => :get} + + resources :deployments do + collection do + get 'multi_stop' + get 'launch_new' + get 'check_name' + end + end + + resources :instances do + collection do + get 'start' + get 'multi_stop' + get 'remove_failed' + get 'can_start' + get 'can_create' + end + get 'key', :on => :member + end
#map.can_start_instance '/instances/:instance_id/can_start/:provider_account_id', :controller => 'instances', :action => 'can_start', :conditions => { :method => :get } #map.can_create_instance '/instances/:instance_id/can_create/:provider_account_id', :controller => 'instances', :action => 'can_create', :conditions => { :method => :get }
resources :image_imports
- resources :hardware_profiles, :collection => { :multi_destroy => :delete } - resources :providers, :collection => { :multi_destroy => :delete } - #This may be the correct way to do the above now.... - #resources :providers do - # resources :accounts, :to => :cloud_accounts - #end + resources :hardware_profiles do + delete 'multi_destroy', :on => :collection + end + + resources :providers do + delete 'multi_destroy', :on => :collection + end + resources :provider_types, :only => :index - resources :users, :collection => { :multi_destroy => :delete } - resources :provider_accounts, :collection => { :multi_destroy => :delete, :set_selected_provider => :get} - resources :roles, :collection => { :multi_destroy => :delete } - resources :settings, :collection => { :self_service => :get, :general_settings => :get } - resources :pool_families, :collection => { :multi_destroy => :delete, :add_provider_account => :post, :multi_destroy_provider_accounts => :delete } - resources :realms, :collection => { :multi_destroy => :delete } - resources :realm_mappings, :collection => { :multi_destroy => :delete } - resources :suggested_deployables, :collection => { :multi_destroy => :delete } + + resources :users do + delete 'multi_destroy', :on => :collection + end + + resources :provider_accounts do + collection do + delete 'multi_destroy' + get 'set_selected_provider' + end + end + + resources :roles do + delete 'multi_destroy', :on => :collection + end + + resources :settings do + collection do + get 'self_service' + get 'general_settings' + end + end + + resources :pool_families do + collection do + delete 'multi_destroy' + post 'add_provider_account' + delete 'multi_destroy_provider_accounts' + end + end + + resources :realms do + delete 'multi_destroy', :on => :collection + end + + resources :realm_mappings do + delete 'multi_destroy', :on => :collection + end + + resources :suggested_deployables do + delete 'multi_destroy', :on => :collection + end
#match 'matching_profiles', :to => '/hardware_profiles/matching_profiles/:hardware_profile_id/provider/:provider_id', :controller => 'hardware_profiles', :action => 'matching_profiles', :conditions => { :method => :get }, :as =>'matching_profiles' match 'dashboard', :to => 'dashboard', :as => 'dashboard'
From: Matt Wagner matt.wagner@redhat.com
--- src/app/views/layouts/_filter_table.haml | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/app/views/layouts/_filter_table.haml b/src/app/views/layouts/_filter_table.haml index a963634..6b1a413 100644 --- a/src/app/views/layouts/_filter_table.haml +++ b/src/app/views/layouts/_filter_table.haml @@ -28,4 +28,4 @@ - columns.each do |column| %th = column[:name] - = rows.collect {|row| capture_haml(row, &block)}.to_s + = rows.collect {|row| capture_haml(row, &block)}.to_s.html_safe
From: Scott Seago sseago@redhat.com
With this change, spec tests will run, although there are several test failures. --- src/spec/models/credential_definition_spec.rb | 2 +- src/spec/spec_helper.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/spec/models/credential_definition_spec.rb b/src/spec/models/credential_definition_spec.rb index 9b39e21..3f59bb7 100644 --- a/src/spec/models/credential_definition_spec.rb +++ b/src/spec/models/credential_definition_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper'
-context CredentialDefinition do +describe CredentialDefinition do before(:each) do @cred_def = Factory.build(:credential_definition) end diff --git a/src/spec/spec_helper.rb b/src/spec/spec_helper.rb index 97aca3e..98d7468 100644 --- a/src/spec/spec_helper.rb +++ b/src/spec/spec_helper.rb @@ -13,6 +13,10 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config| include Authlogic::TestCase + + config.use_transactional_fixtures = true + config.use_instantiated_fixtures = false + config.fixture_path = RAILS_ROOT + '/spec/fixtures/' # # == Mock Framework #
From: Scott Seago sseago@redhat.com
Tests are still all failing, but this gets them to the point where they'll run. --- src/config/cucumber.yml | 2 +- src/config/environments/cucumber.rb | 67 +++--- src/features/step_definitions/custom_web_steps.rb | 3 + src/features/step_definitions/web_steps.rb | 246 +++++++-------------- src/features/support/env.rb | 80 +++---- src/features/support/paths.rb | 6 +- src/features/support/selectors.rb | 39 ++++ src/features/support/vcr.rb | 2 + src/lib/tasks/cucumber.rake | 12 + 9 files changed, 214 insertions(+), 243 deletions(-) create mode 100644 src/features/step_definitions/custom_web_steps.rb create mode 100644 src/features/support/selectors.rb create mode 100644 src/features/support/vcr.rb
diff --git a/src/config/cucumber.yml b/src/config/cucumber.yml index 621a14c..19b288d 100644 --- a/src/config/cucumber.yml +++ b/src/config/cucumber.yml @@ -1,7 +1,7 @@ <% rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" -std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip" +std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip" %> default: <%= std_opts %> features wip: --tags @wip:3 --wip features diff --git a/src/config/environments/cucumber.rb b/src/config/environments/cucumber.rb index 743fd76..f4e4baf 100644 --- a/src/config/environments/cucumber.rb +++ b/src/config/environments/cucumber.rb @@ -1,32 +1,35 @@ -# Edit at your own peril - it's recommended to regenerate this file -# in the future when you upgrade to a newer version of Cucumber. - -# IMPORTANT: Setting config.cache_classes to false is known to -# break Cucumber's use_transactional_fixtures method. -# For more information see https://rspec.lighthouseapp.com/projects/16211/tickets/165 -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 Action Mailer not to deliver emails to the real world. -# The :test delivery method accumulates sent emails in the -# ActionMailer::Base.deliveries array. -config.action_mailer.delivery_method = :test - -config.gem 'cucumber-rails', :lib => false, :version => '~>0.3.2' unless File.directory?(File.join(Rails.root, 'vendor/plugins/cucumber-rails')) -config.gem 'database_cleaner', :lib => false, :version => '~>0.5.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/database_cleaner')) -config.gem 'webrat', :lib => false, :version => '~>0.7.3' unless File.directory?(File.join(Rails.root, 'vendor/plugins/webrat')) -config.gem 'rspec', :lib => false, :version => '~>1.3.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec')) -config.gem 'rspec-rails', :lib => false, :version => '~>1.3.2' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) - -config.gem "factory_girl", :lib => "factory_girl", :version => "~>1.3.1" -config.gem 'vcr', :lib => 'vcr', :version => '>= 1.10.0' -config.gem 'webmock', :lib => 'webmock', :version => '>= 1.6.4' +Conductor::Application.configure do + # 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.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/src/features/step_definitions/custom_web_steps.rb b/src/features/step_definitions/custom_web_steps.rb new file mode 100644 index 0000000..a3e0463 --- /dev/null +++ b/src/features/step_definitions/custom_web_steps.rb @@ -0,0 +1,3 @@ +When /^(?:|I )follow link with ID "([^"]*)"$/ do |link_id| + click_link(link_id) +end diff --git a/src/features/step_definitions/web_steps.rb b/src/features/step_definitions/web_steps.rb index ee01547..d79b63b 100644 --- a/src/features/step_definitions/web_steps.rb +++ b/src/features/step_definitions/web_steps.rb @@ -1,16 +1,45 @@ -# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. -# It is recommended to regenerate this file in the future when you upgrade to a -# newer version of cucumber-rails. Consider adding your own code to a new file -# instead of editing this one. Cucumber will automatically load all features/**/*.rb -# files. +# TL;DR: YOU SHOULD DELETE THIS FILE +# +# This file was generated by Cucumber-Rails and is only here to get you a head start +# These step definitions are thin wrappers around the Capybara/Webrat API that lets you +# visit pages, interact with widgets and make assertions about page content. +# +# If you use these step definitions as basis for your features you will quickly end up +# with features that are: +# +# * Hard to maintain +# * Verbose to read +# +# A much better approach is to write your own higher level step definitions, following +# the advice in the following blog posts: +# +# * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-s... +# * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/ +# * http://elabs.se/blog/15-you-re-cuking-it-wrong +#
require 'uri' require 'cgi' require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) +require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "selectors")) + +module WithinHelpers + def with_scope(locator) + locator ? within(*selector_for(locator)) { yield } : yield + end +end +World(WithinHelpers) + +# Single-line step scoper +When /^(.*) within (.*[^:])$/ do |step, parent| + with_scope(parent) { When step } +end
-# Commonly used webrat steps -# http://github.com/brynary/webrat +# Multi-line step scoper +When /^(.*) within (.*[^:]):$/ do |step, parent, table_or_string| + with_scope(parent) { When "#{step}:", table_or_string } +end
Given /^(?:|I )am on (.+)$/ do |page_name| visit path_to(page_name) @@ -24,24 +53,10 @@ When /^(?:|I )press "([^"]*)"$/ do |button| click_button(button) end
-When /^I press "([^"]*)" within "([^"]*)"$/ do |button,scope_selector| - within(scope_selector) do - click_button(button) - end -end - When /^(?:|I )follow "([^"]*)"$/ do |link| click_link(link) end
-When /^(?:|I )follow link with ID "([^"]*)"$/ do |link_id| - click_link(link_id) -end - -When /^(?:|I )follow "([^"]*)" within "([^"]*)"$/ do |link, parent| - click_link_within(parent, link) -end - When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value| fill_in(field, :with => value) end @@ -71,53 +86,6 @@ When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, field| select(value, :from => field) end
-# Use this step in conjunction with Rail's datetime_select helper. For example: -# When I select "December 25, 2008 10:00" as the date and time -When /^(?:|I )select "([^"]*)" as the date and time$/ do |time| - select_datetime(time) -end - -# Use this step when using multiple datetime_select helpers on a page or -# you want to specify which datetime to select. Given the following view: -# <%= f.label :preferred %><br /> -# <%= f.datetime_select :preferred %> -# <%= f.label :alternative %><br /> -# <%= f.datetime_select :alternative %> -# The following steps would fill out the form: -# When I select "November 23, 2004 11:20" as the "Preferred" date and time -# And I select "November 25, 2004 10:30" as the "Alternative" date and time -When /^(?:|I )select "([^"]*)" as the "([^"]*)" date and time$/ do |datetime, datetime_label| - select_datetime(datetime, :from => datetime_label) -end - -# Use this step in conjunction with Rail's time_select helper. For example: -# When I select "2:20PM" as the time -# Note: Rail's default time helper provides 24-hour time-- not 12 hour time. Webrat -# will convert the 2:20PM to 14:20 and then select it. -When /^(?:|I )select "([^"]*)" as the time$/ do |time| - select_time(time) -end - -# Use this step when using multiple time_select helpers on a page or you want to -# specify the name of the time on the form. For example: -# When I select "7:30AM" as the "Gym" time -When /^(?:|I )select "([^"]*)" as the "([^"]*)" time$/ do |time, time_label| - select_time(time, :from => time_label) -end - -# Use this step in conjunction with Rail's date_select helper. For example: -# When I select "February 20, 1981" as the date -When /^(?:|I )select "([^"]*)" as the date$/ do |date| - select_date(date) -end - -# Use this step when using multiple date_select helpers on one page or -# you want to specify the name of the date on the form. For example: -# When I select "April 26, 1982" as the "Date of Birth" date -When /^(?:|I )select "([^"]*)" as the "([^"]*)" date$/ do |date, date_label| - select_date(date, :from => date_label) -end - When /^(?:|I )check "([^"]*)"$/ do |field| check(field) end @@ -130,137 +98,89 @@ When /^(?:|I )choose "([^"]*)"$/ do |field| choose(field) end
-# Adds support for validates_attachment_content_type. Without the mime-type getting -# passed to attach_file() you will get a "Photo file is not one of the allowed file types." -# error message When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |path, field| - type = path.split(".")[1] - - case type - when "jpg" - type = "image/jpg" - when "jpeg" - type = "image/jpeg" - when "png" - type = "image/png" - when "gif" - type = "image/gif" - end - - attach_file(field, path, type) + attach_file(field, File.expand_path(path)) end
Then /^(?:|I )should see "([^"]*)"$/ do |text| - if response.respond_to? :should - response.should contain(text) + if page.respond_to? :should + page.should have_content(text) else - assert_contain text - end -end - -Then /^(?:|I )should see "([^"]*)" within "([^"]*)"$/ do |text, selector| - within(selector) do |content| - if content.respond_to? :should - content.should contain(text) - else - hc = Webrat::Matchers::HasContent.new(text) - assert hc.matches?(content), hc.failure_message - end + assert page.has_content?(text) end end
Then /^(?:|I )should see /([^/]*)/$/ do |regexp| regexp = Regexp.new(regexp) - if response.respond_to? :should - response.should contain(regexp) - else - assert_match(regexp, response_body) - end -end
-Then /^(?:|I )should see /([^/]*)/ within "([^"]*)"$/ do |regexp, selector| - within(selector) do |content| - regexp = Regexp.new(regexp) - if content.respond_to? :should - content.should contain(regexp) - else - assert_match(regexp, content) - end + if page.respond_to? :should + page.should have_xpath('//*', :text => regexp) + else + assert page.has_xpath?('//*', :text => regexp) end end
Then /^(?:|I )should not see "([^"]*)"$/ do |text| - if response.respond_to? :should_not - response.should_not contain(text) + if page.respond_to? :should + page.should have_no_content(text) else - assert_not_contain(text) - end -end - -Then /^(?:|I )should not see "([^"]*)" within "([^"]*)"$/ do |text, selector| - within(selector) do |content| - if content.respond_to? :should_not - content.should_not contain(text) - else - hc = Webrat::Matchers::HasContent.new(text) - assert !hc.matches?(content), hc.negative_failure_message - end + assert page.has_no_content?(text) end end
Then /^(?:|I )should not see /([^/]*)/$/ do |regexp| regexp = Regexp.new(regexp) - if response.respond_to? :should_not - response.should_not contain(regexp) + + if page.respond_to? :should + page.should have_no_xpath('//*', :text => regexp) else - assert_not_contain(regexp) + assert page.has_no_xpath?('//*', :text => regexp) end end
-Then /^(?:|I )should not see /([^/]*)/ within "([^"]*)"$/ do |regexp, selector| - within(selector) do |content| - regexp = Regexp.new(regexp) - if content.respond_to? :should_not - content.should_not contain(regexp) +Then /^the "([^"]*)" field(?: within (.*))? should contain "([^"]*)"$/ do |field, parent, value| + with_scope(parent) do + field = find_field(field) + field_value = (field.tag_name == 'textarea') ? field.text : field.value + if field_value.respond_to? :should + field_value.should =~ /#{value}/ else - assert_no_match(regexp, content) + assert_match(/#{value}/, field_value) end end end
-Then /^the "([^"]*)" field should contain "([^"]*)"$/ do |field, value| - field_value = field_labeled(field).value - if field_value.respond_to? :should - field_value.should =~ /#{value}/ - else - assert_match(/#{value}/, field_value) - end -end - -Then /^the "([^"]*)" field should not contain "([^"]*)"$/ do |field, value| - field_value = field_labeled(field).value - if field_value.respond_to? :should_not - field_value.should_not =~ /#{value}/ - else - assert_no_match(/#{value}/, field_value) +Then /^the "([^"]*)" field(?: within (.*))? should not contain "([^"]*)"$/ do |field, parent, value| + with_scope(parent) do + field = find_field(field) + field_value = (field.tag_name == 'textarea') ? field.text : field.value + if field_value.respond_to? :should_not + field_value.should_not =~ /#{value}/ + else + assert_no_match(/#{value}/, field_value) + end end end
-Then /^the "([^"]*)" checkbox should be checked$/ do |label| - field = field_labeled(label) - if field.respond_to? :should - field.should be_checked - else - assert field.checked? +Then /^the "([^"]*)" checkbox(?: within (.*))? should be checked$/ do |label, parent| + with_scope(parent) do + field_checked = find_field(label)['checked'] + if field_checked.respond_to? :should + field_checked.should be_true + else + assert field_checked + end end end
-Then /^the "([^"]*)" checkbox should not be checked$/ do |label| - field = field_labeled(label) - if field.respond_to? :should_not - field.should_not be_checked - else - assert !field.checked? +Then /^the "([^"]*)" checkbox(?: within (.*))? should not be checked$/ do |label, parent| + with_scope(parent) do + field_checked = find_field(label)['checked'] + if field_checked.respond_to? :should + field_checked.should be_false + else + assert !field_checked + end end end
diff --git a/src/features/support/env.rb b/src/features/support/env.rb index d06255f..2d8b48e 100644 --- a/src/features/support/env.rb +++ b/src/features/support/env.rb @@ -4,55 +4,47 @@ # instead of editing this one. Cucumber will automatically load all features/**/*.rb # files.
-ENV["RAILS_ENV"] ||= "test" -require File.expand_path(File.dirname(__FILE__) + '/../../config/environment') +require 'cucumber/rails'
-require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support -require 'cucumber/rails/world' -require 'cucumber/rails/active_record' -require 'cucumber/web/tableish' +# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In +# order to ease the transition to Capybara we set the default here. If you'd +# prefer to use XPath just remove this line and adjust any selectors in your +# steps to use the XPath syntax. +Capybara.default_selector = :css
-# Pull in our VCR configuration -require File.expand_path(File.dirname(__FILE__) + '../../../spec/vcr_setup.rb') - -require 'webrat' -require 'webrat/core/matchers' +# By default, any exception happening in your Rails application will bubble up +# to Cucumber so that your scenario will fail. This is a different from how +# your application behaves in the production environment, where an error page will +# be rendered instead. +# +# Sometimes we want to override this default behaviour and allow Rails to rescue +# exceptions and display an error page (just like when the app is running in production). +# Typical scenarios where you want to do this is when you test your error pages. +# There are two ways to allow Rails to rescue exceptions: +# +# 1) Tag your scenario (or feature) with @allow-rescue +# +# 2) Set the value below to true. Beware that doing this globally is not +# recommended as it will mask a lot of errors for you! +# +ActionController::Base.allow_rescue = false
-Webrat.configure do |config| - config.mode = :rack - config.open_error_files = false # Set to true if you want error pages to pop up in the browser +# Remove/comment out the lines below if your app doesn't have a database. +# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead. +begin + DatabaseCleaner.strategy = :transaction +rescue NameError + raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it." end
-# If you set this to false, any error raised from within your app will bubble -# up to your step definition and out to cucumber unless you catch it somewhere -# on the way. You can make Rails rescue errors and render error pages on a -# per-scenario basis by tagging a scenario or feature with the @allow-rescue tag. +# You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios. +# See the DatabaseCleaner documentation for details. Example: # -# If you set this to true, Rails will rescue all errors and render error -# pages, more or less in the same way your application would behave in the -# default production environment. It's not recommended to do this for all -# of your scenarios, as this makes it hard to discover errors in your application. -ActionController::Base.allow_rescue = false - -# If you set this to true, each scenario will run in a database transaction. -# You can still turn off transactions on a per-scenario basis, simply tagging -# a feature or scenario with the @no-txn tag. If you are using Capybara, -# tagging with @culerity or @javascript will also turn transactions off. +# Before('@no-txn,@selenium,@culerity,@celerity,@javascript') do +# DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]} +# end # -# If you set this to false, transactions will be off for all scenarios, -# regardless of whether you use @no-txn or not. +# Before('~@no-txn', '~@selenium', '~@culerity', '~@celerity', '~@javascript') do +# DatabaseCleaner.strategy = :transaction +# end # -# Beware that turning transactions off will leave data in your database -# after each scenario, which can lead to hard-to-debug failures in -# subsequent scenarios. If you do this, we recommend you create a Before -# block that will explicitly put your database in a known state. -Cucumber::Rails::World.use_transactional_fixtures = true -# How to clean your database when transactions are turned off. See -# http://github.com/bmabey/database_cleaner for more info. -if defined?(ActiveRecord::Base) - begin - require 'database_cleaner' - DatabaseCleaner.strategy = :truncation - rescue LoadError => ignore_if_database_cleaner_not_present - end -end diff --git a/src/features/support/paths.rb b/src/features/support/paths.rb index 1461077..271f46d 100644 --- a/src/features/support/paths.rb +++ b/src/features/support/paths.rb @@ -8,7 +8,7 @@ module NavigationHelpers def path_to(page_name) case page_name
- when /the home\s?page/ + when /^the home\s?page$/ '/'
when /the new account page/ @@ -135,10 +135,10 @@ module NavigationHelpers
else begin - page_name =~ /the (.*) page/ + page_name =~ /^the (.*) page$/ path_components = $1.split(/\s+/) self.send(path_components.push('path').join('_').to_sym) - rescue Object => e + rescue NoMethodError, ArgumentError raise "Can't find mapping from "#{page_name}" to a path.\n" + "Now, go and add a mapping in #{__FILE__}" end diff --git a/src/features/support/selectors.rb b/src/features/support/selectors.rb new file mode 100644 index 0000000..44e34a4 --- /dev/null +++ b/src/features/support/selectors.rb @@ -0,0 +1,39 @@ +module HtmlSelectorsHelpers + # Maps a name to a selector. Used primarily by the + # + # When /^(.+) within (.+)$/ do |step, scope| + # + # step definitions in web_steps.rb + # + def selector_for(locator) + case locator + + when "the page" + "html > body" + + # Add more mappings here. + # Here is an example that pulls values out of the Regexp: + # + # when /^the (notice|error|info) flash$/ + # ".flash.#{$1}" + + # You can also return an array to use a different selector + # type, like: + # + # when /the header/ + # [:xpath, "//header"] + + # This allows you to provide a quoted selector as the scope + # for "within" steps as was previously the default for the + # web steps: + when /^"(.+)"$/ + $1 + + else + raise "Can't find mapping from "#{locator}" to a selector.\n" + + "Now, go and add a mapping in #{__FILE__}" + end + end +end + +World(HtmlSelectorsHelpers) diff --git a/src/features/support/vcr.rb b/src/features/support/vcr.rb new file mode 100644 index 0000000..e38bc05 --- /dev/null +++ b/src/features/support/vcr.rb @@ -0,0 +1,2 @@ +# Pull in our VCR configuration +require File.expand_path(File.dirname(__FILE__) + '../../../spec/vcr_setup.rb') diff --git a/src/lib/tasks/cucumber.rake b/src/lib/tasks/cucumber.rake index 64cca31..ae5c636 100644 --- a/src/lib/tasks/cucumber.rake +++ b/src/lib/tasks/cucumber.rake @@ -34,6 +34,12 @@ begin
desc 'Run all features' task :all => [:ok, :wip] + + task :statsetup do + require 'rails/code_statistics' + ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features') + ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features') + end end desc 'Alias for cucumber:ok' task :cucumber => 'cucumber:ok' @@ -43,6 +49,12 @@ begin task :features => :cucumber do STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" end + + # In case we don't have ActiveRecord, append a no-op task that we can depend upon. + task 'db:test:prepare' do + end + + task :stats => 'cucumber:statsetup' rescue LoadError desc 'cucumber rake task not available (cucumber not installed)' task :cucumber do
Signed-off-by: Chris Lalancette clalance@redhat.com --- src/dutils/active_record_env.rb | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/dutils/active_record_env.rb b/src/dutils/active_record_env.rb index 280d266..511954a 100644 --- a/src/dutils/active_record_env.rb +++ b/src/dutils/active_record_env.rb @@ -26,7 +26,7 @@ $LOAD_PATH << File.expand_path(File.dirname(__FILE__)) ENV['RAILS_ENV'] = 'development' unless ENV['RAILS_ENV']
require File.dirname(__FILE__) + '/../config/boot' -require "#{RAILS_ROOT}/config/environment" +require File.dirname(__FILE__) + '/../config/environment'
def database_connect conf = YAML::load(File.open(File.dirname(__FILE__) + '/../config/database.yml'))
Signed-off-by: Chris Lalancette clalance@redhat.com --- src/config/application.rb | 2 +- src/dutils/active_record_env.rb | 1 + 2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/config/application.rb b/src/config/application.rb index 11261ac..af0f874 100644 --- a/src/config/application.rb +++ b/src/config/application.rb @@ -41,7 +41,7 @@ module Conductor
# Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password, :password_confirmation] - require 'lib/warehouse_model.rb' + require File.dirname(__FILE__) + '/../lib/warehouse_model'
config.after_initialize do Haml::Template.options[:format] = :html5 diff --git a/src/dutils/active_record_env.rb b/src/dutils/active_record_env.rb index 511954a..cee3b62 100644 --- a/src/dutils/active_record_env.rb +++ b/src/dutils/active_record_env.rb @@ -18,6 +18,7 @@ # also available at http://www.gnu.org/copyleft/gpl.html.
$: << File.join(File.dirname(__FILE__), "../app") +$: << File.join(File.dirname(__FILE__), "..")
require 'rubygems'
From: Jason Guiditta jguiditt@redhat.com
This fixes all but 1 test, and removes a bunch of deprecation warning for same.
Note that the error output is a first pass and shoudl be extracted into a helper we can use through the app with the layout we want consistently applied. --- src/app/models/hardware_profile_property.rb | 10 ++++++---- src/app/models/image_warehouse_object.rb | 2 +- src/app/models/instance.rb | 8 ++++---- src/app/views/user_sessions/new.haml | 2 +- src/app/views/users/_form.haml | 5 ++++- src/app/views/users/edit.haml | 2 +- src/config/routes.rb | 1 - src/features/support/paths.rb | 6 +++--- src/lib/warehouse_model.rb | 4 ++-- 9 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/src/app/models/hardware_profile_property.rb b/src/app/models/hardware_profile_property.rb index 18c29e2..6c83231 100644 --- a/src/app/models/hardware_profile_property.rb +++ b/src/app/models/hardware_profile_property.rb @@ -54,6 +54,7 @@ class HardwareProfileProperty < ActiveRecord::Base
has_many :property_enum_entries
+ before_validation :is_form_empty? validates_presence_of :name validates_inclusion_of :name, :in => [MEMORY, STORAGE, CPU, ARCHITECTURE] @@ -74,10 +75,6 @@ class HardwareProfileProperty < ActiveRecord::Base p.kind == RANGE and p.value.present?} validates_associated :property_enum_entries
- def before_validation - # If the form isn't filled out, it comes in as "", which we treat as nil: - self.value = nil if self.value=="" - end
def validate case name @@ -146,5 +143,10 @@ class HardwareProfileProperty < ActiveRecord::Base return name == "architecture" ? sort_value : sort_value.to_f end
+ protected + def is_form_empty? + # If the form isn't filled out, it comes in as "", which we treat as nil: + self.value = nil if self.value=="" + end end
diff --git a/src/app/models/image_warehouse_object.rb b/src/app/models/image_warehouse_object.rb index b88cc93..89c1e7b 100644 --- a/src/app/models/image_warehouse_object.rb +++ b/src/app/models/image_warehouse_object.rb @@ -23,7 +23,7 @@ class WarehouseObjectNotFoundError < Exception;end
module ImageWarehouseObject
- WAREHOUSE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml") + WAREHOUSE_CONFIG = YAML.load_file("#{::Rails.root.to_s}/config/image_warehouse.yml")
def xml @xml ||= ImageDescriptorXML.new(self[:xml].to_s) diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index af5ec85..7374c1e 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -103,11 +103,11 @@ class Instance < ActiveRecord::Base STATE_SHUTTING_DOWN, STATE_STOPPED, STATE_CREATE_FAILED, STATE_ERROR]
- named_scope :deployed, :conditions => { :state => [STATE_RUNNING, STATE_SHUTTING_DOWN] } + scope :deployed, :conditions => { :state => [STATE_RUNNING, STATE_SHUTTING_DOWN] } # FIXME: "pending" is misleading as it doesn't just cover STATE_PENDING - named_scope :pending, :conditions => { :state => [STATE_NEW, STATE_PENDING] } + scope :pending, :conditions => { :state => [STATE_NEW, STATE_PENDING] } # FIXME: "failed" is misleading too... - named_scope :failed, :conditions => { :state => [STATE_CREATE_FAILED, STATE_ERROR] } + scope :failed, :conditions => { :state => [STATE_CREATE_FAILED, STATE_ERROR] }
SEARCHABLE_COLUMNS = %w(name state) @@ -340,7 +340,7 @@ class Instance < ActiveRecord::Base end end
- named_scope :with_hardware_profile, lambda { + scope :with_hardware_profile, lambda { {:include => :hardware_profile} } end diff --git a/src/app/views/user_sessions/new.haml b/src/app/views/user_sessions/new.haml index 1a08139..3ef9eb3 100644 --- a/src/app/views/user_sessions/new.haml +++ b/src/app/views/user_sessions/new.haml @@ -47,7 +47,7 @@ = render :partial => 'security' .panel#login .content - - form_for @user_session, :url => user_session_path do |f| + = form_for @user_session, :url => user_session_path do |f| %fieldset.primary = f.label :login, "Username:" = f.text_field :login, :class => 'username' diff --git a/src/app/views/users/_form.haml b/src/app/views/users/_form.haml index b174b1b..fb186dd 100644 --- a/src/app/views/users/_form.haml +++ b/src/app/views/users/_form.haml @@ -1,4 +1,7 @@ -= form.error_messages +%ul + =@user.errors.full_messages.each do |msg| + %li =msg + %fieldset %p = form.label :login, t(:choose_name) diff --git a/src/app/views/users/edit.haml b/src/app/views/users/edit.haml index 063c6a7..e4d6686 100644 --- a/src/app/views/users/edit.haml +++ b/src/app/views/users/edit.haml @@ -16,5 +16,5 @@ %h2 Editing Account
.content - - form_for @user, :url => user_path(@user), :html => { :method => :put, :class => 'generic' } do |f| + = form_for @user, :url => user_path(@user), :html => { :method => :put, :class => 'generic' } do |f| = render :partial => "form", :locals => { :form => f, :cancel_path => users_path } diff --git a/src/config/routes.rb b/src/config/routes.rb index f70b525..c53ea06 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -55,7 +55,6 @@ Conductor::Application.routes.draw do # Note: This route will make all actions in every controller accessible via GET requests. # match ':controller(/:action(/:id(.:format)))'
- #Do we still need this one? => resource :user_session resource :user_session match 'login', :to => 'user_sessions#new', :as => 'login' match 'logout', :to => 'user_sessions#destroy', :as => 'logout' diff --git a/src/features/support/paths.rb b/src/features/support/paths.rb index 271f46d..891e828 100644 --- a/src/features/support/paths.rb +++ b/src/features/support/paths.rb @@ -30,7 +30,7 @@ module NavigationHelpers account_path
when /the login error page/ - url_for :controller => 'user_sessions', :action => 'new', :only_path => true + user_session_path
when /the providers page/ url_for :controller => 'providers', :action => 'index', :only_path => true @@ -120,8 +120,8 @@ module NavigationHelpers pool = Pool.find_by_name($1) pool_path(pool, :view => 'filter')
- when /^the (.*)'s user page$/ - user_path(User.find_by_login($1)) + when /^the user page$/ + user_path #(User.find_by_login($1))
when /^the (.*)'s edit user page$/ edit_user_path(User.find_by_login($1)) diff --git a/src/lib/warehouse_model.rb b/src/lib/warehouse_model.rb index e2a8c9a..056cbdd 100644 --- a/src/lib/warehouse_model.rb +++ b/src/lib/warehouse_model.rb @@ -3,7 +3,7 @@ class BucketObjectNotFound < Exception;end class BucketNotFound < Exception;end
class WarehouseModel - WAREHOUSE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml") + WAREHOUSE_CONFIG = YAML.load_file("#{::Rails.root.to_s}/config/image_warehouse.yml")
def ==(other_obj) # If the objects have different instance variables defined, they're definitely not == @@ -72,4 +72,4 @@ class WarehouseModel self.warehouse.query(@bucket_name, query_string) end end -end \ No newline at end of file +end
Thin's rails adapter apparently doesn't know how to deal with rails3. Instead, use rackup with thin to launch the conductor, which seems to work. Also export RAILS_RELATIVE_URL_ROOT so that the conductor lives under /conductor.
Signed-off-by: Chris Lalancette clalance@redhat.com --- conf/aeolus-conductor | 34 ++++++++++++---------------------- conf/aeolus-conductor.sysconf | 21 +++++++++++++-------- 2 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/conf/aeolus-conductor b/conf/aeolus-conductor index e6e7d25..824a4b8 100755 --- a/conf/aeolus-conductor +++ b/conf/aeolus-conductor @@ -14,34 +14,32 @@
RAILS_ENV="${RAILS_ENV:-production}" CONDUCTOR_DIR="${CONDUCTOR_DIR:-/usr/share/aeolus-conductor}" -THIN_LOG="${THIN_LOG:-/var/log/aeolus-conductor/thin.log}" +CONDUCTOR_USER="${CONDUCTOR_USER:-aeolus}" +THIN_PROG="${THIN_PROG:-thin}" THIN_PID="${THIN_PID:-/var/run/aeolus-conductor/thin.pid}" -THIN_LOCKFILE="${THIN_LOCKFILE:-/var/lock/subsys/aeolus-conductor}" -AEOLUS_USER="${AEOLUS_USER:-aeolus}" -AEOLUS_GROUP="${AEOLUS_GROUP:-aeolus}" +THIN_LOG="${THIN_LOG:-/var/log/aeolus-conductor/thin.log}" PREFIX="${PREFIX:-/conductor}" -ADAPTER="${ADAPTER:-rails}" +ADDR="${ADDR:-127.0.0.1}"
-THIN_PROG=thin -ADDR=127.0.0.1 -RETVAL=0 +export RAILS_RELATIVE_URL_ROOT=$PREFIX
+RETVAL=0 STARTTIMEOUT=20
. /etc/init.d/functions
start() { echo -n "Starting aeolus-conductor: " - if [ -f $THIN_PID ] && checkpid `cat $THIN_PID` ; then + if [ -f "$THIN_PID" ] && checkpid `cat $THIN_PID` ; then echo_failure echo echo "Thin is already running" exit 1 fi
- $THIN_PROG start -c $CONDUCTOR_DIR -l $THIN_LOG -P $THIN_PID \ - -a $ADDR -e $RAILS_ENV --user $AEOLUS_USER --group $AEOLUS_GROUP \ - -d --prefix=$PREFIX -A $ADAPTER + $THIN_PROG start -c "$CONDUCTOR_DIR" -l "$THIN_LOG" -P "$THIN_PID" \ + -a $ADDR -e $RAILS_ENV --user $CONDUCTOR_USER -d --prefix=$PREFIX \ + --rackup "$CONDUCTOR_DIR/config.ru" RETVAL=$? if [ $RETVAL -eq 0 ] ; then # wait until we can contact the server @@ -68,15 +66,7 @@ start() {
stop() { echo -n "Shutting down aeolus-conductor: " - $THIN_PROG stop -c $CONDUCTOR_DIR -P $THIN_PID - RETVAL=$? - if [ $RETVAL -eq 0 ] && rm -f $THIN_LOCKFILE ; then - echo_success - echo - else - echo_failure - echo - fi + killproc -p $THINPID thin }
case "$1" in @@ -100,7 +90,7 @@ case "$1" in RETVAL=$? ;; *) - echo "Usage: aeolus-conductor {start|stop|restart|status}" + echo "Usage: aeolus-conductor {start|stop|restart|reload|force-reload|status}" exit 1 ;; esac diff --git a/conf/aeolus-conductor.sysconf b/conf/aeolus-conductor.sysconf index 50c450e..63bc0ee 100644 --- a/conf/aeolus-conductor.sysconf +++ b/conf/aeolus-conductor.sysconf @@ -1,16 +1,21 @@ # root directory of the Aeolus Conductor Rails application #CONDUCTOR_DIR=/usr/share/aeolus-conductor
-# location of the logfile -#THIN_LOG=/var/log/aeolus-conductor/thin.log +# user under which Rails application runs +#CONDUCTOR_USER=aeolus
-# location of the lockfile -#THIN_LOCKFILE=/var/lock/subsys/aeolus-conductor +# location of the thin program +#THIN_PROG=thin
-# location of the file containing running process ID +# location for the thin pid file #THIN_PID=/var/run/aeolus-conductor/thin.pid
-# user and group under which Rails application runs -#CONDUCTOR_USER=aeolus -#CONDUCTOR_GROUP=aeolus +# location for the thin log file +#THIN_LOG=/var/log/aeolus-conductor/thin.log + +# prefix for the conductor +#PREFIX=/conductor
+# address that the conductor should listen on (127.0.0.1 by default, when +# proxying through apache +#ADDR=127.0.0.1
aeolus-devel@lists.fedorahosted.org