Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

Signed-off-by: David A. Cuadrado <krawek@gmail.com>
  • Loading branch information...
commit 5b590697e1efd54e84b93cae743f84b7668b6e11 0 parents
David Cuadrado dcu authored
Showing with 4,268 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +243 −0 README
  3. +10 −0 Rakefile
  4. +10 −0 app/controllers/application_controller.rb
  5. +3 −0  app/helpers/application_helper.rb
  6. +110 −0 config/boot.rb
  7. +22 −0 config/database.yml
  8. +41 −0 config/environment.rb
  9. +17 −0 config/environments/development.rb
  10. +28 −0 config/environments/production.rb
  11. +28 −0 config/environments/test.rb
  12. +7 −0 config/initializers/backtrace_silencers.rb
  13. +10 −0 config/initializers/inflections.rb
  14. +5 −0 config/initializers/mime_types.rb
  15. +19 −0 config/initializers/new_rails_defaults.rb
  16. +15 −0 config/initializers/session_store.rb
  17. +5 −0 config/locales/en.yml
  18. +43 −0 config/routes.rb
  19. +2 −0  doc/README_FOR_APP
  20. +30 −0 public/404.html
  21. +30 −0 public/422.html
  22. +30 −0 public/500.html
  23. 0  public/favicon.ico
  24. BIN  public/images/rails.png
  25. +49 −0 public/javascripts/application.js
  26. +273 −0 public/javascripts/jquery-ui.js
  27. +541 −0 public/javascripts/jquery.autocomplete.js
  28. +132 −0 public/javascripts/jquery.autogrow.js
  29. +97 −0 public/javascripts/jquery.cookie.js
  30. +12 −0 public/javascripts/jquery.dimensions.min.js
  31. +161 −0 public/javascripts/jquery.dynatree.min.js
  32. +601 −0 public/javascripts/jquery.form.js
  33. +19 −0 public/javascripts/jquery.js
  34. +37 −0 public/javascripts/jquery.json.js
  35. +104 −0 public/javascripts/jquery.localscroll.js
  36. +85 −0 public/javascripts/jquery.mousewheel.js
  37. +150 −0 public/javascripts/jquery.scrollTo.js
  38. +58 −0 public/javascripts/jquery.sprintf.js
  39. +182 −0 public/javascripts/jquery.treeTable.js
  40. +72 −0 public/javascripts/jquery.treeview.async.js
  41. +251 −0 public/javascripts/jquery.treeview.js
  42. +652 −0 public/javascripts/jquery.wysiwyg.js
  43. +34 −0 public/javascripts/parseuri.js
  44. +5 −0 public/robots.txt
  45. +4 −0 script/about
  46. +3 −0  script/console
  47. +3 −0  script/dbconsole
  48. +3 −0  script/destroy
  49. +3 −0  script/generate
  50. +3 −0  script/performance/benchmarker
  51. +3 −0  script/performance/profiler
  52. +3 −0  script/plugin
  53. +3 −0  script/runner
  54. +3 −0  script/server
  55. +1 −0  test/.gitignore
  56. +9 −0 vendor/plugins/haml/init.rb
4 .gitignore
@@ -0,0 +1,4 @@
+*~
+coverage
+*.log
+*.sqlite3
243 README
@@ -0,0 +1,243 @@
+== Welcome to Rails
+
+Rails is a web-application framework that includes everything needed to create
+database-backed web applications according to the Model-View-Control pattern.
+
+This pattern splits the view (also called the presentation) into "dumb" templates
+that are primarily responsible for inserting pre-built data in between HTML tags.
+The model contains the "smart" domain objects (such as Account, Product, Person,
+Post) that holds all the business logic and knows how to persist themselves to
+a database. The controller handles the incoming requests (such as Save New Account,
+Update Product, Show Post) by manipulating the model and directing data to the view.
+
+In Rails, the model is handled by what's called an object-relational mapping
+layer entitled Active Record. This layer allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in
+link:files/vendor/rails/activerecord/README.html.
+
+The controller and view are handled by the Action Pack, which handles both
+layers by its two parts: Action View and Action Controller. These two layers
+are bundled in a single package due to their heavy interdependence. This is
+unlike the relationship between the Active Record and Action Pack that is much
+more separate. Each of these packages can be used independently outside of
+Rails. You can read more about Action Pack in
+link:files/vendor/rails/actionpack/README.html.
+
+
+== Getting Started
+
+1. At the command prompt, start a new Rails application using the <tt>rails</tt> command
+ and your application name. Ex: rails myapp
+2. Change directory into myapp and start the web server: <tt>script/server</tt> (run with --help for options)
+3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!"
+4. Follow the guidelines to start developing your application
+
+
+== Web Servers
+
+By default, Rails will try to use Mongrel if it's are installed when started with script/server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails
+with a variety of other web servers.
+
+Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
+suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
+getting up and running with mongrel is as easy as: <tt>gem install mongrel</tt>.
+More info at: http://mongrel.rubyforge.org
+
+Say other Ruby web servers like Thin and Ebb or regular web servers like Apache or LiteSpeed or
+Lighttpd or IIS. The Ruby web servers are run through Rack and the latter can either be setup to use
+FCGI or proxy to a pack of Mongrels/Thin/Ebb servers.
+
+== Apache .htaccess example for FCGI/CGI
+
+# General Apache options
+AddHandler fastcgi-script .fcgi
+AddHandler cgi-script .cgi
+Options +FollowSymLinks +ExecCGI
+
+# If you don't want Rails to look in certain directories,
+# use the following rewrite rules so that Apache won't rewrite certain requests
+#
+# Example:
+# RewriteCond %{REQUEST_URI} ^/notrails.*
+# RewriteRule .* - [L]
+
+# Redirect all requests not available on the filesystem to Rails
+# By default the cgi dispatcher is used which is very slow
+#
+# For better performance replace the dispatcher with the fastcgi one
+#
+# Example:
+# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
+RewriteEngine On
+
+# If your Rails application is accessed via an Alias directive,
+# then you MUST also set the RewriteBase in this htaccess file.
+#
+# Example:
+# Alias /myrailsapp /path/to/myrailsapp/public
+# RewriteBase /myrailsapp
+
+RewriteRule ^$ index.html [QSA]
+RewriteRule ^([^.]+)$ $1.html [QSA]
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
+
+# In case Rails experiences terminal errors
+# Instead of displaying this message you can supply a file here which will be rendered instead
+#
+# Example:
+# ErrorDocument 500 /500.html
+
+ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
+
+
+== Debugging Rails
+
+Sometimes your application goes wrong. Fortunately there are a lot of tools that
+will help you debug it and get it back on the rails.
+
+First area to check is the application log files. Have "tail -f" commands running
+on the server.log and development.log. Rails will automatically display debugging
+and runtime information to these files. Debugging info will also be shown in the
+browser on requests from 127.0.0.1.
+
+You can also log your own messages directly into the log file from your code using
+the Ruby logger class from inside your controllers. Example:
+
+ class WeblogController < ActionController::Base
+ def destroy
+ @weblog = Weblog.find(params[:id])
+ @weblog.destroy
+ logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
+ end
+ end
+
+The result will be a message in your log file along the lines of:
+
+ Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1
+
+More information on how to use the logger is at http://www.ruby-doc.org/core/
+
+Also, Ruby documentation can be found at http://www.ruby-lang.org/ including:
+
+* The Learning Ruby (Pickaxe) Book: http://www.ruby-doc.org/docs/ProgrammingRuby/
+* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
+
+These two online (and free) books will bring you up to speed on the Ruby language
+and also on programming in general.
+
+
+== Debugger
+
+Debugger support is available through the debugger command when you start your Mongrel or
+Webrick server with --debugger. This means that you can break out of execution at any point
+in the code, investigate and change the model, AND then resume execution!
+You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'
+Example:
+
+ class WeblogController < ActionController::Base
+ def index
+ @posts = Post.find(:all)
+ debugger
+ end
+ end
+
+So the controller will accept the action, run the first line, then present you
+with a IRB prompt in the server window. Here you can do things like:
+
+ >> @posts.inspect
+ => "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
+ #<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
+ >> @posts.first.title = "hello from a debugger"
+ => "hello from a debugger"
+
+...and even better is that you can examine how your runtime objects actually work:
+
+ >> f = @posts.first
+ => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
+ >> f.
+ Display all 152 possibilities? (y or n)
+
+Finally, when you're ready to resume execution, you enter "cont"
+
+
+== Console
+
+You can interact with the domain model by starting the console through <tt>script/console</tt>.
+Here you'll have all parts of the application configured, just like it is when the
+application is running. You can inspect domain models, change values, and save to the
+database. Starting the script without arguments will launch it in the development environment.
+Passing an argument will specify a different environment, like <tt>script/console production</tt>.
+
+To reload your controllers and models after launching the console run <tt>reload!</tt>
+
+== dbconsole
+
+You can go to the command line of your database directly through <tt>script/dbconsole</tt>.
+You would be connected to the database with the credentials defined in database.yml.
+Starting the script without arguments will connect you to the development database. Passing an
+argument will connect you to a different database, like <tt>script/dbconsole production</tt>.
+Currently works for mysql, postgresql and sqlite.
+
+== Description of Contents
+
+app
+ Holds all the code that's specific to this particular application.
+
+app/controllers
+ Holds controllers that should be named like weblogs_controller.rb for
+ automated URL mapping. All controllers should descend from ApplicationController
+ which itself descends from ActionController::Base.
+
+app/models
+ Holds models that should be named like post.rb.
+ Most models will descend from ActiveRecord::Base.
+
+app/views
+ Holds the template files for the view that should be named like
+ weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby
+ syntax.
+
+app/views/layouts
+ Holds the template files for layouts to be used with views. This models the common
+ header/footer method of wrapping views. In your views, define a layout using the
+ <tt>layout :default</tt> and create a file named default.html.erb. Inside default.html.erb,
+ call <% yield %> to render the view using this layout.
+
+app/helpers
+ Holds view helpers that should be named like weblogs_helper.rb. These are generated
+ for you automatically when using script/generate for controllers. Helpers can be used to
+ wrap functionality for your views into methods.
+
+config
+ Configuration files for the Rails environment, the routing map, the database, and other dependencies.
+
+db
+ Contains the database schema in schema.rb. db/migrate contains all
+ the sequence of Migrations for your schema.
+
+doc
+ This directory is where your application documentation will be stored when generated
+ using <tt>rake doc:app</tt>
+
+lib
+ Application specific libraries. Basically, any kind of custom code that doesn't
+ belong under controllers, models, or helpers. This directory is in the load path.
+
+public
+ The directory available for the web server. Contains subdirectories for images, stylesheets,
+ and javascripts. Also contains the dispatchers and the default HTML files. This should be
+ set as the DOCUMENT_ROOT of your web server.
+
+script
+ Helper scripts for automation and generation.
+
+test
+ Unit and functional tests along with fixtures. When using the script/generate scripts, template
+ test files will be generated for you and placed in this directory.
+
+vendor
+ External libraries that the application depends on. Also includes the plugins subdirectory.
+ If the app has frozen rails, those gems also go here, under vendor/rails/.
+ This directory is in the load path.
10 Rakefile
@@ -0,0 +1,10 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require(File.join(File.dirname(__FILE__), 'config', 'boot'))
+
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+require 'tasks/rails'
10 app/controllers/application_controller.rb
@@ -0,0 +1,10 @@
+# Filters added to this controller apply to all controllers in the application.
+# Likewise, all the methods added will be available for all controllers.
+
+class ApplicationController < ActionController::Base
+ helper :all # include all helpers, all the time
+ protect_from_forgery # See ActionController::RequestForgeryProtection for details
+
+ # Scrub sensitive parameters from your log
+ # filter_parameter_logging :password
+end
3  app/helpers/application_helper.rb
@@ -0,0 +1,3 @@
+# Methods added to this helper will be available to all templates in the application.
+module ApplicationHelper
+end
110 config/boot.rb
@@ -0,0 +1,110 @@
+# 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
+ require 'rubygems'
+ min_version = '1.3.1'
+ 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!
22 config/database.yml
@@ -0,0 +1,22 @@
+# SQLite version 3.x
+# gem install sqlite3-ruby (not necessary on OS X Leopard)
+development:
+ adapter: sqlite3
+ database: db/development.sqlite3
+ pool: 5
+ timeout: 5000
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: sqlite3
+ database: db/test.sqlite3
+ pool: 5
+ timeout: 5000
+
+production:
+ adapter: sqlite3
+ database: db/production.sqlite3
+ pool: 5
+ timeout: 5000
41 config/environment.rb
@@ -0,0 +1,41 @@
+# Be sure to restart your server when you modify this file
+
+# Specifies gem version of Rails to use when vendor/rails is not present
+RAILS_GEM_VERSION = '2.3.2' unless defined? RAILS_GEM_VERSION
+
+# Bootstrap the Rails environment, frameworks, and default configuration
+require File.join(File.dirname(__FILE__), 'boot')
+
+Rails::Initializer.run do |config|
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Add additional load paths for your own custom dirs
+ # config.load_paths += %W( #{RAILS_ROOT}/extras )
+
+ # Specify gems that this application depends on and have them installed with rake gems:install
+ # config.gem "bj"
+ # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
+ # config.gem "sqlite3-ruby", :lib => "sqlite3"
+ # config.gem "aws-s3", :lib => "aws/s3"
+
+ # Only load the plugins named here, in the order given (default is alphabetical).
+ # :all can be used as a placeholder for all plugins not explicitly named
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+ # Skip frameworks you're not going to use. To use Rails without a database,
+ # you must remove the Active Record framework.
+ # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
+
+ # Activate observers that should always be running
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names.
+ config.time_zone = 'UTC'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
+ # config.i18n.default_locale = :de
+end
17 config/environments/development.rb
@@ -0,0 +1,17 @@
+# Settings specified here will take precedence over those in config/environment.rb
+
+# In the development environment your application's code is reloaded on
+# every request. This slows down response time but is perfect for development
+# since you don't have to restart the webserver when you make code changes.
+config.cache_classes = false
+
+# Log error messages when you accidentally call methods on nil.
+config.whiny_nils = true
+
+# Show full error reports and disable caching
+config.action_controller.consider_all_requests_local = true
+config.action_view.debug_rjs = true
+config.action_controller.perform_caching = false
+
+# Don't care if the mailer can't send
+config.action_mailer.raise_delivery_errors = false
28 config/environments/production.rb
@@ -0,0 +1,28 @@
+# Settings specified here will take precedence over those in config/environment.rb
+
+# The production environment is meant for finished, "live" apps.
+# Code is not reloaded between requests
+config.cache_classes = true
+
+# Full error reports are disabled and caching is turned on
+config.action_controller.consider_all_requests_local = false
+config.action_controller.perform_caching = true
+config.action_view.cache_template_loading = true
+
+# See everything in the log (default is :info)
+# config.log_level = :debug
+
+# Use a different logger for distributed setups
+# config.logger = SyslogLogger.new
+
+# Use a different cache store in production
+# config.cache_store = :mem_cache_store
+
+# Enable serving of images, stylesheets, and javascripts from an asset server
+# config.action_controller.asset_host = "http://assets.example.com"
+
+# Disable delivery errors, bad email addresses will be ignored
+# config.action_mailer.raise_delivery_errors = false
+
+# Enable threaded mode
+# config.threadsafe!
28 config/environments/test.rb
@@ -0,0 +1,28 @@
+# Settings specified here will take precedence over those in config/environment.rb
+
+# The test environment is used exclusively to run your application's
+# test suite. You never need to work with it otherwise. Remember that
+# your test database is "scratch space" for the test suite and is wiped
+# and recreated between test runs. Don't rely on the data there!
+config.cache_classes = true
+
+# Log error messages when you accidentally call methods on nil.
+config.whiny_nils = true
+
+# Show full error reports and disable caching
+config.action_controller.consider_all_requests_local = true
+config.action_controller.perform_caching = false
+config.action_view.cache_template_loading = true
+
+# Disable request forgery protection in test environment
+config.action_controller.allow_forgery_protection = false
+
+# Tell Action Mailer not to deliver emails to the real world.
+# The :test delivery method accumulates sent emails in the
+# ActionMailer::Base.deliveries array.
+config.action_mailer.delivery_method = :test
+
+# Use SQL instead of Active Record's schema dumper when creating the test database.
+# This is necessary if your schema can't be completely dumped by the schema dumper,
+# like if you have constraints or database-specific column types
+# config.active_record.schema_format = :sql
7 config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
10 config/initializers/inflections.rb
@@ -0,0 +1,10 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
5 config/initializers/mime_types.rb
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register_alias "text/html", :iphone
19 config/initializers/new_rails_defaults.rb
@@ -0,0 +1,19 @@
+# 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
15 config/initializers/session_store.rb
@@ -0,0 +1,15 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key for verifying cookie session data integrity.
+# If you change this key, all old sessions will become invalid!
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+ActionController::Base.session = {
+ :key => '_stackopenflow_session',
+ :secret => '9ac4fd97a52153070a0bd47467c00eded1badf526f145827384ddfde45ac0bfd3f0230c961ddfb9ef84d490b3d889e0169de8eee3ef7b7ed114262824f8aa8aa'
+}
+
+# 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
5 config/locales/en.yml
@@ -0,0 +1,5 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+en:
+ hello: "Hello world"
43 config/routes.rb
@@ -0,0 +1,43 @@
+ActionController::Routing::Routes.draw do |map|
+ # The priority is based upon order of creation: first created -> highest priority.
+
+ # Sample of regular route:
+ # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
+ # Keep in mind you can assign values other than :controller and :action
+
+ # Sample of named route:
+ # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
+ # This route can be invoked with purchase_url(:id => product.id)
+
+ # Sample resource route (maps HTTP verbs to controller actions automatically):
+ # map.resources :products
+
+ # Sample resource route with options:
+ # map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
+
+ # Sample resource route with sub-resources:
+ # map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller
+
+ # Sample resource route with more complex sub-resources
+ # map.resources :products do |products|
+ # products.resources :comments
+ # products.resources :sales, :collection => { :recent => :get }
+ # end
+
+ # Sample resource route within a namespace:
+ # map.namespace :admin do |admin|
+ # # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb)
+ # admin.resources :products
+ # end
+
+ # You can have the root of your site routed with map.root -- just remember to delete public/index.html.
+ # map.root :controller => "welcome"
+
+ # See how all your routes lay out with "rake routes"
+
+ # Install the default routes as the lowest priority.
+ # Note: These default routes make all actions in every controller accessible via GET requests. You should
+ # consider removing the them or commenting them out if you're using named routes and resources.
+ map.connect ':controller/:action/:id'
+ map.connect ':controller/:action/:id.:format'
+end
2  doc/README_FOR_APP
@@ -0,0 +1,2 @@
+Use this README file to introduce your application and point to useful places in the API for learning more.
+Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
30 public/404.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <title>The page you were looking for doesn't exist (404)</title>
+ <style type="text/css">
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+ div.dialog {
+ width: 25em;
+ padding: 0 4em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #ccc;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ }
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ </style>
+</head>
+
+<body>
+ <!-- This file lives in public/404.html -->
+ <div class="dialog">
+ <h1>The page you were looking for doesn't exist.</h1>
+ <p>You may have mistyped the address or the page may have moved.</p>
+ </div>
+</body>
+</html>
30 public/422.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <title>The change you wanted was rejected (422)</title>
+ <style type="text/css">
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+ div.dialog {
+ width: 25em;
+ padding: 0 4em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #ccc;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ }
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ </style>
+</head>
+
+<body>
+ <!-- This file lives in public/422.html -->
+ <div class="dialog">
+ <h1>The change you wanted was rejected.</h1>
+ <p>Maybe you tried to change something you didn't have access to.</p>
+ </div>
+</body>
+</html>
30 public/500.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <title>We're sorry, but something went wrong (500)</title>
+ <style type="text/css">
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+ div.dialog {
+ width: 25em;
+ padding: 0 4em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #ccc;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ }
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ </style>
+</head>
+
+<body>
+ <!-- This file lives in public/500.html -->
+ <div class="dialog">
+ <h1>We're sorry, but something went wrong.</h1>
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
+ </div>
+</body>
+</html>
0  public/favicon.ico
No changes.
BIN  public/images/rails.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 public/javascripts/application.js
@@ -0,0 +1,49 @@
+// Common JavaScript code across your application goes here.
+// Theme
+
+var Theme = {
+ activate: function(name) {
+ window.location.hash = 'themes/' + name
+ Theme.loadCurrent();
+ },
+
+ loadCurrent: function() {
+ var hash = window.location.hash;
+ if (hash.length > 0) {
+ matches = hash.match(/^#themes\/([a-z0-9\-_]+)$/);
+ if (matches && matches.length > 1) {
+ $('#current-theme').attr('href', '/stylesheets/themes/' + matches[1] + '/style.css');
+ } else {
+ alert('theme not valid');
+ }
+ }
+ }
+}
+
+$(document).ready(function() {
+ Theme.loadCurrent();
+ $.localScroll();
+ $('.table :checkbox.toggle').each(function(i, toggle) {
+ $(toggle).change(function(e) {
+ $(toggle).parents('table:first').find(':checkbox:not(.toggle)').each(function(j, checkbox) {
+ checkbox.checked = !checkbox.checked;
+ })
+ });
+ });
+});
+
+$.postJSON = function(url, data, callback) {
+ if(data && data.length > 0)
+ data += "&format=json"
+ else
+ data = "format=json"
+ $.post(url, data, callback, "json");
+};
+
+function renderFlashMessage(message) {
+ $('#flash-messages').html(message);
+}
+
+//
+
+
273 public/javascripts/jquery-ui.js
273 additions, 0 deletions not shown
541 public/javascripts/jquery.autocomplete.js
@@ -0,0 +1,541 @@
+jQuery.autocomplete = function(input, options) {
+ // Create a link to self
+ var me = this;
+
+ // Create jQuery object for input element
+ var $input = $(input).attr("autocomplete", "off");
+
+ // Apply inputClass if necessary
+ if (options.inputClass) {
+ $input.addClass(options.inputClass);
+ }
+
+ // Create results
+ var results = document.createElement("div");
+
+ // Create jQuery object for results
+ // var $results = $(results);
+ var $results = $(results).hide().addClass(options.resultsClass).css("position", "absolute");
+ if( options.width > 0 ) {
+ $results.css("width", options.width);
+ }
+
+ // Add to body element
+ $("body").append(results);
+
+ input.autocompleter = me;
+
+ var timeout = null;
+ var prev = "";
+ var active = -1;
+ var cache = {};
+ var keyb = false;
+ var hasFocus = false;
+ var lastKeyPressCode = null;
+ var mouseDownOnSelect = false;
+ var hidingResults = false;
+
+ // flush cache
+ function flushCache(){
+ cache = {};
+ cache.data = {};
+ cache.length = 0;
+ };
+
+ // flush cache
+ flushCache();
+
+ // if there is a data array supplied
+ if( options.data != null ){
+ var sFirstChar = "", stMatchSets = {}, row = [];
+
+ // no url was specified, we need to adjust the cache length to make sure it fits the local data store
+ if( typeof options.url != "string" ) {
+ options.cacheLength = 1;
+ }
+
+ // loop through the array and create a lookup structure
+ for( var i=0; i < options.data.length; i++ ){
+ // if row is a string, make an array otherwise just reference the array
+ row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]);
+
+ // if the length is zero, don't add to list
+ if( row[0].length > 0 ){
+ // get the first character
+ sFirstChar = row[0].substring(0, 1).toLowerCase();
+ // if no lookup array for this character exists, look it up now
+ if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = [];
+ // if the match is a string
+ stMatchSets[sFirstChar].push(row);
+ }
+ }
+
+ // add the data items to the cache
+ for( var k in stMatchSets ) {
+ // increase the cache size
+ options.cacheLength++;
+ // add to the cache
+ addToCache(k, stMatchSets[k]);
+ }
+ }
+
+ $input
+ .keydown(function(e) {
+ // track last key pressed
+ lastKeyPressCode = e.keyCode;
+ switch(e.keyCode) {
+ case 38: // up
+ e.preventDefault();
+ moveSelect(-1);
+ break;
+ case 40: // down
+ e.preventDefault();
+ moveSelect(1);
+ break;
+ case 9: // tab
+ case 13: // return
+ if( selectCurrent() ){
+ // make sure to blur off the current field
+ $input.get(0).blur();
+ e.preventDefault();
+ }
+ break;
+ default:
+ active = -1;
+ if (timeout) clearTimeout(timeout);
+ timeout = setTimeout(function(){onChange();}, options.delay);
+ break;
+ }
+ })
+ .focus(function(){
+ // track whether the field has focus, we shouldn't process any results if the field no longer has focus
+ hasFocus = true;
+ })
+ .blur(function() {
+ // track whether the field has focus
+ hasFocus = false;
+ if (!mouseDownOnSelect) {
+ hideResults();
+ }
+ });
+
+ hideResultsNow();
+
+ function onChange() {
+ // ignore if the following keys are pressed: [del] [shift] [capslock]
+ if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide();
+ var v = $input.val();
+ if (v == prev) return;
+ prev = v;
+ if (v.length >= options.minChars) {
+ $input.addClass(options.loadingClass);
+ requestData(v);
+ } else {
+ $input.removeClass(options.loadingClass);
+ $results.hide();
+ }
+ };
+
+ function moveSelect(step) {
+
+ var lis = $("li", results);
+ if (!lis) return;
+
+ active += step;
+
+ if (active < 0) {
+ active = 0;
+ } else if (active >= lis.size()) {
+ active = lis.size() - 1;
+ }
+
+ lis.removeClass("ac_over");
+
+ $(lis[active]).addClass("ac_over");
+
+ // Weird behaviour in IE
+ // if (lis[active] && lis[active].scrollIntoView) {
+ // lis[active].scrollIntoView(false);
+ // }
+
+ };
+
+ function selectCurrent() {
+ var li = $("li.ac_over", results)[0];
+ if (!li) {
+ var $li = $("li", results);
+ if (options.selectOnly) {
+ if ($li.length == 1) li = $li[0];
+ } else if (options.selectFirst) {
+ li = $li[0];
+ }
+ }
+ if (li) {
+ selectItem(li);
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ function selectItem(li) {
+ if (!li) {
+ li = document.createElement("li");
+ li.extra = [];
+ li.selectValue = "";
+ }
+ var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
+ input.lastSelected = v;
+ prev = v;
+ $results.html("");
+ $input.val(v);
+ hideResultsNow();
+ if (options.onItemSelect) {
+ setTimeout(function() { options.onItemSelect(li) }, 1);
+ }
+ };
+
+ // selects a portion of the input string
+ function createSelection(start, end){
+ // get a reference to the input element
+ var field = $input.get(0);
+ if( field.createTextRange ){
+ var selRange = field.createTextRange();
+ selRange.collapse(true);
+ selRange.moveStart("character", start);
+ selRange.moveEnd("character", end);
+ selRange.select();
+ } else if( field.setSelectionRange ){
+ field.setSelectionRange(start, end);
+ } else {
+ if( field.selectionStart ){
+ field.selectionStart = start;
+ field.selectionEnd = end;
+ }
+ }
+ field.focus();
+ };
+
+ // fills in the input box w/the first match (assumed to be the best match)
+ function autoFill(sValue){
+ // if the last user key pressed was backspace, don't autofill
+ if( lastKeyPressCode != 8 ){
+ // fill in the value (keep the case the user has typed)
+ $input.val($input.val() + sValue.substring(prev.length));
+ // select the portion of the value not typed by the user (so the next character will erase)
+ createSelection(prev.length, sValue.length);
+ }
+ };
+
+ function showResults() {
+ // get the position of the input field right now (in case the DOM is shifted)
+ var pos = findPos(input);
+ // either use the specified width, or autocalculate based on form element
+ var iWidth = (options.width > 0) ? options.width : $input.width();
+ // reposition
+ $results.css({
+ width: parseInt(iWidth) + "px",
+ top: (pos.y + input.offsetHeight) + "px",
+ left: pos.x + "px"
+ }).show();
+ };
+
+ function hideResults() {
+ if (timeout) clearTimeout(timeout);
+ timeout = setTimeout(hideResultsNow, 200);
+ };
+
+ function hideResultsNow() {
+ if (hidingResults) {
+ return;
+ }
+ hidingResults = true;
+
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+
+ var v = $input.removeClass(options.loadingClass).val();
+
+ if ($results.is(":visible")) {
+ $results.hide();
+ }
+
+ if (options.mustMatch) {
+ if (!input.lastSelected || input.lastSelected != v) {
+ selectItem(null);
+ }
+ }
+
+ hidingResults = false;
+ };
+
+ function receiveData(q, data) {
+ if (data) {
+ $input.removeClass(options.loadingClass);
+ results.innerHTML = "";
+
+ // if the field no longer has focus or if there are no matches, do not display the drop down
+ if( !hasFocus || data.length == 0 ) return hideResultsNow();
+
+ if ($.browser.msie) {
+ // we put a styled iframe behind the calendar so HTML SELECT elements don't show through
+ $results.append(document.createElement('iframe'));
+ }
+ results.appendChild(dataToDom(data));
+ // autofill in the complete box w/the first match as long as the user hasn't entered in more data
+ if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);
+ showResults();
+ } else {
+ hideResultsNow();
+ }
+ };
+
+ function parseData(data) {
+ if (!data) return null;
+ var parsed = [];
+ var rows = data.split(options.lineSeparator);
+ for (var i=0; i < rows.length; i++) {
+ var row = $.trim(rows[i]);
+ if (row) {
+ parsed[parsed.length] = row.split(options.cellSeparator);
+ }
+ }
+ return parsed;
+ };
+
+ function dataToDom(data) {
+ var ul = document.createElement("ul");
+ var num = data.length;
+
+ // limited results to a max number
+ if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;
+
+ for (var i=0; i < num; i++) {
+ var row = data[i];
+ if (!row) continue;
+ var li = document.createElement("li");
+ if (options.formatItem) {
+ li.innerHTML = options.formatItem(row, i, num);
+ li.selectValue = row[0];
+ } else {
+ li.innerHTML = row[0];
+ li.selectValue = row[0];
+ }
+ var extra = null;
+ if (row.length > 1) {
+ extra = [];
+ for (var j=1; j < row.length; j++) {
+ extra[extra.length] = row[j];
+ }
+ }
+ li.extra = extra;
+ ul.appendChild(li);
+
+ $(li).hover(
+ function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); },
+ function() { $(this).removeClass("ac_over"); }
+ ).click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ selectItem(this)
+ });
+
+ }
+ $(ul).mousedown(function() {
+ mouseDownOnSelect = true;
+ }).mouseup(function() {
+ mouseDownOnSelect = false;
+ });
+ return ul;
+ };
+
+ function requestData(q) {
+ if (!options.matchCase) q = q.toLowerCase();
+ var data = options.cacheLength ? loadFromCache(q) : null;
+ // recieve the cached data
+ if (data) {
+ receiveData(q, data);
+ // if an AJAX url has been supplied, try loading the data now
+ } else if( (typeof options.url == "string") && (options.url.length > 0) ){
+ $.get(makeUrl(q), function(data) {
+ data = parseData(data);
+ addToCache(q, data);
+ receiveData(q, data);
+ });
+ // if there's been no data found, remove the loading class
+ } else {
+ $input.removeClass(options.loadingClass);
+ }
+ };
+
+ function makeUrl(q) {
+ var sep = options.url.indexOf('?') == -1 ? '?' : '&';
+ var url = options.url + sep + "q=" + encodeURI(q);
+ for (var i in options.extraParams) {
+ url += "&" + i + "=" + encodeURI(options.extraParams[i]);
+ }
+ return url;
+ };
+
+ function loadFromCache(q) {
+ if (!q) return null;
+ if (cache.data[q]) return cache.data[q];
+ if (options.matchSubset) {
+ for (var i = q.length - 1; i >= options.minChars; i--) {
+ var qs = q.substr(0, i);
+ var c = cache.data[qs];
+ if (c) {
+ var csub = [];
+ for (var j = 0; j < c.length; j++) {
+ var x = c[j];
+ var x0 = x[0];
+ if (matchSubset(x0, q)) {
+ csub[csub.length] = x;
+ }
+ }
+ return csub;
+ }
+ }
+ }
+ return null;
+ };
+
+ function matchSubset(s, sub) {
+ if (!options.matchCase) s = s.toLowerCase();
+ var i = s.indexOf(sub);
+ if (i == -1) return false;
+ return i == 0 || options.matchContains;
+ };
+
+ this.flushCache = function() {
+ flushCache();
+ };
+
+ this.setExtraParams = function(p) {
+ options.extraParams = p;
+ };
+
+ this.findValue = function(){
+ var q = $input.val();
+
+ if (!options.matchCase) q = q.toLowerCase();
+ var data = options.cacheLength ? loadFromCache(q) : null;
+ if (data) {
+ findValueCallback(q, data);
+ } else if( (typeof options.url == "string") && (options.url.length > 0) ){
+ $.get(makeUrl(q), function(data) {
+ data = parseData(data)
+ addToCache(q, data);
+ findValueCallback(q, data);
+ });
+ } else {
+ // no matches
+ findValueCallback(q, null);
+ }
+ }
+
+ function findValueCallback(q, data){
+ if (data) $input.removeClass(options.loadingClass);
+
+ var num = (data) ? data.length : 0;
+ var li = null;
+
+ for (var i=0; i < num; i++) {
+ var row = data[i];
+
+ if( row[0].toLowerCase() == q.toLowerCase() ){
+ li = document.createElement("li");
+ if (options.formatItem) {
+ li.innerHTML = options.formatItem(row, i, num);
+ li.selectValue = row[0];
+ } else {
+ li.innerHTML = row[0];
+ li.selectValue = row[0];
+ }
+ var extra = null;
+ if( row.length > 1 ){
+ extra = [];
+ for (var j=1; j < row.length; j++) {
+ extra[extra.length] = row[j];
+ }
+ }
+ li.extra = extra;
+ }
+ }
+
+ if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1);
+ }
+
+ function addToCache(q, data) {
+ if (!data || !q || !options.cacheLength) return;
+ if (!cache.length || cache.length > options.cacheLength) {
+ flushCache();
+ cache.length++;
+ } else if (!cache[q]) {
+ cache.length++;
+ }
+ cache.data[q] = data;
+ };
+
+ function findPos(obj) {
+ var curleft = obj.offsetLeft || 0;
+ var curtop = obj.offsetTop || 0;
+ while (obj = obj.offsetParent) {
+ curleft += obj.offsetLeft
+ curtop += obj.offsetTop
+ }
+ return {x:curleft,y:curtop};
+ }
+}
+
+jQuery.fn.autocomplete = function(url, options, data) {
+ // Make sure options exists
+ options = options || {};
+ // Set url as option
+ options.url = url;
+ // set some bulk local data
+ options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;
+
+ // Set default values for required options
+ options = $.extend({
+ inputClass: "ac_input",
+ resultsClass: "ac_results",
+ lineSeparator: "\n",
+ cellSeparator: "|",
+ minChars: 1,
+ delay: 400,
+ matchCase: 0,
+ matchSubset: 1,
+ matchContains: 0,
+ cacheLength: 1,
+ mustMatch: 0,
+ extraParams: {},
+ loadingClass: "ac_loading",
+ selectFirst: false,
+ selectOnly: false,
+ maxItemsToShow: -1,
+ autoFill: false,
+ width: 0
+ }, options);
+ options.width = parseInt(options.width, 10);
+
+ this.each(function() {
+ var input = this;
+ new jQuery.autocomplete(input, options);
+ });
+
+ // Don't break the chain
+ return this;
+}
+
+jQuery.fn.autocompleteArray = function(data, options) {
+ return this.autocomplete(null, options, data);
+}
+
+jQuery.fn.indexOf = function(e){
+ for( var i=0; i<this.length; i++ ){
+ if( this[i] == e ) return i;
+ }
+ return -1;
+};
132 public/javascripts/jquery.autogrow.js
@@ -0,0 +1,132 @@
+/*
+ * Auto Expanding Text Area (1.2.2)
+ * by Chrys Bader (www.chrysbader.com)
+ * chrysb@gmail.com
+ *
+ * Special thanks to:
+ * Jake Chapa - jake@hybridstudio.com
+ * John Resig - jeresig@gmail.com
+ *
+ * Copyright (c) 2008 Chrys Bader (www.chrysbader.com)
+ * Licensed under the GPL (GPL-LICENSE.txt) license.
+ *
+ *
+ * NOTE: This script requires jQuery to work. Download jQuery at www.jquery.com
+ *
+ */
+
+(function(jQuery) {
+
+ var self = null;
+
+ jQuery.fn.autogrow = function(o)
+ {
+ return this.each(function() {
+ new jQuery.autogrow(this, o);
+ });
+ };
+
+
+ /**
+ * The autogrow object.
+ *
+ * @constructor
+ * @name jQuery.autogrow
+ * @param Object e The textarea to create the autogrow for.
+ * @param Hash o A set of key/value pairs to set as configuration properties.
+ * @cat Plugins/autogrow
+ */
+
+ jQuery.autogrow = function (e, o)
+ {
+ this.options = o || {};
+ this.dummy = null;
+ this.interval = null;
+ this.line_height = this.options.lineHeight || parseInt(jQuery(e).css('line-height'));
+ this.min_height = this.options.minHeight || parseInt(jQuery(e).css('min-height'));
+ this.max_height = this.options.maxHeight || parseInt(jQuery(e).css('max-height'));;
+ this.textarea = jQuery(e);
+
+ if(this.line_height == NaN)
+ this.line_height = 0;
+
+ // Only one textarea activated at a time, the one being used
+ this.init();
+ };
+
+ jQuery.autogrow.fn = jQuery.autogrow.prototype = {
+ autogrow: '1.2.2'
+ };
+
+ jQuery.autogrow.fn.extend = jQuery.autogrow.extend = jQuery.extend;
+
+ jQuery.autogrow.fn.extend({
+
+ init: function() {
+ var self = this;
+ this.textarea.css({overflow: 'hidden', display: 'block'});
+ this.textarea.bind('focus', function() { self.startExpand() } ).bind('blur', function() { self.stopExpand() });
+ this.checkExpand();
+ },
+
+ startExpand: function() {
+ var self = this;
+ this.interval = window.setInterval(function() {self.checkExpand()}, 400);
+ },
+
+ stopExpand: function() {
+ clearInterval(this.interval);
+ },
+
+ checkExpand: function() {
+
+ if (this.dummy == null)
+ {
+ this.dummy = jQuery('<div></div>');
+ this.dummy.css({
+ 'font-size' : this.textarea.css('font-size'),
+ 'font-family': this.textarea.css('font-family'),
+ 'width' : this.textarea.css('width'),
+ 'padding' : this.textarea.css('padding'),
+ 'line-height': this.line_height + 'px',
+ 'overflow-x' : 'hidden',
+ 'position' : 'absolute',
+ 'top' : 0,
+ 'left' : -9999
+ }).appendTo('body');
+ }
+
+ // Strip HTML tags
+ var html = this.textarea.val().replace(/(<|>)/g, '');
+
+ // IE is different, as per usual
+ if ($.browser.msie)
+ {
+ html = html.replace(/\n/g, '<BR>new');
+ }
+ else
+ {
+ html = html.replace(/\n/g, '<br>new');
+ }
+
+ if (this.dummy.html() != html)
+ {
+ this.dummy.html(html);
+
+ if (this.max_height > 0 && (this.dummy.height() + this.line_height > this.max_height))
+ {
+ this.textarea.css('overflow-y', 'auto');
+ }
+ else
+ {
+ this.textarea.css('overflow-y', 'hidden');
+ if (this.textarea.height() < this.dummy.height() + this.line_height || (this.dummy.height() < this.textarea.height()))
+ {
+ this.textarea.animate({height: (this.dummy.height() + this.line_height) + 'px'}, 100);
+ }
+ }
+ }
+ }
+
+ });
+})(jQuery);
97 public/javascripts/jquery.cookie.js
@@ -0,0 +1,97 @@
+/**
+ * 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. Keep in mind that you have to use the same path and domain
+ * used when the cookie was set.
+ *
+ * @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 = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
+ 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
+ }
+ // NOTE Needed to parenthesize options.path and options.domain
+ // in the following expressions, otherwise they evaluate to undefined
+ // in the packed version for some reason...
+ 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;
+ }
+};
12 public/javascripts/jquery.dimensions.min.js
@@ -0,0 +1,12 @@
+/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-12-20 08:43:48 -0600 (Thu, 20 Dec 2007) $
+ * $Rev: 4257 $
+ *
+ * Version: 1.2
+ *
+ * Requires: jQuery 1.2+
+ */
+(function($){$.dimensions={version:'1.2'};$.each(['Height','Width'],function(i,name){$.fn['inner'+name]=function(){if(!this[0])return;var torl=name=='Height'?'Top':'Left',borr=name=='Height'?'Bottom':'Right';return this.is(':visible')?this[0]['client'+name]:num(this,name.toLowerCase())+num(this,'padding'+torl)+num(this,'padding'+borr);};$.fn['outer'+name]=function(options){if(!this[0])return;var torl=name=='Height'?'Top':'Left',borr=name=='Height'?'Bottom':'Right';options=$.extend({margin:false},options||{});var val=this.is(':visible')?this[0]['offset'+name]:num(this,name.toLowerCase())+num(this,'border'+torl+'Width')+num(this,'border'+borr+'Width')+num(this,'padding'+torl)+num(this,'padding'+borr);return val+(options.margin?(num(this,'margin'+torl)+num(this,'margin'+borr)):0);};});$.each(['Left','Top'],function(i,name){$.fn['scroll'+name]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(name=='Left'?val:$(window)['scrollLeft'](),name=='Top'?val:$(window)['scrollTop']()):this['scroll'+name]=val;}):this[0]==window||this[0]==document?self[(name=='Left'?'pageXOffset':'pageYOffset')]||$.boxModel&&document.documentElement['scroll'+name]||document.body['scroll'+name]:this[0]['scroll'+name];};});$.fn.extend({position:function(){var left=0,top=0,elem=this[0],offset,parentOffset,offsetParent,results;if(elem){offsetParent=this.offsetParent();offset=this.offset();parentOffset=offsetParent.offset();offset.top-=num(elem,'marginTop');offset.left-=num(elem,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&$.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return $(offsetParent);}});function num(el,prop){return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;};})(jQuery);
161 public/javascripts/jquery.dynatree.min.js
@@ -0,0 +1,161 @@
+// jquery.dynatree.js build 0.4.2
+// Revision: 216, date: 2009-04-19 08:08:47
+// Copyright (c) 2008-09 Martin Wendt (http://dynatree.googlecode.com/)
+// Licensed under the MIT License.
+
+var _canLog=true;function _log(mode,msg){if(!_canLog)
+return;var args=Array.prototype.slice.apply(arguments,[1]);var dt=new Date();var tag=dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds()+"."+dt.getMilliseconds();args[0]=tag+" - "+args[0];try{switch(mode){case"info":window.console.info.apply(window.console,args);break;case"warn":window.console.warn.apply(window.console,args);break;default:window.console.log.apply(window.console,args);}}catch(e){if(!window.console)
+_canLog=false;}}
+function logMsg(msg){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments);}
+var DTNodeStatus_Error=-1;var DTNodeStatus_Loading=1;var DTNodeStatus_Ok=0;;(function($){var Class={create:function(){return function(){this.initialize.apply(this,arguments);}}}
+var DynaTreeNode=Class.create();DynaTreeNode.prototype={initialize:function(parent,tree,data){this.parent=parent;this.tree=tree;if(typeof data=="string")
+data={title:data};if(data.key==undefined)
+data.key="_"+tree._nodeCount++;this.data=$.extend({},$.ui.dynatree.nodedatadefaults,data);this.div=null;this.span=null;this.childList=null;this.isRead=false;this.hasSubSel=false;if(tree.initMode=="cookie"){if(tree.initActiveKey==this.data.key)
+tree.activeNode=this;if(tree.initFocusKey==this.data.key)
+tree.focusNode=this;this.bExpanded=($.inArray(this.data.key,tree.initExpandedKeys)>=0);this.bSelected=($.inArray(this.data.key,tree.initSelectedKeys)>=0);}else{if(data.activate)
+tree.activeNode=this;if(data.focus)
+tree.focusNode=this;this.bExpanded=(data.expand==true);this.bSelected=(data.select==true);}
+if(this.bExpanded)
+tree.expandedNodes.push(this);if(this.bSelected)
+tree.selectedNodes.push(this);},toString:function(){return"dtnode<"+this.data.key+">: '"+this.data.title+"'";},toDict:function(recursive,callback){var dict=$.extend({},this.data);dict.activate=(this.tree.activeNode===this);dict.focus=(this.tree.focusNode===this);dict.expand=this.bExpanded;dict.select=this.bSelected;if(callback)
+callback(dict);if(recursive&&this.childList){dict.children=[];for(var i=0;i<this.childList.length;i++)
+dict.children.push(this.childList[i].toDict(true,callback));}else{delete dict.children;}
+return dict;},_getInnerHtml:function(){var opts=this.tree.options;var cache=this.tree.cache;var rootParent=opts.rootVisible?null:this.tree.tnRoot;var bHideFirstExpander=(opts.rootVisible&&opts.minExpandLevel>0)||opts.minExpandLevel>1;var bHideFirstConnector=opts.rootVisible||opts.minExpandLevel>0;var res="";var p=this.parent;while(p){if(bHideFirstConnector&&(p==rootParent))
+break;res=(p.isLastSibling()?cache.tagEmpty:cache.tagVline)+res;p=p.parent;}
+if(bHideFirstExpander&&this.parent==rootParent){}else if(this.childList||this.data.isLazy){res+=cache.tagExpander;}else{res+=cache.tagConnector;}
+if(opts.checkbox&&this.data.hideCheckbox!=true&&!this.data.isStatusNode){res+=cache.tagCheckbox;}
+if(this.data.icon){res+="<img src='"+opts.imagePath+this.data.icon+"' alt='' />";}else if(this.data.icon==false){}else{res+=cache.tagNodeIcon;}
+var tooltip=(this.data&&typeof this.data.tooltip=="string")?" title='"+this.data.tooltip+"'":"";res+="<a href='#'"+tooltip+">"+this.data.title+"</a>";return res;},render:function(bDeep,bHidden){if(!this.div){this.span=document.createElement("span");this.span.dtnode=this;if(this.data.key)
+this.span.id=this.tree.options.idPrefix+this.data.key;this.div=document.createElement("div");this.div.appendChild(this.span);if(this.parent)
+this.parent.div.appendChild(this.div);if(this.parent==null&&!this.tree.options.rootVisible)
+this.span.style.display="none";}
+this.span.innerHTML=this._getInnerHtml();this.div.style.display=(this.parent==null||this.parent.bExpanded?"":"none");var opts=this.tree.options;var cn=opts.classNames;var isLastSib=this.isLastSibling();var cnList=[];cnList.push((this.data.isFolder)?cn.folder:cn.document);if(this.bExpanded)
+cnList.push(cn.expanded);if(this.data.isLazy&&!this.isRead)
+cnList.push(cn.lazy);if(isLastSib)
+cnList.push(cn.lastsib);if(this.bSelected)
+cnList.push(cn.selected);if(this.hasSubSel)
+cnList.push(cn.partsel);if(this.tree.activeNode===this)
+cnList.push(cn.active);if(this.data.addClass)
+cnList.push(this.data.addClass);cnList.push(cn.combinedExpanderPrefix
++(this.bExpanded?"e":"c")
++(this.data.isLazy&&!this.isRead?"d":"")
++(isLastSib?"l":""));cnList.push(cn.combinedIconPrefix
++(this.bExpanded?"e":"c")
++(this.data.isFolder?"f":""));this.span.className=cnList.join(" ");if(bDeep&&this.childList&&(bHidden||this.bExpanded)){for(var i=0;i<this.childList.length;i++){this.childList[i].render(bDeep,bHidden)}}},hasChildren:function(){return this.childList!=null;},isLastSibling:function(){var p=this.parent;if(!p)return true;return p.childList[p.childList.length-1]===this;},prevSibling:function(){if(!this.parent)return null;var ac=this.parent.childList;for(var i=1;i<ac.length;i++)
+if(ac[i]===this)
+return ac[i-1];return null;},nextSibling:function(){if(!this.parent)return null;var ac=this.parent.childList;for(var i=0;i<ac.length-1;i++)
+if(ac[i]===this)
+return ac[i+1];return null;},_setStatusNode:function(data){var firstChild=(this.childList?this.childList[0]:null);if(!data){if(firstChild){this.div.removeChild(firstChild.div);if(this.childList.length==1)
+this.childList=null;else
+this.childList.shift();}}else if(firstChild){data.isStatusNode=true;firstChild.data=data;firstChild.render(false,false);}else{data.isStatusNode=true;firstChild=this._addNode(data);}},setLazyNodeStatus:function(lts){switch(lts){case DTNodeStatus_Ok:this._setStatusNode(null);this.isRead=true;this.render(false,false);if(this.tree.options.autoFocus){if(this===this.tree.tnRoot&&!this.tree.options.rootVisible&&this.childList){this.childList[0].focus();}else{this.focus();}}
+break;case DTNodeStatus_Loading:this._setStatusNode({title:this.tree.options.strings.loading,addClass:this.tree.options.classNames.nodeWait});break;case DTNodeStatus_Error:this._setStatusNode({title:this.tree.options.strings.loadError,addClass:this.tree.options.classNames.nodeError});break;default:throw"Bad LazyNodeStatus: '"+lts+"'.";}},_parentList:function(includeRoot,includeSelf){var l=[];var dtn=includeSelf?this:this.parent;while(dtn){if(includeRoot||dtn.parent)
+l.unshift(dtn);dtn=dtn.parent;};return l;},getLevel:function(){var level=0;var dtn=this.parent;while(dtn){level++;dtn=dtn.parent;};return level;},isVisible:function(){var parents=this._parentList(true,false);for(var i=0;i<parents.length;i++)
+if(!parents[i].bExpanded)return false;return true;},makeVisible:function(){var parents=this._parentList(true,false);for(var i=0;i<parents.length;i++)
+parents[i]._expand(true);},focus:function(){this.makeVisible();try{$(this.span).find(">a").focus();}catch(e){}},isActive:function(){return(this.tree.activeNode===this);},activate:function(){var opts=this.tree.options;if(this.data.isStatusNode)
+return;if(opts.onQueryActivate&&opts.onQueryActivate.call(this.span,true,this)==false)
+return;if(this.tree.activeNode){if(this.tree.activeNode===this)
+return;this.tree.activeNode.deactivate();}
+if(opts.activeVisible)
+this.makeVisible();this.tree.activeNode=this;if(opts.persist)
+$.cookie(opts.cookieId+"-active",this.data.key,opts.cookie);$(this.span).addClass(opts.classNames.active);if(opts.onActivate)
+opts.onActivate.call(this.span,this);},deactivate:function(){if(this.tree.activeNode===this){var opts=this.tree.options;if(opts.onQueryActivate&&opts.onQueryActivate.call(this.span,false,this)==false)
+return;$(this.span).removeClass(opts.classNames.active);if(opts.persist){$.cookie(opts.cookieId+"-active","",opts.cookie);}
+this.tree.activeNode=null;if(opts.onDeactivate)
+opts.onDeactivate.call(this.span,this);}},_userActivate:function(){var activate=true;var expand=false;if(this.data.isFolder){switch(this.tree.options.clickFolderMode){case 2:activate=false;expand=true;break;case 3:activate=expand=true;break;}}
+if(this.parent==null&&this.tree.options.minExpandLevel>0){expand=false;}
+if(expand){this.toggleExpand();this.focus();}
+if(activate){this.activate();}},_setSubSel:function(hasSubSel){if(hasSubSel){this.hasSubSel=true;$(this.span).addClass(this.tree.options.classNames.partsel);}else{this.hasSubSel=false;$(this.span).removeClass(this.tree.options.classNames.partsel);}},_fixSelectionState:function(){if(this.bSelected){this.visit(function(dtnode){dtnode.parent._setSubSel(true);dtnode._select(true,false,false);});var p=this.parent;while(p){p._setSubSel(true);var allChildsSelected=true;for(var i=0;i<p.childList.length;i++){var n=p.childList[i];if(!n.bSelected&&!n.data.isStatusNode){allChildsSelected=false;break;}}
+if(allChildsSelected)
+p._select(true,false,false);p=p.parent;}}else{this._setSubSel(false);this.visit(function(dtnode){dtnode._setSubSel(false);dtnode._select(false,false,false);});var p=this.parent;while(p){p._select(false,false,false);var isPartSel=false;for(var i=0;i<p.childList.length;i++){if(p.childList[i].bSelected||p.childList[i].hasSubSel){isPartSel=true;break;}}
+p._setSubSel(isPartSel);p=p.parent;}}},_select:function(sel,fireEvents,deep){var opts=this.tree.options;if(this.data.isStatusNode)
+return;if(this.bSelected==sel){return;}
+if(fireEvents&&opts.onQuerySelect&&opts.onQuerySelect.call(this.span,sel,this)==false)
+return;if(opts.selectMode==1&&this.tree.selectedNodes.length&&sel)
+this.tree.selectedNodes[0]._select(false,false,false);this.bSelected=sel;this.tree._changeNodeList("select",this,sel);if(sel){$(this.span).addClass(opts.classNames.selected);if(deep&&opts.selectMode==3)
+this._fixSelectionState();if(fireEvents&&opts.onSelect)
+opts.onSelect.call(this.span,true,this);}else{$(this.span).removeClass(opts.classNames.selected);if(deep&&opts.selectMode==3)
+this._fixSelectionState();if(fireEvents&&opts.onSelect)
+opts.onSelect.call(this.span,false,this);}},isSelected:function(){return this.bSelected;},select:function(sel){return this._select(sel!=false,true,true);},toggleSelect:function(){return this.select(!this.bSelected);},_expand:function(bExpand){if(this.bExpanded==bExpand){return;}
+var opts=this.tree.options;if(!bExpand&&this.getLevel()<opts.minExpandLevel){this.tree.logDebug("dtnode._expand(%o) forced expand - %o",bExpand,this);return;}
+if(opts.onQueryExpand&&opts.onQueryExpand.call(this.span,bExpand,this)==false)
+return;this.bExpanded=bExpand;this.tree._changeNodeList("expand",this,bExpand);this.render(false);if(this.bExpanded&&this.parent&&opts.autoCollapse){var parents=this._parentList(false,true);for(var i=0;i<parents.length;i++)
+parents[i].collapseSiblings();}
+if(opts.activeVisible&&this.tree.activeNode&&!this.tree.activeNode.isVisible()){this.tree.activeNode.deactivate();}
+if(bExpand&&this.data.isLazy&&!this.isRead){try{this.tree.logDebug("_expand: start lazy - %o",this);this.setLazyNodeStatus(DTNodeStatus_Loading);if(true==opts.onLazyRead.call(this.span,this)){this.setLazyNodeStatus(DTNodeStatus_Ok);this.tree.logDebug("_expand: lazy succeeded - %o",this);}}catch(e){this.setLazyNodeStatus(DTNodeStatus_Error);}
+return;}
+if(opts.fx){var duration=opts.fx.duration||200;$(">DIV",this.div).animate(opts.fx,duration);}else{var $d=$(">DIV",this.div);$d.toggle();}
+if(opts.onExpand)
+opts.onExpand.call(this.span,bExpand,this);},expand:function(flag){if(!this.childList&&!this.data.isLazy&&flag)
+return;if(this.parent==null&&this.tree.options.minExpandLevel>0&&!flag)
+return;this._expand(flag);},toggleExpand:function(){this.expand(!this.bExpanded);},collapseSiblings:function(){if(this.parent==null)
+return;var ac=this.parent.childList;for(var i=0;i<ac.length;i++){if(ac[i]!==this&&ac[i].bExpanded)
+ac[i]._expand(false);}},onClick:function(event){if($(event.target).hasClass(this.tree.options.classNames.expander)){this.toggleExpand();}else if($(event.target).hasClass(this.tree.options.classNames.checkbox)){this.toggleSelect();}else{this._userActivate();this.span.getElementsByTagName("a")[0].focus();}
+return false;},onDblClick:function(event){},onKeydown:function(event){var handled=true;switch(event.which){case 107:case 187:if(!this.bExpanded)this.toggleExpand();break;case 109:case 189:if(this.bExpanded)this.toggleExpand();break;case 32:this._userActivate();break;case 8:if(this.parent)
+this.parent.focus();break;case 37:if(this.bExpanded){this.toggleExpand();this.focus();}else if(this.parent&&(this.tree.options.rootVisible||this.parent.parent)){this.parent.focus();}
+break;case 39:if(!this.bExpanded&&(this.childList||this.data.isLazy)){this.toggleExpand();this.focus();}else if(this.childList){this.childList[0].focus();}
+break;case 38:var sib=this.prevSibling();while(sib&&sib.bExpanded)
+sib=sib.childList[sib.childList.length-1];if(!sib&&this.parent&&(this.tree.options.rootVisible||this.parent.parent))
+sib=this.parent;if(sib)sib.focus();break;case 40:var sib;if(this.bExpanded){sib=this.childList[0];}else{var parents=this._parentList(false,true);for(var i=parents.length-1;i>=0;i--){sib=parents[i].nextSibling();if(sib)break;}}
+if(sib)sib.focus();break;default:handled=false;}
+return!handled;},onKeypress:function(event){},onFocus:function(event){var opts=this.tree.options;if(event.type=="blur"||event.type=="focusout"){if(opts.onBlur)
+opts.onBlur.call(this.span,this);if(this.tree.tnFocused)
+$(this.tree.tnFocused.span).removeClass(opts.classNames.focused);this.tree.tnFocused=null;if(opts.persist){$.cookie(opts.cookieId+"-focus",null,$.extend({},opts.cookie));}}else if(event.type=="focus"||event.type=="focusin"){if(this.tree.tnFocused&&this.tree.tnFocused!==this){this.tree.logDebug("dtnode.onFocus: out of sync: curFocus: %o",this.tree.tnFocused);$(this.tree.tnFocused.span).removeClass(opts.classNames.focused);}
+this.tree.tnFocused=this;if(opts.onFocus)
+opts.onFocus.call(this.span,this);$(this.tree.tnFocused.span).addClass(opts.classNames.focused);if(opts.persist)
+$.cookie(opts.cookieId+"-focus",this.data.key,opts.cookie);}},_postInit:function(){if(opts.onPostInit)
+opts.onPostInit.call(this.span,this);},visit:function(fn,data,includeSelf){var n=0;if(includeSelf==true){if(fn(this,data)==false)
+return 1;n++;}
+if(this.childList)
+for(var i=0;i<this.childList.length;i++)
+n+=this.childList[i].visit(fn,data,true);return n;},remove:function(){if(this===this.tree.root)
+return false;return this.parent.removeChild(this);},removeChild:function(tn){var ac=this.childList;if(ac.length==1){if(tn!==ac[0])
+throw"removeChild: invalid child";return this.removeChildren();}
+if(tn===this.tree.activeNode)
+tn.deactivate();if(tn.bSelected)
+this.tree._changeNodeList("select",tn,false);if(tn.bExpanded)
+this.tree._changeNodeList("expand",tn,false);tn.removeChildren(true);this.div.removeChild(tn.div);for(var i=0;i<ac.length;i++){if(ac[i]===tn){this.childList.splice(i,1);delete tn;break;}}},removeChildren:function(recursive){var tree=this.tree;var ac=this.childList;if(ac){for(var i=0;i<ac.length;i++){var tn=ac[i];if(tn===tree.activeNode)
+tn.deactivate();if(tn.bSelected)
+this.tree._changeNodeList("select",tn,false);if(tn.bExpanded)
+this.tree._changeNodeList("expand",tn,false);tn.removeChildren(true);this.div.removeChild(tn.div);delete tn;}
+this.childList=null;if(!recursive){this._expand(false);this.isRead=false;this.render(false,false);}}},_addChildNode:function(dtnode){var tree=this.tree;var opts=tree.options;if(this.childList==null){this.childList=[];}else{$(this.childList[this.childList.length-1].span).removeClass(opts.classNames.lastsib);}
+this.childList.push(dtnode);dtnode.parent=this;if(dtnode.data.expand||opts.minExpandLevel>=dtnode.getLevel())
+this.bExpanded=true;if(!dtnode.data.isStatusNode&&opts.selectMode==3&&!tree.isInitializing())
+dtnode._fixSelectionState();if(tree.bEnableUpdate)
+this.render(true,true);return dtnode;},_addNode:function(data){return this._addChildNode(new DynaTreeNode(this,this.tree,data));},append:function(obj){if(!obj||obj.length==0)
+return;if(!obj.length)
+obj=[obj];var prevFlag=this.tree.enableUpdate(false);var tnFirst=null;for(var i=0;i<obj.length;i++){var data=obj[i];var dtnode=this._addNode(data);if(!tnFirst)tnFirst=dtnode;if(data.children)
+dtnode.append(data.children);}
+this.tree.enableUpdate(prevFlag);return tnFirst;},appendAjax:function(ajaxOptions){this.setLazyNodeStatus(DTNodeStatus_Loading);var self=this;var orgSuccess=ajaxOptions.success;var orgError=ajaxOptions.error;var options=$.extend({},this.tree.options.ajaxDefaults,ajaxOptions,{success:function(data,textStatus){self.append(data);self.setLazyNodeStatus(DTNodeStatus_Ok);if(orgSuccess)
+orgSuccess.call(options,self);},error:function(XMLHttpRequest,textStatus,errorThrown){self.setLazyNodeStatus(DTNodeStatus_Error);if(orgError)
+orgError.call(options,self,XMLHttpRequest,textStatus,errorThrown);}});$.ajax(options);},lastentry:undefined}
+var DynaTree=Class.create();DynaTree.version="$Version: 0.4.2$";DynaTree.prototype={initialize:function(divContainer,options){this.options=options;this.bEnableUpdate=true;this._nodeCount=0;this.initMode="data";this.activeNode=null;this.selectedNodes=[];this.expandedNodes=[];if(this.options.persist){this.initActiveKey=$.cookie(this.options.cookieId+"-active");if(cookie||this.initActiveKey!=null)
+this.initMode="cookie";this.initFocusKey=$.cookie(this.options.cookieId+"-focus");var cookie=$.cookie(this.options.cookieId+"-expand");if(cookie!=null)
+this.initMode="cookie";this.initExpandedKeys=cookie?cookie.split(","):[];cookie=$.cookie(this.options.cookieId+"-select");this.initSelectedKeys=cookie?cookie.split(","):[];}
+this.logDebug("initMode: %o, active: %o, focus: %o, expanded: %o, selected: %o",this.initMode,this.initActiveKey,this.initFocusKey,this.initExpandedKeys,this.initSelectedKeys);this.cache={tagEmpty:"<span class='"+options.classNames.empty+"'></span>",tagVline:"<span class='"+options.classNames.vline+"'></span>",tagExpander:"<span class='"+options.classNames.expander+"'></span>",tagConnector:"<span class='"+options.classNames.connector+"'></span>",tagNodeIcon:"<span class='"+options.classNames.nodeIcon+"'></span>",tagCheckbox:"<span class='"+options.classNames.checkbox+"'></span>",lastentry:undefined};this.divTree=divContainer;this.tnRoot=new DynaTreeNode(null,this,{title:this.options.title,key:"root"});this.tnRoot.data.isFolder=true;this.tnRoot.render(false,false);this.divRoot=this.tnRoot.div;this.divRoot.className=this.options.classNames.container;this.divTree.appendChild(this.divRoot);},toString:function(){return"DynaTree '"+this.options.title+"'";},toDict:function(){return this.tnRoot.toDict(true);},logDebug:function(msg){if(this.options.debugLevel>=2){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments);}},logInfo:function(msg){if(this.options.debugLevel>=1){Array.prototype.unshift.apply(arguments,["info"]);_log.apply(this,arguments);}},logWarning:function(msg){Array.prototype.unshift.apply(arguments,["warn"]);_log.apply(this,arguments);},isInitializing:function(){return(this.initMode=="data"||this.initMode=="cookie"||this.initMode=="postInit");},_changeNodeList:function(mode,node,bAdd){if(!node)
+return false;var cookieName=this.options.cookieId+"-"+mode;var nodeList=(mode=="expand")?this.expandedNodes:this.selectedNodes;var idx=$.inArray(node,nodeList);if(bAdd){if(idx>=0)
+return false;nodeList.push(node);}else{if(idx<0)
+return false;nodeList.splice(idx,1);}
+if(this.options.persist){var keyList=$.map(nodeList,function(e,i){return e.data.key});$.cookie(cookieName,keyList.join(","),this.options.cookie);}else{}},redraw:function(){this.logDebug("dynatree.redraw()...");this.tnRoot.render(true,true);this.logDebug("dynatree.redraw() done.");},getRoot:function(){return this.tnRoot;},getNodeByKey:function(key){var el=document.getElementById(this.options.idPrefix+key);return(el&&el.dtnode)?el.dtnode:null;},getActiveNode:function(){return this.activeNode;},getSelectedNodes:function(stopOnParents){if(stopOnParents==true){var nodeList=[];this.tnRoot.visit(function(dtnode){if(dtnode.bSelected){nodeList.push(dtnode);return false;}});return nodeList;}else{return this.selectedNodes;}},activateKey:function(key){var dtnode=this.getNodeByKey(key);if(!dtnode){this.activeNode=null;return null;}
+dtnode.focus();dtnode.activate();return dtnode;},selectKey:function(key,select){var dtnode=this.getNodeByKey(key);if(!dtnode)
+return null;dtnode.select(select);return dtnode;},enableUpdate:function(bEnable){if(this.bEnableUpdate==bEnable)
+return bEnable;this.bEnableUpdate=bEnable;if(bEnable)
+this.redraw();return!bEnable;},visit:function(fn,data,includeRoot){return this.tnRoot.visit(fn,data,includeRoot);},_createFromTag:function(parentTreeNode,$ulParent){var self=this;$ulParent.find(">li").each(function(){var $li=$(this);var $liSpan=$li.find(">span:first");var title;if($liSpan.length){title=$liSpan.html();}else{title=$li.html();var iPos=title.search(/<ul/i);if(iPos>=0)
+title=$.trim(title.substring(0,iPos));else
+title=$.trim(title);}
+var data={title:title,isFolder:$li.hasClass("folder"),isLazy:$li.hasClass("lazy"),expand:$li.hasClass("expanded"),select:$li.hasClass("selected"),activate:$li.hasClass("active"),focus:$li.hasClass("focused")};if($li.attr("title"))
+data.tooltip=$li.attr("title");if($li.attr("id"))
+data.key=$li.attr("id");if($li.attr("data")){var dataAttr=$.trim($li.attr("data"));if(dataAttr){if(dataAttr.charAt(0)!="{")
+dataAttr="{"+dataAttr+"}"
+try{$.extend(data,eval("("+dataAttr+")"));}catch(e){throw("Error parsing node data: "+e+"\ndata:\n'"+dataAttr+"'");}}}
+childNode=parentTreeNode._addNode(data);var $ul=$li.find(">ul:first");if($ul.length){self._createFromTag(childNode,$ul);}});},lastentry:undefined};$.widget("ui.dynatree",{init:function(){return this._init();},_init:function(){logMsg("Dynatree._init(): version='%s', debugLevel=%o.",DynaTree.version,this.options.debugLevel);this.options.event+=".dynatree";var $this=this.element;var opts=this.options;if(!opts.imagePath){$("script").each(function(){if(this.src.search(/.*dynatree[^/]*\.js$/i)>=0){if(this.src.indexOf("/")>=0)
+opts.imagePath=this.src.slice(0,this.src.lastIndexOf("/"))+"/skin/";else
+opts.imagePath="skin/";logMsg("Guessing imagePath from '%s': '%s'",this.src,opts.imagePath);return false;}});}
+var divContainer=$this.get(0);if(opts.children||(opts.initAjax&&opts.initAjax.url)||opts.initId)
+$(divContainer).empty();this.tree=new DynaTree(divContainer,opts);var root=this.tree.getRoot();var prevFlag=this.tree.enableUpdate(false);this.tree.logDebug("Start init tree structure...");if(opts.children){root.append(opts.children);}else if(opts.initAjax&&opts.initAjax.url){root.appendAjax(opts.initAjax);}else if(opts.initId){this.tree._createFromTag(root,$("#"+opts.initId));}else{var $ul=$this.find(">ul").hide();this.tree._createFromTag(root,$ul);$ul.remove();}
+this.tree.enableUpdate(prevFlag);this.tree.logDebug("Init tree structure... done.");this.bind();this.tree.initMode="postInit";nodeList=this.tree.selectedNodes.slice();this.tree.selectedNodes=[];for(var i=0;i<nodeList.length;i++){var dtnode=nodeList[i];this.tree.logDebug("Re-select on init: %o",dtnode);dtnode.bSelected=false;dtnode.select(true);}
+if(this.tree.focusNode){this.tree.logDebug("Focus on init: %o",this.tree.focusNode);this.tree.focusNode.focus();}
+if(this.tree.activeNode){var dtnode=this.tree.activeNode;this.tree.activeNode=null;this.tree.logDebug("Activate on init: %o",dtnode);dtnode._userActivate();}
+this.tree.initMode="running";},bind:function(){var $this=this.element;var o=this.options;this.unbind();function __getNodeFromElement(el){var iMax=4;do{if(el.dtnode)return el.dtnode;el=el.parentNode;}while(iMax--);return null;}
+$this.bind("click.dynatree dblclick.dynatree keypress.dynatree keydown.dynatree",function(event){var dtnode=__getNodeFromElement(event.target);if(!dtnode)
+return false;dtnode.tree.logDebug("bind(%o): dtnode: %o",event,dtnode);switch(event.type){case"click":return(o.onClick&&o.onClick(dtnode,event)===false)?false:dtnode.onClick(event);case"dblclick":return(o.onDblClick&&o.onDblClick(dtnode,event)===false)?false:dtnode.onDblClick(event);case"keydown":return(o.onKeydown&&o.onKeydown(dtnode,event)===false)?false:dtnode.onKeydown(event);case"keypress":return(o.onKeypress&&o.onKeypress(dtnode,event)===false)?false:dtnode.onKeypress(event);};});function __focusHandler(event){event=arguments[0]=$.event.fix(event||window.event);var dtnode=__getNodeFromElement(event.target);return dtnode?dtnode.onFocus(event):false;}
+var div=this.tree.divTree;if(div.addEventListener){div.addEventListener("focus",__focusHandler,true);div.addEventListener("blur",__focusHandler,true);}else{div.onfocusin=div.onfocusout=__focusHandler;}},unbind:function(){this.element.unbind(".dynatree");},enable:function(){this.bind();this.setData("disabled",false);},disable:function(){this.unbind();this.setData("disabled",true);},getTree:function(){return this.tree;},getRoot:function(){return this.tree.getRoot();},getActiveNode:function(){return this.tree.getActiveNode();},getSelectedNodes:function(){return this.tree.getSelectedNodes();},lastentry:undefined});$.ui.dynatree.getter="getTree getRoot getActiveNode getSelectedNodes";$.ui.dynatree.defaults={title:"Dynatree root",rootVisible:false,minExpandLevel:1,imagePath:null,children:null,initId:null,initAjax:null,autoFocus:true,keyboard:true,persist:false,autoCollapse:false,clickFolderMode:3,activeVisible:true,checkbox:false,selectMode:2,fx:null,onClick:null,onDblClick:null,onKeydown:null,onKeypress:null,onFocus:null,onBlur:null,onQueryActivate:null,onQuerySelect:null,onQueryExpand:null,onActivate:null,onDeactivate:null,onSelect:null,onExpand:null,onLazyRead:null,ajaxDefaults:{cache:false,dataType:"json"},strings:{loading:"Loading&#8230;",loadError:"Load error!"},idPrefix:"ui-dynatree-id-",cookieId:"ui-dynatree-cookie",cookie:{expires:null},classNames:{container:"ui-dynatree-container",folder:"ui-dynatree-folder",document:"ui-dynatree-document",empty:"ui-dynatree-empty",vline:"ui-dynatree-vline",expander:"ui-dynatree-expander",connector:"ui-dynatree-connector",checkbox:"ui-dynatree-checkbox",nodeIcon:"ui-dynatree-icon",nodeError:"ui-dynatree-statusnode-error",nodeWait:"ui-dynatree-statusnode-wait",hidden:"ui-dynatree-hidden",combinedExpanderPrefix:"ui-dynatree-exp-",combinedIconPrefix:"ui-dynatree-ico-",active:"ui-dynatree-active",selected:"ui-dynatree-selected",expanded:"ui-dynatree-expanded",lazy:"ui-dynatree-lazy",focused:"ui-dynatree-focused",partsel:"ui-dynatree-partsel",lastsib:"ui-dynatree-lastsib"},debugLevel:1,lastentry:undefined};$.ui.dynatree.nodedatadefaults={title:null,key:null,isFolder:false,isLazy:false,tooltip:null,icon:null,addClass:null,activate:false,focus:false,expand:false,select:false,children:null,lastentry:undefined};})(jQuery);
601 public/javascripts/jquery.form.js
@@ -0,0 +1,601 @@
+/*
+ * jQuery Form Plugin
+ * version: 2.12 (06/07/2008)
+ * @requires jQuery v1.2.2 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id$
+ */
+(function($) {
+
+/*
+ Usage Note:
+ -----------
+ Do not use both ajaxSubmit and ajaxForm on the same form. These
+ functions are intended to be exclusive. Use ajaxSubmit if you want
+ to bind your own submit handler to the form. For example,
+
+ $(document).ready(function() {
+ $('#myForm').bind('submit', function() {
+ $(this).ajaxSubmit({
+ target: '#output'
+ });
+ return false; // <-- important!
+ });
+ });
+
+ Use ajaxForm when you want the plugin to manage all the event binding
+ for you. For example,
+
+ $(document).ready(function() {
+ $('#myForm').ajaxForm({
+ target: '#output'
+ });
+ });
+
+ When using ajaxForm, the ajaxSubmit function will be invoked for you
+ at the appropriate time.
+*/
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+ // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+ if (!this.length) {
+ log('ajaxSubmit: skipping submit process - no element selected');
+ return this;
+ }
+
+ if (typeof options == 'function')
+ options = { success: options };
+
+ options = $.extend({
+ url: this.attr('action') || window.location.toString(),
+ type: this.attr('method') || 'GET'
+ }, options || {});
+
+ // hook for manipulating the form data before it is extracted;
+ // convenient for use with rich editors like tinyMCE or FCKEditor
+ var veto = {};
+ this.trigger('form-pre-serialize', [this, options, veto]);
+ if (veto.veto) {
+ log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+ return this;
+ }
+
+ var a = this.formToArray(options.semantic);
+ if (options.data) {
+ options.extraData = options.data;
+ for (var n in options.data)
+ a.push( { name: n, value: options.data[n] } );
+ }
+
+ // give pre-submit callback an opportunity to abort the submit
+ if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+ log('ajaxSubmit: submit aborted via beforeSubmit callback');
+ return this;
+ }
+
+ // fire vetoable 'validate' event
+ this.trigger('form-submit-validate', [a, this, options, veto]);
+ if (veto.veto) {
+ log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+ return this;
+ }
+
+ var q = $.param(a);
+
+ if (options.type.toUpperCase() == 'GET') {
+ options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+ options.data = null; // data is null for 'get'
+ }
+ else
+ options.data = q; // data is the query string for 'post'
+
+ var $form = this, callbacks = [];
+ if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
+ if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
+
+ // perform a load on the target only if dataType is not provided
+ if (!options.dataType && options.target) {
+ var oldSuccess = options.success || function(){};
+ callbacks.push(function(data) {
+ $(options.target).html(data).each(oldSuccess, arguments);
+ });
+ }
+ else if (options.success)
+ callbacks.push(options.success);
+
+ options.success = function(data, status) {
+ for (var i=0, max=callbacks.length; i < max; i++)
+ callbacks[i](data, status, $form);
+ };
+
+ // are there files to upload?
+ var files = $('input:file', this).fieldValue();
+ var found = false;
+ for (var j=0; j < files.length; j++)
+ if (files[j])
+ found = true;
+
+ // options.iframe allows user to force iframe mode
+ if (options.iframe || found) {
+ // hack to fix Safari hang (thanks to Tim Molendijk for this)
+ // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+ if ($.browser.safari && options.closeKeepAlive)
+ $.get(options.closeKeepAlive, fileUpload);
+ else
+ fileUpload();
+ }
+ else
+ $.ajax(options);
+
+ // fire 'notify' event
+ this.trigger('form-submit-notify', [this, options]);
+ return this;
+
+
+ // private function for handling file uploads (hat tip to YAHOO!)
+ function fileUpload() {
+ var form = $form[0];
+
+ if ($(':input[@name=submit]', form).length) {
+ alert('Error: Form elements must not be named "submit".');
+ return;
+ }
+
+ var opts = $.extend({}, $.ajaxSettings, options);
+
+ var id = 'jqFormIO' + (new Date().getTime());
+ var $io = $('<iframe id="' + id + '" name="' + id + '" />');
+ var io = $io[0];
+
+ if ($.browser.msie || $.browser.opera)
+ io.src = 'javascript:false;document.write("");';
+ $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+
+ var xhr = { // mock object
+ responseText: null,
+ responseXML: null,
+ status: 0,
+ statusText: 'n/a',
+ getAllResponseHeaders: function() {},
+ getResponseHeader: function() {},
+ setRequestHeader: function() {}
+ };
+
+ var g = opts.global;
+ // trigger ajax global events so that activity/block indicators work like normal
+ if (g && ! $.active++) $.event.trigger("ajaxStart");
+ if (g) $.event.trigger("ajaxSend", [xhr, opts]);
+
+ var cbInvoked = 0;
+ var timedOut = 0;
+
+ // add submitting element to data if we know it
+ var sub = form.clk;
+ if (sub) {
+ var n = sub.name;
+ if (n && !sub.disabled) {
+ options.extraData = options.extraData || {};
+ options.extraData[n] = sub.value;
+ if (sub.type == "image") {
+ options.extraData[name+'.x'] = form.clk_x;
+ options.extraData[name+'.y'] = form.clk_y;
+ }
+ }
+ }
+
+ // take a breath so that pending repaints get some cpu time before the upload starts
+ setTimeout(function() {
+ // make sure form attrs are set
+ var t = $form.attr('target'), a = $form.attr('action');
+ $form.attr({
+ target: id,
+ encoding: 'multipart/form-data',
+ enctype: 'multipart/form-data',
+ method: 'POST',
+ action: opts.url
+ });
+
+ // support timout
+ if (opts.timeout)
+ setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
+
+ // add "extra" data to form if provided in options
+ var extraInputs = [];
+ try {
+ if (options.extraData)
+ for (var n in options.extraData)
+ extraInputs.push(
+ $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
+ .appendTo(form)[0]);
+
+ // add iframe to doc and submit the form
+ $io.appendTo('body');
+ io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
+ form.submit();
+ }
+ finally {
+ // reset attrs and remove "extra" input elements
+ $form.attr('action', a);
+ t ? $form.attr('target', t) : $form.removeAttr('target');
+ $(extraInputs).remove();
+ }
+ }, 10);
+
+ function cb() {
+ if (cbInvoked++) return;
+
+ io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
+
+ var operaHack = 0;
+ var ok = true;
+ try {
+ if (timedOut) throw 'timeout';
+ // extract the server response from the iframe
+ var data, doc;
+
+ doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
+
+ if (doc.body == null && !operaHack && $.browser.opera) {
+ // In Opera 9.2.x the iframe DOM is not always traversable when
+ // the onload callback fires so we give Opera 100ms to right itself
+ operaHack = 1;
+ cbInvoked--;
+ setTimeout(cb, 100);
+ return;
+ }
+
+ xhr.responseText = doc.body ? doc.body.innerHTML : null;
+ xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+ xhr.getResponseHeader = function(header){
+ var headers = {'content-type': opts.dataType};
+ return headers[header];
+ };
+
+ if (opts.dataType == 'json' || opts.dataType == 'script') {
+ var ta = doc.getElementsByTagName('textarea')[0];
+ xhr.responseText = ta ? ta.value : xhr.responseText;
+ }
+ else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
+ xhr.responseXML = toXml(xhr.responseText);
+ }
+ data = $.httpData(xhr, opts.dataType);
+ }
+ catch(e){
+ ok = false;
+ $.handleError(opts, xhr, 'error', e);
+ }
+
+ // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+ if (ok) {
+ opts.success(data, 'success');
+ if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
+ }
+ if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
+ if (g && ! --$.active) $.event.trigger("ajaxStop");
+ if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
+
+ // clean up
+ setTimeout(function() {
+ $io.remove();
+ xhr.responseXML = null;
+ }, 100);
+ };
+
+ function toXml(s, doc) {
+ if (window.ActiveXObject) {
+ doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = 'false';
+ doc.loadXML(s);
+ }
+ else
+ doc = (new DOMParser()).parseFromString(s, 'text/xml');
+ return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
+ };
+ };
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ * is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ * used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+ return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
+ $(this).ajaxSubmit(options);
+ return false;
+ }).each(function() {
+ // store options in hash
+ $(":submit,input:image", this).bind('click.form-plugin',function(e) {
+ var $form = this.form;
+ $form.clk = this;
+ if (this.type == 'image') {
+ if (e.offsetX != undefined) {
+ $form.clk_x = e.offsetX;
+ $form.clk_y = e.offsetY;
+ } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
+ var offset = $(this).offset();
+ $form.clk_x = e.pageX - offset.left;
+ $form.clk_y = e.pageY - offset.top;
+ } else {
+ $form.clk_x = e.pageX - this.offsetLeft;
+ $form.clk_y = e.pageY - this.offsetTop;
+ }
+ }
+ // clear form vars
+ setTimeout(function() { $form.clk = $form.clk_x = $form.clk_y = null; }, 10);
+ });
+ });
+};
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+ this.unbind('submit.form-plugin');
+ return this.each(function() {
+ $(":submit,input:image", this).unbind('click.form-plugin');
+ });
+
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property. An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic) {
+ var a = [];
+ if (this.length == 0) return a;
+
+ var form = this[0];
+ var els = semantic ? form.getElementsByTagName('*') : form.elements;
+ if (!els) return a;
+ for(var i=0, max=els.length; i < max; i++) {
+ var el = els[i];
+ var n = el.name;
+ if (!n) continue;
+
+ if (semantic && form.clk && el.type == "image") {
+ // handle image inputs on the fly when semantic == true
+ if(!el.disabled && form.clk == el)
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+ continue;
+ }
+
+ var v = $.fieldValue(el, true);
+ if (v && v.constructor == Array) {
+ for(var j=0, jmax=v.length; j < jmax; j++)
+ a.push({name: n, value: v[j]});
+ }
+ else if (v !== null && typeof v != 'undefined')
+ a.push({name: n, value: v});
+ }
+
+ if (!semantic && form.clk) {
+ // input type=='image' are not found in elements array! handle them here
+ var inputs = form.getElementsByTagName("input");
+ for(var i=0, max=inputs.length; i < max; i++) {
+ var input = inputs[i];
+ var n = input.name;
+ if(n && !input.disabled && input.type == "image" && form.clk == input)
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+ }
+ }
+ return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+ //hand off to jQuery.param for proper encoding
+ return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+ var a = [];
+ this.each(function() {
+ var n = this.name;
+ if (!n) return;
+ var v = $.fieldValue(this, successful);
+ if (v && v.constructor == Array) {
+ for (var i=0,max=v.length; i < max; i++)
+ a.push({name: n, value: v[i]});
+ }
+ else if (v !== null && typeof v != 'undefined')
+ a.push({name: this.name, value: v});
+ });
+ //hand off to jQuery.param for proper encoding
+ return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set. For example, consider the following form:
+ *
+ * <form><fieldset>
+ * <input name="A" type="text" />
+ * <input name="A" type="text" />
+ * <input name="B" type="checkbox" value="B1" />
+ * <input name="B" type="checkbox" value="B2"/>
+ * <input name="C" type="radio" value="C1" />
+ * <input name="C" type="radio" value="C2" />
+ * </fieldset></form>
+ *
+ * var v = $(':text').fieldValue();
+ * // if no values are entered into the text inputs
+ * v == ['','']
+ * // if values entered into the text inputs are 'foo' and 'bar'
+ * v == ['foo','bar']
+ *
+ * var v = $(':checkbox').fieldValue();
+ * // if neither checkbox is checked
+ * v === undefined
+ * // if both checkboxes are checked
+ * v == ['B1', 'B2']
+ *
+ * var v = $(':radio').fieldValue();
+ * // if neither radio is checked
+ * v === undefined
+ * // if first radio is checked
+ * v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true. If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array. If no valid value can be determined the
+ * array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+ for (var val=[], i=0, max=this.length; i < max; i++) {
+ var el = this[i];
+ var v = $.fieldValue(el, successful);
+ if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
+ continue;
+ v.constructor == Array ? $.merge(val, v) : val.push(v);
+ }
+ return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+ var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+ if (typeof successful == 'undefined') successful = true;
+
+