Skip to content
Browse files

Initial commit

  • Loading branch information...
0 parents commit dff13c816498d695040eb20bf737aa9ce17d5ac5 @binarylogic committed Sep 5, 2008
Showing with 17,792 additions and 0 deletions.
  1. +5 −0 .gitignore
  2. +256 −0 README
  3. +10 −0 Rakefile
  4. +15 −0 app/controllers/application.rb
  5. +12 −0 app/controllers/orders_controller.rb
  6. +15 −0 app/controllers/users_controller.rb
  7. +3 −0 app/helpers/application_helper.rb
  8. +3 −0 app/models/order.rb
  9. +3 −0 app/models/user.rb
  10. +10 −0 app/views/layouts/application.html.erb
  11. +106 −0 app/views/users/index.html.erb
  12. +109 −0 config/boot.rb
  13. +70 −0 config/environment.rb
  14. +17 −0 config/environments/development.rb
  15. +22 −0 config/environments/production.rb
  16. +22 −0 config/environments/test.rb
  17. +10 −0 config/initializers/inflections.rb
  18. +5 −0 config/initializers/mime_types.rb
  19. +15 −0 config/initializers/new_rails_defaults.rb
  20. +26 −0 config/initializers/searchgasm.rb
  21. +5 −0 config/routes.rb
  22. +16 −0 db/migrate/20080904202523_create_users.rb
  23. +15 −0 db/migrate/20080904202548_create_orders.rb
  24. +2 −0 doc/README_FOR_APP
  25. +30 −0 public/404.html
  26. +30 −0 public/422.html
  27. +30 −0 public/500.html
  28. +2 −0 public/blank_iframe.html
  29. +10 −0 public/dispatch.cgi
  30. +24 −0 public/dispatch.fcgi
  31. +10 −0 public/dispatch.rb
  32. 0 public/favicon.ico
  33. BIN public/images/calendar_date_select/calendar.gif
  34. BIN public/images/rails.png
  35. +2 −0 public/javascripts/application.js
  36. +430 −0 public/javascripts/calendar_date_select/calendar_date_select.js
  37. +34 −0 public/javascripts/calendar_date_select/format_american.js
  38. +27 −0 public/javascripts/calendar_date_select/format_db.js
  39. +7 −0 public/javascripts/calendar_date_select/format_euro_24hr.js
  40. +7 −0 public/javascripts/calendar_date_select/format_euro_24hr_ymd.js
  41. +24 −0 public/javascripts/calendar_date_select/format_finnish.js
  42. +36 −0 public/javascripts/calendar_date_select/format_hyphen_ampm.js
  43. +46 −0 public/javascripts/calendar_date_select/format_iso_date.js
  44. +24 −0 public/javascripts/calendar_date_select/format_italian.js
  45. +10 −0 public/javascripts/calendar_date_select/locale/fi.js
  46. +10 −0 public/javascripts/calendar_date_select/locale/fr.js
  47. +10 −0 public/javascripts/calendar_date_select/locale/pl.js
  48. +10 −0 public/javascripts/calendar_date_select/locale/pt.js
  49. +963 −0 public/javascripts/controls.js
  50. +972 −0 public/javascripts/dragdrop.js
  51. +1,120 −0 public/javascripts/effects.js
  52. +4,225 −0 public/javascripts/prototype.js
  53. +5 −0 public/robots.txt
  54. +130 −0 public/stylesheets/calendar_date_select/blue.css
  55. +135 −0 public/stylesheets/calendar_date_select/default.css
  56. +128 −0 public/stylesheets/calendar_date_select/plain.css
  57. +135 −0 public/stylesheets/calendar_date_select/red.css
  58. +133 −0 public/stylesheets/calendar_date_select/silver.css
  59. +3 −0 script/about
  60. +3 −0 script/console
  61. +3 −0 script/dbconsole
  62. +3 −0 script/destroy
  63. +3 −0 script/generate
  64. +3 −0 script/performance/benchmarker
  65. +3 −0 script/performance/profiler
  66. +3 −0 script/performance/request
  67. +3 −0 script/plugin
  68. +3 −0 script/process/inspector
  69. +3 −0 script/process/reaper
  70. +3 −0 script/process/spawner
  71. +3 −0 script/runner
  72. +3 −0 script/server
  73. +11 −0 test/fixtures/orders.yml
  74. +13 −0 test/fixtures/users.yml
  75. +38 −0 test/test_helper.rb
  76. +8 −0 test/unit/order_test.rb
  77. +8 −0 test/unit/user_test.rb
  78. +200 −0 vendor/plugins/calendar_date_select/CHANGELOG
  79. +20 −0 vendor/plugins/calendar_date_select/MIT-LICENSE
  80. +31 −0 vendor/plugins/calendar_date_select/README
  81. +14 −0 vendor/plugins/calendar_date_select/calendar_date_select.gemspec
  82. +17 −0 vendor/plugins/calendar_date_select/init.rb
  83. +306 −0 vendor/plugins/calendar_date_select/js_test/functional/.tmp_cds_test.html
  84. +334 −0 vendor/plugins/calendar_date_select/js_test/functional/cds_test.html
  85. +4,184 −0 vendor/plugins/calendar_date_select/js_test/prototype.js
  86. +40 −0 vendor/plugins/calendar_date_select/js_test/test.css
  87. +46 −0 vendor/plugins/calendar_date_select/js_test/unit/cds_helper_methods.html
  88. +564 −0 vendor/plugins/calendar_date_select/js_test/unittest.js
  89. +222 −0 vendor/plugins/calendar_date_select/lib/calendar_date_select.rb
  90. +3 −0 vendor/plugins/calendar_date_select/lib/gem_init.rb
  91. +38 −0 vendor/plugins/calendar_date_select/lib/includes_helper.rb
  92. +157 −0 vendor/plugins/calendar_date_select/test/functional/calendar_date_select_test.rb
  93. +15 −0 vendor/plugins/calendar_date_select/test/functional/helper_methods_test.rb
  94. +26 −0 vendor/plugins/calendar_date_select/test/test_helper.rb
  95. +16 −0 vendor/rails/.gitignore
  96. +341 −0 vendor/rails/actionmailer/CHANGELOG
  97. +21 −0 vendor/rails/actionmailer/MIT-LICENSE
  98. +149 −0 vendor/rails/actionmailer/README
  99. +98 −0 vendor/rails/actionmailer/Rakefile
  100. +30 −0 vendor/rails/actionmailer/install.rb
  101. +52 −0 vendor/rails/actionmailer/lib/action_mailer.rb
  102. +30 −0 vendor/rails/actionmailer/lib/action_mailer/adv_attr_accessor.rb
  103. +682 −0 vendor/rails/actionmailer/lib/action_mailer/base.rb
  104. +111 −0 vendor/rails/actionmailer/lib/action_mailer/helpers.rb
  105. +19 −0 vendor/rails/actionmailer/lib/action_mailer/mail_helper.rb
  106. +110 −0 vendor/rails/actionmailer/lib/action_mailer/part.rb
  107. +51 −0 vendor/rails/actionmailer/lib/action_mailer/part_container.rb
  108. +61 −0 vendor/rails/actionmailer/lib/action_mailer/quoting.rb
  109. +64 −0 vendor/rails/actionmailer/lib/action_mailer/test_case.rb
  110. +67 −0 vendor/rails/actionmailer/lib/action_mailer/test_helper.rb
  111. +8 −0 vendor/rails/actionmailer/lib/action_mailer/utils.rb
  112. +14 −0 vendor/rails/actionmailer/lib/action_mailer/vendor.rb
Sorry, we could not display the entire diff because too many files (1,603) changed.
5 .gitignore
@@ -0,0 +1,5 @@
+db/schema.rb
+config/database.yml
+tmp/*
+log/*
+.DS_Store
256 README
@@ -0,0 +1,256 @@
+== 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 and lighttpd if they are installed, otherwise
+Rails will use WEBrick, the webserver that ships with Ruby. When you run script/server,
+Rails will check if Mongrel exists, then lighttpd and finally fall back to WEBrick. This ensures
+that you can always get up and running quickly.
+
+Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
+suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
+getting up and running with mongrel is as easy as: <tt>gem install mongrel</tt>.
+More info at: http://mongrel.rubyforge.org
+
+If Mongrel is not installed, Rails will look for lighttpd. It's considerably faster than
+Mongrel and WEBrick and also suited for production use, but requires additional
+installation and currently only works well on OS X/Unix (Windows users are encouraged
+to start with Mongrel). We recommend version 1.4.11 and higher. You can download it from
+http://www.lighttpd.net.
+
+And finally, if neither Mongrel or lighttpd are installed, Rails will use the built-in Ruby
+web server, WEBrick. WEBrick is a small Ruby web server suitable for development, but not
+for production.
+
+But of course its also possible to run Rails on any platform that supports FCGI.
+Apache, LiteSpeed, IIS are just a few. For more information on FCGI,
+please visit: http://wiki.rubyonrails.com/rails/pages/FastCGI
+
+
+== Apache .htaccess example
+
+# 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'
15 app/controllers/application.rb
@@ -0,0 +1,15 @@
+# Filters added to this controller apply to all controllers in the application.
+# Likewise, all the methods added will be available for all controllers.
+
+class ApplicationController < ActionController::Base
+ helper :all # include all helpers, all the time
+
+ # See ActionController::RequestForgeryProtection for details
+ # Uncomment the :secret if you're not using the cookie session store
+ protect_from_forgery # :secret => 'e619585c1ea01344f19d504e61dd6e3d'
+
+ # See ActionController::Base for details
+ # Uncomment this to filter the contents of submitted sensitive data parameters
+ # from your application log (in this case, all fields with names like "password").
+ # filter_parameter_logging :password
+end
12 app/controllers/orders_controller.rb
@@ -0,0 +1,12 @@
+class OrdersController < ApplicationController
+ def index
+ # This creates a new search object to search for users. It's safe to pass params into here because
+ # new_search and new_conditions are protected, meaning the structure of the params hash is run through
+ # checks to ensure there is no SQL injection or anything invalid. This ultimately allows you to create a controllers action
+ # that searches, orders, and paginates in 2 lines.
+ @search = User.new_search(params[:search])
+
+ # .all takes pagination into account. .count tells you how many records will be returned disregarding the limit and offset options.
+ @users, @users_count = @search.all, @search.count
+ end
+end
15 app/controllers/users_controller.rb
@@ -0,0 +1,15 @@
+class UsersController < ApplicationController
+ def index
+ # This creates a new search object to search for users. It's safe to pass params into here because
+ # new_search and new_conditions are protected, meaning the structure of the params hash is run through
+ # checks to ensure there is no SQL injection or anything invalid. This ultimately allows you to create a controllers action
+ # that searches, orders, and paginates in 2 lines.
+ #
+ # This also gives people using your site as a service some real flexibility when it comes to searching. The sky is the limit on how they want to search, unless you restrict them.
+ # Restricting conditions works similar to ActiveRecord's attr_protected and attr_accessible. See the documentation for more details.
+ @search = User.new_search(params[:search])
+
+ # .all takes pagination into account. .count tells you how many records will be returned disregarding the limit and offset options.
+ @users, @users_count = @search.all, @search.count
+ end
+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
3 app/models/order.rb
@@ -0,0 +1,3 @@
+class Order < ActiveRecord::Base
+ belongs_to :user
+end
3 app/models/user.rb
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+ has_many :orders
+end
10 app/views/layouts/application.html.erb
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>Searchgasm Example</title>
+ <%= javascript_include_tag :all %>
+ <%= calendar_date_select_includes %>
+</head>
+<body>
+ <%= yield %>
+</body>
+</html>
106 app/views/users/index.html.erb
@@ -0,0 +1,106 @@
+<!--
+You can pass your search object right into form_for or remote_form_for and it will do the rest. Just like passing an ActiveRecord attribute. Use it the same way:
+
+Need to scope the search? form_for([@current_user, @search])
+Want to specify your own url? form_for(@search, :url => whatever_path)
+Need to specify your own name? form_for(:whatever, @search)
+
+The beauty of this is that it recoginizes that its a search object and helps you out. It adds 3 hidden fields for you:
+
+1. order_by
+2. order_as
+2. per_page
+
+This way when people start a new search those 3 things will be "remembered" and the results will be displayed in that manner.
+-->
+<% form_for @search do |f| %>
+ <fieldset>
+ <legend>Search</legend>
+
+ <% f.fields_for @search.conditions do |users| %>
+ <!--
+ You can specify ANY of the conditions available on ANY of the attributes. Adding a condition and having it be a part
+ of the search is as simple as adding another form element.
+ -->
+ First name:<br />
+ <%= users.text_field :first_name_keywords %><br />
+ <br />
+
+ First name sounds like: (try &quot;bin&quot;, this is a custom condition, checkout config/initializers/searchgasm.rb)<br />
+ <%= users.text_field :first_name_sounds_like %><br />
+ <br />
+
+ Last name:<br />
+ <%= users.text_field :last_name_keywords %><br />
+ <br />
+
+ Email ends with:<br />
+ <%= users.text_field :email_ends_with %><br />
+ <br />
+
+ Created after:<br />
+ <%= users.calendar_date_select :created_after %><br /> <!-- # nice rails plugin for replacing date_select -->
+ <br />
+
+ <!--
+ You can traverse through your relationships to set conditions. For example, the condition below will add the following condition:
+
+ "return users that have orders with a total greater than X"
+
+ You could keep going through your relationships. If order has many line items you could do:
+
+ orders.fields_for orders.object.line_items do |line_item|
+ -->
+ <% users.fields_for users.object.orders do |orders| %>
+ Has orders with a total greater than:<br />
+ $<%= orders.text_field :total_gt %><br />
+ <br />
+ <% end %>
+ <%= f.submit "Search" %>
+ <% end %>
+ </fieldset>
+<% end %>
+
+<% if @users_count > 0 %>
+ <%= @users_count %> users found
+ <table>
+ <tr>
+ <!--
+ order_by allows you to create a link to order the data by that coloumn. You aren't limited to the local columns. Since users belong to user groups we could do
+
+ order_by(:user_group => :name)
+
+ You can traverse through your relationships to define how things are ordered. There are a lot of options for this to allow you to customize it to your liking. Please
+ glance at the Searchgasm::Helpers module for a list of options.
+ -->
+ <th><%= order_by :id %></th>
+ <th><%= order_by :first_name %></th>
+ <th><%= order_by :last_name %></th>
+ <th><%= order_by :email %></th>
+ <% @users.each do |user| %>
+ <tr>
+ <td><%= user.id %></td>
+ <td><%= user.first_name %></td>
+ <td><%= user.last_name %></td>
+ <td><%= user.email %></td>
+ </tr>
+ <% end %>
+ </table>
+
+ <br />
+ <br />
+ <!--
+ Per page returns a select with the different options. This is very customizable, you can change just about anything. Please take a look at the Searchgasm::Helpers documentation for options
+ -->
+ Per page: <%= per_page %>
+
+ <!--
+ Page returns a drop down with the page options. You can change this from a drop down to a links. It's completely customizable. Please take a look at the Searchgasm::Helpers documentation for options
+ -->
+ <% if @search.page_count > 1 %>
+ <br />
+ Page: <%= pages %>
+ <% end %>
+<% else %>
+ No users were returned
+<% end %>
109 config/boot.rb
@@ -0,0 +1,109 @@
+# 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)
+ 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 if defined? Gem::RubyGemsVersion
+ end
+
+ def gem_version
+ if defined? RAILS_GEM_VERSION
+ RAILS_GEM_VERSION
+ elsif ENV.include?('RAILS_GEM_VERSION')
+ ENV['RAILS_GEM_VERSION']
+ else
+ parse_gem_version(read_environment_rb)
+ end
+ end
+
+ def load_rubygems
+ require 'rubygems'
+
+ unless rubygems_version >= '0.9.4'
+ $stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.)
+ exit 1
+ end
+
+ rescue LoadError
+ $stderr.puts %(Rails requires RubyGems >= 0.9.4. Please install RubyGems and try again: http://rubygems.rubyforge.org)
+ exit 1
+ end
+
+ def parse_gem_version(text)
+ $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
+ end
+
+ private
+ def read_environment_rb
+ File.read("#{RAILS_ROOT}/config/environment.rb")
+ end
+ end
+ end
+end
+
+# All that for this:
+Rails.boot!
70 config/environment.rb
@@ -0,0 +1,70 @@
+# Be sure to restart your server when you modify this file
+
+# Uncomment below to force Rails into production mode when
+# you don't control web/app server and can't set it the proper way
+# ENV['RAILS_ENV'] ||= 'production'
+
+# Specifies gem version of Rails to use when vendor/rails is not present
+RAILS_GEM_VERSION = '2.1.0' 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.
+ # See Rails::Configuration for more options.
+
+ # Skip frameworks you're not going to use. To use Rails without a database
+ # you must remove the Active Record framework.
+ # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
+
+ # Specify gems that this application depends on.
+ # They can then be installed with "rake gems:install" on new installations.
+ # config.gem "bj"
+ # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
+ # config.gem "aws-s3", :lib => "aws/s3"
+ #config.gem :searchgasm
+ config.plugin_paths += ["../../Ruby Libs"]
+ config.plugins = [:calendar_date_select, :searchgasm]
+
+ # Only load the plugins named here, in the order given. By default, all plugins
+ # in vendor/plugins are loaded in alphabetical order.
+ # :all can be used as a placeholder for all plugins not explicitly named
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+ # Add additional load paths for your own custom dirs
+ # config.load_paths += %W( #{RAILS_ROOT}/extras )
+
+ # Force all environments to use the same logger level
+ # (by default production uses :info, the others :debug)
+ # config.log_level = :debug
+
+ # Make Time.zone default to the specified zone, and make Active Record store time values
+ # in the database in UTC, and return them converted to the specified local zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Uncomment to use default local time.
+ config.time_zone = 'UTC'
+
+ # 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.
+ config.action_controller.session = {
+ :session_key => '_searchgasm_example_session',
+ :secret => '4d7db02f53d3bccd73428357072797fb6b04507ad3ef08f0abc589c2f1a6ee8f10e71bdbbc357f8fd50a7620f4bb433836e18017517a9df9df70c910fa3006c8'
+ }
+
+ # 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")
+ # config.action_controller.session_store = :active_record_store
+
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
+ # like if you have constraints or database-specific column types
+ # config.active_record.schema_format = :sql
+
+ # Activate observers that should always be running
+ # config.active_record.observers = :cacher, :garbage_collector
+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
22 config/environments/production.rb
@@ -0,0 +1,22 @@
+# Settings specified here will take precedence over those in config/environment.rb
+
+# The production environment is meant for finished, "live" apps.
+# Code is not reloaded between requests
+config.cache_classes = true
+
+# Use a different logger for distributed setups
+# config.logger = SyslogLogger.new
+
+# Full error reports are disabled and caching is turned on
+config.action_controller.consider_all_requests_local = false
+config.action_controller.perform_caching = true
+config.action_view.cache_template_loading = true
+
+# 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
22 config/environments/test.rb
@@ -0,0 +1,22 @@
+# Settings specified here will take precedence over those in config/environment.rb
+
+# The test environment is used exclusively to run your application's
+# test suite. You never need to work with it otherwise. Remember that
+# your test database is "scratch space" for the test suite and is wiped
+# and recreated between test runs. Don't rely on the data there!
+config.cache_classes = true
+
+# Log error messages when you accidentally call methods on nil.
+config.whiny_nils = true
+
+# Show full error reports and disable caching
+config.action_controller.consider_all_requests_local = true
+config.action_controller.perform_caching = false
+
+# Disable request forgery protection in test environment
+config.action_controller.allow_forgery_protection = false
+
+# Tell 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
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):
+# 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
15 config/initializers/new_rails_defaults.rb
@@ -0,0 +1,15 @@
+# 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.
+
+# 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
+
+# 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
26 config/initializers/searchgasm.rb
@@ -0,0 +1,26 @@
+# Actual function for MySQL databases only
+class SoundsLikeCondition < Searchgasm::Condition::Base
+ class << self
+ # I pass you the column, you tell me what you want the method to be called.
+ # If you don't want to add this condition for that column, return nil
+ # It defaults to "#{column.name}_sounds_like". So if thats what you want you don't even need to do this.
+ def name_for_column(column)
+ return unless column.type == :string
+ super
+ end
+
+ # Only do this if you want aliases for your condition
+ def aliases_for_column(column)
+ ["#{column.name}_sounds", "#{column.name}_similar_to"]
+ end
+ end
+
+ # You can return an array or a string. NOT a hash, because all of these conditions
+ # need to eventually get merged together. The array or string can be anything you would put in
+ # the :conditions option for ActiveRecord::Base.find()
+ def to_conditions(value)
+ ["#{quoted_table_name}.#{quoted_column_name} SOUNDS LIKE ?", value]
+ end
+end
+
+Searchgasm::Conditions::Base.register_condition(SoundsLikeCondition)
5 config/routes.rb
@@ -0,0 +1,5 @@
+ActionController::Routing::Routes.draw do |map|
+ map.default '', :controller => "users"
+ map.resources :users
+ map.resources :orders
+end
16 db/migrate/20080904202523_create_users.rb
@@ -0,0 +1,16 @@
+class CreateUsers < ActiveRecord::Migration
+ def self.up
+ create_table :users do |t|
+ t.string :first_name
+ t.string :last_name
+ t.string :email
+ t.date :born_on
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :users
+ end
+end
15 db/migrate/20080904202548_create_orders.rb
@@ -0,0 +1,15 @@
+class CreateOrders < ActiveRecord::Migration
+ def self.up
+ create_table :orders do |t|
+ t.integer :user_id
+ t.float :total
+ t.string :description
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :orders
+ end
+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>
2 public/blank_iframe.html
@@ -0,0 +1,2 @@
+<!-- Nothing here -->
+<html><head></head><body></body></html>
10 public/dispatch.cgi
@@ -0,0 +1,10 @@
+#!/opt/local/bin/ruby
+
+require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
+Dispatcher.dispatch
24 public/dispatch.fcgi
@@ -0,0 +1,24 @@
+#!/opt/local/bin/ruby
+#
+# You may specify the path to the FastCGI crash log (a log of unhandled
+# exceptions which forced the FastCGI instance to exit, great for debugging)
+# and the number of requests to process before running garbage collection.
+#
+# By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
+# and the GC period is nil (turned off). A reasonable number of requests
+# could range from 10-100 depending on the memory footprint of your app.
+#
+# Example:
+# # Default log path, normal GC behavior.
+# RailsFCGIHandler.process!
+#
+# # Default log path, 50 requests between GC.
+# RailsFCGIHandler.process! nil, 50
+#
+# # Custom log path, normal GC behavior.
+# RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
+#
+require File.dirname(__FILE__) + "/../config/environment"
+require 'fcgi_handler'
+
+RailsFCGIHandler.process!
10 public/dispatch.rb
@@ -0,0 +1,10 @@
+#!/opt/local/bin/ruby
+
+require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
+Dispatcher.dispatch
0 public/favicon.ico
No changes.
BIN public/images/calendar_date_select/calendar.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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.
2 public/javascripts/application.js
@@ -0,0 +1,2 @@
+// Place your application-specific JavaScript functions and classes here
+// This file is automatically included by javascript_include_tag :defaults
430 public/javascripts/calendar_date_select/calendar_date_select.js
@@ -0,0 +1,430 @@
+// CalendarDateSelect version 1.10.11 - a prototype based date picker
+// Questions, comments, bugs? - see the project page: http://code.google.com/p/calendardateselect
+if (typeof Prototype == 'undefined') alert("CalendarDateSelect Error: Prototype could not be found. Please make sure that your application's layout includes prototype.js (.g. <%= javascript_include_tag :defaults %>) *before* it includes calendar_date_select.js (.g. <%= calendar_date_select_includes %>).");
+if (Prototype.Version < "1.6") alert("Prototype 1.6.0 is required. If using earlier version of prototype, please use calendar_date_select version 1.8.3");
+
+Element.addMethods({
+ purgeChildren: function(element) { $A(element.childNodes).each(function(e){$(e).remove();}); },
+ build: function(element, type, options, style) {
+ var newElement = Element.buildAndAppend(type, options, style);
+ element.appendChild(newElement);
+ return newElement;
+ }
+});
+
+Element.buildAndAppend = function(type, options, style)
+{
+ var e = $(document.createElement(type));
+ $H(options).each(function(pair) { eval("e." + pair.key + " = pair.value" ); });
+ if (style)
+ $H(style).each(function(pair) { eval("e.style." + pair.key + " = pair.value" ); });
+ return e;
+};
+nil = null;
+
+Date.one_day = 24*60*60*1000;
+Date.weekdays = $w("S M T W T F S");
+Date.first_day_of_week = 0;
+Date.months = $w("January February March April May June July August September October November December" );
+Date.padded2 = function(hour) { var padded2 = parseInt(hour, 10); if (hour < 10) padded2 = "0" + padded2; return padded2; }
+Date.prototype.getPaddedMinutes = function() { return Date.padded2(this.getMinutes()); }
+Date.prototype.getAMPMHour = function() { var hour = this.getHours(); return (hour == 0) ? 12 : (hour > 12 ? hour - 12 : hour ) }
+Date.prototype.getAMPM = function() { return (this.getHours() < 12) ? "AM" : "PM"; }
+Date.prototype.stripTime = function() { return new Date(this.getFullYear(), this.getMonth(), this.getDate());};
+Date.prototype.daysDistance = function(compare_date) { return Math.round((compare_date - this) / Date.one_day); };
+Date.prototype.toFormattedString = function(include_time){
+ var hour, str;
+ str = Date.months[this.getMonth()] + " " + this.getDate() + ", " + this.getFullYear();
+
+ if (include_time) { hour = this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() + " " + this.getAMPM() }
+ return str;
+}
+Date.parseFormattedString = function(string) { return new Date(string);}
+Math.floor_to_interval = function(n, i) { return Math.floor(n/i) * i;}
+window.f_height = function() { return( [window.innerHeight ? window.innerHeight : null, document.documentElement ? document.documentElement.clientHeight : null, document.body ? document.body.clientHeight : null].select(function(x){return x>0}).first()||0); }
+window.f_scrollTop = function() { return ([window.pageYOffset ? window.pageYOffset : null, document.documentElement ? document.documentElement.scrollTop : null, document.body ? document.body.scrollTop : null].select(function(x){return x>0}).first()||0 ); }
+
+_translations = {
+ "OK": "OK",
+ "Now": "Now",
+ "Today": "Today"
+}
+SelectBox = Class.create();
+SelectBox.prototype = {
+ initialize: function(parent_element, values, html_options, style_options) {
+ this.element = $(parent_element).build("select", html_options, style_options);
+ this.populate(values);
+ },
+ populate: function(values) {
+ this.element.purgeChildren();
+ var that = this; $A(values).each(function(pair) { if (typeof(pair)!="object") {pair = [pair, pair]}; that.element.build("option", { value: pair[1], innerHTML: pair[0]}) });
+ },
+ setValue: function(value) {
+ var e = this.element;
+ var matched = false;
+ $R(0, e.options.length - 1 ).each(function(i) { if(e.options[i].value==value.toString()) {e.selectedIndex = i; matched = true;}; } );
+ return matched;
+ },
+ getValue: function() { return $F(this.element)}
+}
+CalendarDateSelect = Class.create();
+CalendarDateSelect.prototype = {
+ initialize: function(target_element, options) {
+ this.target_element = $(target_element); // make sure it's an element, not a string
+ if (!this.target_element) { alert("Target element " + target_element + " not found!"); return false;}
+ if (this.target_element.tagName != "INPUT") this.target_element = this.target_element.down("INPUT")
+
+ this.target_element.calendar_date_select = this;
+ this.last_click_at = 0;
+ // initialize the date control
+ this.options = $H({
+ embedded: false,
+ popup: nil,
+ time: false,
+ buttons: true,
+ year_range: 10,
+ close_on_click: nil,
+ minute_interval: 5,
+ popup_by: this.target_element,
+ month_year: "dropdowns",
+ onchange: this.target_element.onchange,
+ valid_date_check: nil
+ }).merge(options || {});
+ this.use_time = this.options.get("time");
+ this.parseDate();
+ this.callback("before_show")
+ this.initCalendarDiv();
+ if(!this.options.get("embedded")) {
+ this.positionCalendarDiv()
+ // set the click handler to check if a user has clicked away from the document
+ Event.observe(document, "mousedown", this.closeIfClickedOut_handler = this.closeIfClickedOut.bindAsEventListener(this));
+ Event.observe(document, "keypress", this.keyPress_handler = this.keyPress.bindAsEventListener(this));
+ }
+ this.callback("after_show")
+ },
+ positionCalendarDiv: function() {
+ var above = false;
+ var c_pos = this.calendar_div.cumulativeOffset(), c_left = c_pos[0], c_top = c_pos[1], c_dim = this.calendar_div.getDimensions(), c_height = c_dim.height, c_width = c_dim.width;
+ var w_top = window.f_scrollTop(), w_height = window.f_height();
+ var e_dim = $(this.options.get("popup_by")).cumulativeOffset(), e_top = e_dim[1], e_left = e_dim[0], e_height = $(this.options.get("popup_by")).getDimensions().height, e_bottom = e_top + e_height;
+
+ if ( (( e_bottom + c_height ) > (w_top + w_height)) && ( e_bottom - c_height > w_top )) above = true;
+ var left_px = e_left.toString() + "px", top_px = (above ? (e_top - c_height ) : ( e_top + e_height )).toString() + "px";
+
+ this.calendar_div.style.left = left_px; this.calendar_div.style.top = top_px;
+
+ this.calendar_div.setStyle({visibility:""});
+
+ // draw an iframe behind the calendar -- ugly hack to make IE 6 happy
+ if(navigator.appName=="Microsoft Internet Explorer") this.iframe = $(document.body).build("iframe", {src: "javascript:false", className: "ie6_blocker"}, { left: left_px, top: top_px, height: c_height.toString()+"px", width: c_width.toString()+"px", border: "0px"})
+ },
+ initCalendarDiv: function() {
+ if (this.options.get("embedded")) {
+ var parent = this.target_element.parentNode;
+ var style = {}
+ } else {
+ var parent = document.body
+ var style = { position:"absolute", visibility: "hidden", left:0, top:0 }
+ }
+ this.calendar_div = $(parent).build('div', {className: "calendar_date_select"}, style);
+
+ var that = this;
+ // create the divs
+ $w("top header body buttons footer bottom").each(function(name) {
+ eval("var " + name + "_div = that." + name + "_div = that.calendar_div.build('div', { className: 'cds_"+name+"' }, { clear: 'left'} ); ");
+ });
+
+ this.initHeaderDiv();
+ this.initButtonsDiv();
+ this.initCalendarGrid();
+ this.updateFooter("&#160;");
+
+ this.refresh();
+ this.setUseTime(this.use_time);
+ },
+ initHeaderDiv: function() {
+ var header_div = this.header_div;
+ this.close_button = header_div.build("a", { innerHTML: "x", href:"#", onclick:function () { this.close(); return false; }.bindAsEventListener(this), className: "close" });
+ this.next_month_button = header_div.build("a", { innerHTML: "&gt;", href:"#", onclick:function () { this.navMonth(this.date.getMonth() + 1 ); return false; }.bindAsEventListener(this), className: "next" });
+ this.prev_month_button = header_div.build("a", { innerHTML: "&lt;", href:"#", onclick:function () { this.navMonth(this.date.getMonth() - 1 ); return false; }.bindAsEventListener(this), className: "prev" });
+
+ if (this.options.get("month_year")=="dropdowns") {
+ this.month_select = new SelectBox(header_div, $R(0,11).map(function(m){return [Date.months[m], m]}), {className: "month", onchange: function () { this.navMonth(this.month_select.getValue()) }.bindAsEventListener(this)});
+ this.year_select = new SelectBox(header_div, [], {className: "year", onchange: function () { this.navYear(this.year_select.getValue()) }.bindAsEventListener(this)});
+ this.populateYearRange();
+ } else {
+ this.month_year_label = header_div.build("span")
+ }
+ },
+ initCalendarGrid: function() {
+ var body_div = this.body_div;
+ this.calendar_day_grid = [];
+ var days_table = body_div.build("table", { cellPadding: "0px", cellSpacing: "0px", width: "100%" })
+ // make the weekdays!
+ var weekdays_row = days_table.build("thead").build("tr");
+ Date.weekdays.each( function(weekday) {
+ weekdays_row.build("th", {innerHTML: weekday});
+ });
+
+ var days_tbody = days_table.build("tbody")
+ // Make the days!
+ var row_number = 0, weekday;
+ for(var cell_index = 0; cell_index<42; cell_index++)
+ {
+ weekday = (cell_index+Date.first_day_of_week ) % 7;
+ if ( cell_index % 7==0 ) days_row = days_tbody.build("tr", {className: 'row_'+row_number++});
+ (this.calendar_day_grid[cell_index] = days_row.build("td", {
+ calendar_date_select: this,
+ onmouseover: function () { this.calendar_date_select.dayHover(this); },
+ onmouseout: function () { this.calendar_date_select.dayHoverOut(this) },
+ onclick: function() { this.calendar_date_select.updateSelectedDate(this, true); },
+ className: (weekday==0) || (weekday==6) ? " weekend" : "" //clear the class
+ },
+ { cursor: "pointer" }
+ )).build("div");
+ this.calendar_day_grid[cell_index];
+ }
+ },
+ initButtonsDiv: function()
+ {
+ var buttons_div = this.buttons_div;
+ if (this.options.get("time"))
+ {
+ var blank_time = $A(this.options.get("time")=="mixed" ? [[" - ", ""]] : []);
+ buttons_div.build("span", {innerHTML:"@", className: "at_sign"});
+
+ var t = new Date();
+ this.hour_select = new SelectBox(buttons_div,
+ blank_time.concat($R(0,23).map(function(x) {t.setHours(x); return $A([t.getAMPMHour()+ " " + t.getAMPM(),x])} )),
+ {
+ calendar_date_select: this,
+ onchange: function() { this.calendar_date_select.updateSelectedDate( { hour: this.value });},
+ className: "hour"
+ }
+ );
+ buttons_div.build("span", {innerHTML:":", className: "seperator"});
+ var that = this;
+ this.minute_select = new SelectBox(buttons_div,
+ blank_time.concat($R(0,59).select(function(x){return (x % that.options.get('minute_interval')==0)}).map(function(x){ return $A([ Date.padded2(x), x]); } ) ),
+ {
+ calendar_date_select: this,
+ onchange: function() { this.calendar_date_select.updateSelectedDate( {minute: this.value }) },
+ className: "minute"
+ }
+ );
+
+ } else if (! this.options.get("buttons")) buttons_div.remove();
+
+ if (this.options.get("buttons")) {
+ buttons_div.build("span", {innerHTML: "&#160;"});
+ if (this.options.get("time")=="mixed" || !this.options.get("time")) b = buttons_div.build("a", {
+ innerHTML: _translations["Today"],
+ href: "#",
+ onclick: function() {this.today(false); return false;}.bindAsEventListener(this)
+ });
+
+ if (this.options.get("time")=="mixed") buttons_div.build("span", {innerHTML: " | ", className:"button_seperator"})
+
+ if (this.options.get("time")) b = buttons_div.build("a", {
+ innerHTML: _translations["Now"],
+ href: "#",
+ onclick: function() {this.today(true); return false}.bindAsEventListener(this)
+ });
+
+ if (!this.options.get("embedded"))
+ {
+ buttons_div.build("span", {innerHTML: "&#160;"});
+ buttons_div.build("a", { innerHTML: _translations["OK"], href: "#", onclick: function() {this.close(); return false;}.bindAsEventListener(this) });
+ }
+ }
+ },
+ refresh: function ()
+ {
+ this.refreshMonthYear();
+ this.refreshCalendarGrid();
+
+ this.setSelectedClass();
+ this.updateFooter();
+ },
+ refreshCalendarGrid: function () {
+ this.beginning_date = new Date(this.date).stripTime();
+ this.beginning_date.setDate(1);
+ this.beginning_date.setHours(12); // Prevent daylight savings time boundaries from showing a duplicate day
+ var pre_days = this.beginning_date.getDay() // draw some days before the fact
+ if (pre_days < 3) pre_days += 7;
+ this.beginning_date.setDate(1 - pre_days + Date.first_day_of_week);
+
+ var iterator = new Date(this.beginning_date);
+
+ var today = new Date().stripTime();
+ var this_month = this.date.getMonth();
+ vdc = this.options.get("valid_date_check");
+ for (var cell_index = 0;cell_index<42; cell_index++)
+ {
+ day = iterator.getDate(); month = iterator.getMonth();
+ cell = this.calendar_day_grid[cell_index];
+ Element.remove(cell.childNodes[0]); div = cell.build("div", {innerHTML:day});
+ if (month!=this_month) div.className = "other";
+ cell.day = day; cell.month = month; cell.year = iterator.getFullYear();
+ if (vdc) { if (vdc(iterator.stripTime())) cell.removeClassName("disabled"); else cell.addClassName("disabled") };
+ iterator.setDate( day + 1);
+ }
+
+ if (this.today_cell) this.today_cell.removeClassName("today");
+
+ if ( $R( 0, 41 ).include(days_until = this.beginning_date.stripTime().daysDistance(today)) ) {
+ this.today_cell = this.calendar_day_grid[days_until];
+ this.today_cell.addClassName("today");
+ }
+ },
+ refreshMonthYear: function() {
+ var m = this.date.getMonth();
+ var y = this.date.getFullYear();
+ // set the month
+ if (this.options.get("month_year") == "dropdowns")
+ {
+ this.month_select.setValue(m, false);
+
+ var e = this.year_select.element;
+ if (this.flexibleYearRange() && (!(this.year_select.setValue(y, false)) || e.selectedIndex <= 1 || e.selectedIndex >= e.options.length - 2 )) this.populateYearRange();
+
+ this.year_select.setValue(y);
+
+ } else {
+ this.month_year_label.update( Date.months[m] + " " + y.toString() );
+ }
+ },
+ populateYearRange: function() {
+ this.year_select.populate(this.yearRange().toArray());
+ },
+ yearRange: function() {
+ if (!this.flexibleYearRange())
+ return $R(this.options.get("year_range")[0], this.options.get("year_range")[1]);
+
+ var y = this.date.getFullYear();
+ return $R(y - this.options.get("year_range"), y + this.options.get("year_range"));
+ },
+ flexibleYearRange: function() { return (typeof(this.options.get("year_range")) == "number"); },
+ validYear: function(year) { if (this.flexibleYearRange()) { return true;} else { return this.yearRange().include(year);} },
+ dayHover: function(element) {
+ var hover_date = new Date(this.selected_date);
+ hover_date.setYear(element.year); hover_date.setMonth(element.month); hover_date.setDate(element.day);
+ this.updateFooter(hover_date.toFormattedString(this.use_time));
+ },
+ dayHoverOut: function(element) { this.updateFooter(); },
+ clearSelectedClass: function() {if (this.selected_cell) this.selected_cell.removeClassName("selected");},
+ setSelectedClass: function() {
+ if (!this.selection_made) return;
+ this.clearSelectedClass()
+ if ($R(0,42).include( days_until = this.beginning_date.stripTime().daysDistance(this.selected_date.stripTime()) )) {
+ this.selected_cell = this.calendar_day_grid[days_until];
+ this.selected_cell.addClassName("selected");
+ }
+ },
+ reparse: function() { this.parseDate(); this.refresh(); },
+ dateString: function() {
+ return (this.selection_made) ? this.selected_date.toFormattedString(this.use_time) : "&#160;";
+ },
+ parseDate: function()
+ {
+ var value = $F(this.target_element).strip()
+ this.selection_made = (value != "");
+ this.date = value=="" ? NaN : Date.parseFormattedString(this.options.get("date") || value);
+ if (isNaN(this.date)) this.date = new Date();
+ if (!this.validYear(this.date.getFullYear())) this.date.setYear( (this.date.getFullYear() < this.yearRange().start) ? this.yearRange().start : this.yearRange().end);
+ this.selected_date = new Date(this.date);
+ this.use_time = /[0-9]:[0-9]{2}/.exec(value) ? true : false;
+ this.date.setDate(1);
+ },
+ updateFooter:function(text) { if (!text) text = this.dateString(); this.footer_div.purgeChildren(); this.footer_div.build("span", {innerHTML: text }); },
+ updateSelectedDate:function(partsOrElement, via_click) {
+ var parts = $H(partsOrElement);
+ if ((this.target_element.disabled || this.target_element.readOnly) && this.options.get("popup") != "force") return false;
+ if (parts.get("day")) {
+ var t_selected_date = this.selected_date, vdc = this.options.get("valid_date_check");
+ for (var x = 0; x<=3; x++) t_selected_date.setDate(parts.get("day"));
+ t_selected_date.setYear(parts.get("year"));
+ t_selected_date.setMonth(parts.get("month"));
+
+ if (vdc && ! vdc(t_selected_date.stripTime())) { return false; }
+ this.selected_date = t_selected_date;
+ this.selection_made = true;
+ }
+
+ if (!isNaN(parts.get("hour"))) this.selected_date.setHours(parts.get("hour"));
+ if (!isNaN(parts.get("minute"))) this.selected_date.setMinutes( Math.floor_to_interval(parts.get("minute"), this.options.get("minute_interval")) );
+ if (parts.get("hour") === "" || parts.get("minute") === "")
+ this.setUseTime(false);
+ else if (!isNaN(parts.get("hour")) || !isNaN(parts.get("minute")))
+ this.setUseTime(true);
+
+ this.updateFooter();
+ this.setSelectedClass();
+
+ if (this.selection_made) this.updateValue();
+ if (this.closeOnClick()) { this.close(); }
+ if (via_click && !this.options.get("embedded")) {
+ if ((new Date() - this.last_click_at) < 333) this.close();
+ this.last_click_at = new Date();
+ }
+ },
+ closeOnClick: function() {
+ if (this.options.get("embedded")) return false;
+ if (this.options.get("close_on_click")===nil )
+ return (this.options.get("time")) ? false : true
+ else
+ return (this.options.get("close_on_click"))
+ },
+ navMonth: function(month) { (target_date = new Date(this.date)).setMonth(month); return (this.navTo(target_date)); },
+ navYear: function(year) { (target_date = new Date(this.date)).setYear(year); return (this.navTo(target_date)); },
+ navTo: function(date) {
+ if (!this.validYear(date.getFullYear())) return false;
+ this.date = date;
+ this.date.setDate(1);
+ this.refresh();
+ this.callback("after_navigate", this.date);
+ return true;
+ },
+ setUseTime: function(turn_on) {
+ this.use_time = this.options.get("time") && (this.options.get("time")=="mixed" ? turn_on : true) // force use_time to true if time==true && time!="mixed"
+ if (this.use_time && this.selected_date) { // only set hour/minute if a date is already selected
+ var minute = Math.floor_to_interval(this.selected_date.getMinutes(), this.options.get("minute_interval"));
+ var hour = this.selected_date.getHours();
+
+ this.hour_select.setValue(hour);
+ this.minute_select.setValue(minute)
+ } else if (this.options.get("time")=="mixed") {
+ this.hour_select.setValue(""); this.minute_select.setValue("");
+ }
+ },
+ updateValue: function() {
+ var last_value = this.target_element.value;
+ this.target_element.value = this.dateString();
+ if (last_value!=this.target_element.value) this.callback("onchange");
+ },
+ today: function(now) {
+ var d = new Date(); this.date = new Date();
+ var o = $H({ day: d.getDate(), month: d.getMonth(), year: d.getFullYear(), hour: d.getHours(), minute: d.getMinutes()});
+ if ( ! now ) o = o.merge({hour: "", minute:""});
+ this.updateSelectedDate(o, true);
+ this.refresh();
+ },
+ close: function() {
+ if (this.closed) return false;
+ this.callback("before_close");
+ this.target_element.calendar_date_select = nil;
+ Event.stopObserving(document, "mousedown", this.closeIfClickedOut_handler);
+ Event.stopObserving(document, "keypress", this.keyPress_handler);
+ this.calendar_div.remove(); this.closed = true;
+ if (this.iframe) this.iframe.remove();
+ if (this.target_element.type!="hidden") this.target_element.focus();
+ this.callback("after_close");
+ },
+ closeIfClickedOut: function(e) {
+ if (! $(Event.element(e)).descendantOf(this.calendar_div) ) this.close();
+ },
+ keyPress: function(e) {
+ if (e.keyCode==Event.KEY_ESC) this.close();
+ },
+ callback: function(name, param) { if (this.options.get(name)) { this.options.get(name).bind(this.target_element)(param); } }
+}
34 public/javascripts/calendar_date_select/format_american.js
@@ -0,0 +1,34 @@
+// American Format: 12/31/2000 5:00 pm
+// Thanks, Wes Hays
+Date.prototype.toFormattedString = function(include_time){
+ str = Date.padded2(this.getMonth() + 1) + '/' +Date.padded2(this.getDate()) + '/' + this.getFullYear();
+
+ if (include_time) { hour=this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() + " " + this.getAMPM() }
+ return str;
+}
+
+Date.parseFormattedString = function (string) {
+ // Test these with and without the time
+ // 11/11/1111 12pm
+ // 11/11/1111 1pm
+ // 1/11/1111 10:10pm
+ // 11/1/1111 01pm
+ // 1/1/1111 01:11pm
+ // 1/1/1111 1:11pm
+ var regexp = "(([0-1]?[0-9])\/[0-3]?[0-9]\/[0-9]{4}) *([0-9]{1,2}(:[0-9]{2})? *(am|pm))?";
+ var d = string.match(new RegExp(regexp, "i"));
+ if (d==null) {
+ return Date.parse(string); // Give javascript a chance to parse it.
+ }
+
+ mdy = d[1].split('/');
+ hrs = 0;
+ mts = 0;
+ if(d[3] != null) {
+ hrs = parseInt(d[3].split('')[0], 10);
+ if(d[5].toLowerCase() == 'pm') { hrs += 12; } // Add 12 more to hrs
+ mts = d[4].split(':')[1];
+ }
+
+ return new Date(mdy[2], parseInt(mdy[0], 10)-1, mdy[1], hrs, mts, 0);
+}
27 public/javascripts/calendar_date_select/format_db.js
@@ -0,0 +1,27 @@
+// DB No Seconds Format: 2007-12-05 12:00
+
+Date.padded2 = function(hour) { padded2 = hour.toString(); if ((parseInt(hour) < 10) || (parseInt(hour) == null)) padded2="0" + padded2; return padded2; }
+Date.prototype.getAMPMHour = function() { hour=Date.padded2(this.getHours()); return (hour == null) ? 00 : (hour > 24 ? hour - 24 : hour ) }
+Date.prototype.getAMPM = function() { return (this.getHours() < 12) ? "" : ""; }
+
+Date.prototype.toFormattedString = function(include_time){
+ str = this.getFullYear() + "-" + (this.getMonth() + 1) + "-" + Date.padded2(this.getDate());
+ if (include_time) { hour=this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() }
+ return str;
+}
+
+Date.parseFormattedString = function (string) {
+ var regexp = '([0-9]{4})-(([0-9]{1,2})-(([0-9]{1,2})( ([0-9]{1,2}):([0-9]{2})? *)?)?)?';
+ var d = string.match(new RegExp(regexp, "i"));
+ if (d==null) return Date.parse(string); // at least give javascript a crack at it.
+ var offset = 0;
+ var date = new Date(d[1], 0, 1);
+ if (d[3]) { date.setMonth(d[3] - 1); }
+ if (d[5]) { date.setDate(d[5]); }
+ if (d[7]) {
+ date.setHours(parseInt(d[7], 10));
+ }
+ if (d[8]) { date.setMinutes(d[8]); }
+ if (d[10]) { date.setSeconds(d[10]); }
+ return date;
+}
7 public/javascripts/calendar_date_select/format_euro_24hr.js
@@ -0,0 +1,7 @@
+// Formats date and time as "01 January 2000 17:00"
+Date.prototype.toFormattedString = function(include_time)
+{
+ str = Date.padded2(this.getDate()) + " " + Date.months[this.getMonth()] + " " + this.getFullYear();
+ if (include_time) { str += " " + this.getHours() + ":" + this.getPaddedMinutes() }
+ return str;
+}
7 public/javascripts/calendar_date_select/format_euro_24hr_ymd.js
@@ -0,0 +1,7 @@
+// Formats date and time as "2000.01.20 17:00"
+Date.prototype.toFormattedString = function(include_time)
+{
+ str = this.getFullYear() + "." + Date.padded2(this.getMonth()+1) + "." + Date.padded2(this.getDate());
+ if (include_time) { str += " " + this.getHours() + ":" + this.getPaddedMinutes() }
+ return str;
+}
24 public/javascripts/calendar_date_select/format_finnish.js
@@ -0,0 +1,24 @@
+Date.padded2 = function(hour) { padded2 = hour.toString(); if ((parseInt(hour) < 10) || (parseInt(hour) == null)) padded2="0" + padded2; return padded2; }
+Date.prototype.getAMPMHour = function() { hour=Date.padded2(this.getHours()); return (hour == null) ? 00 : (hour > 24 ? hour - 24 : hour ) }
+Date.prototype.getAMPM = function() { return (this.getHours() < 12) ? "" : ""; }
+
+Date.prototype.toFormattedString = function(include_time){
+ str = this.getDate() + "." + (this.getMonth() + 1) + "." + this.getFullYear();
+ if (include_time) { hour=this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() }
+ return str;
+}
+Date.parseFormattedString = function (string) {
+ var regexp = '([0-9]{1,2})\.(([0-9]{1,2})\.(([0-9]{4})( ([0-9]{1,2}):([0-9]{2})? *)?)?)?';
+ var d = string.match(new RegExp(regexp, "i"));
+ if (d==null) return Date.parse(string); // at least give javascript a crack at it.
+ var offset = 0;
+ var date = new Date(d[5], 0, 1);
+ if (d[3]) { date.setMonth(d[3] - 1); }
+ if (d[5]) { date.setDate(d[1]); }
+ if (d[7]) {
+ date.setHours(parseInt(d[7], 10));
+ }
+ if (d[8]) { date.setMinutes(d[8]); }
+ if (d[10]) { date.setSeconds(d[10]); }
+ return date;
+}
36 public/javascripts/calendar_date_select/format_hyphen_ampm.js
@@ -0,0 +1,36 @@
+Date.prototype.toFormattedString = function(include_time){
+ str = this.getFullYear() + "-" + Date.padded2(this.getMonth() + 1) + "-" +Date.padded2(this.getDate());
+
+if (include_time) { hour=this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() + " " + this.getAMPM() }
+return str;
+}
+
+Date.parseFormattedString = function (string) {
+ var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
+ "( ([0-9]{1,2}):([0-9]{2})? *(pm|am)" +
+ "?)?)?)?";
+ var d = string.match(new RegExp(regexp, "i"));
+ if (d==null) return Date.parse(string); // at least give javascript a crack at it.
+ var offset = 0;
+ var date = new Date(d[1], 0, 1);
+ if (d[3]) { date.setMonth(d[3] - 1); }
+ if (d[5]) { date.setDate(d[5]); }
+ if (d[7]) {
+ hours = parseInt(d[7], 10);
+ offset=0;
+ is_pm = (d[9].toLowerCase()=="pm")
+ if (is_pm && hours <= 11) hours+=12;
+ if (!is_pm && hours == 12) hours=0;
+ date.setHours(hours);
+
+ }
+ if (d[8]) { date.setMinutes(d[8]); }
+ if (d[10]) { date.setSeconds(d[10]); }
+ if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
+ if (d[14]) {
+ offset = (Number(d[16]) * 60) + Number(d[17]);
+ offset *= ((d[15] == '-') ? 1 : -1);
+ }
+
+ return date;
+}
46 public/javascripts/calendar_date_select/format_iso_date.js
@@ -0,0 +1,46 @@
+Date.prototype.toFormattedString = function(include_time) {
+ var hour;
+ var str = this.getFullYear() + "-" + Date.padded2(this.getMonth() + 1) + "-" +Date.padded2(this.getDate());
+ if (include_time) {
+ hour = this.getHours();
+ str += " " + this.getHours() + ":" + this.getPaddedMinutes();
+ }
+ return str;
+};
+
+Date.parseFormattedString = function (string) {
+
+ var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
+ "( ([0-9]{1,2}):([0-9]{2})?" +
+ "?)?)?)?";
+
+ var d = string.match(new RegExp(regexp, "i"));
+ if (d === null) {
+ return Date.parse(string); // at least give javascript a crack at it.
+ }
+ var offset = 0;
+ var date = new Date(d[1], 0, 1);
+ if (d[3]) {
+ date.setMonth(d[3] - 1);
+ }
+ if (d[5]) {
+ date.setDate(d[5]);
+ }
+ if (d[7]) {
+ date.setHours(d[7]);
+ }
+ if (d[8]) {
+ date.setMinutes(d[8]);
+ }
+ if (d[0]) {
+ date.setSeconds(d[0]);
+ }
+ if (d[2]) {
+ date.setMilliseconds(Number("0." + d[2]));
+ }
+ if (d[4]) {
+ offset = (Number(d[6])) + Number(d[8]);
+ offset = ((d[5] == '-') ? 1 : -1);
+ }
+ return date;
+};
24 public/javascripts/calendar_date_select/format_italian.js
@@ -0,0 +1,24 @@
+// Italian Format: 31/12/2000 23:00
+// Thanks, Bigonazzi!
+
+Date.prototype.toFormattedString = function(include_time){
+ str = this.getDate() + "/" + (this.getMonth() + 1) + "/" + this.getFullYear();
+ if (include_time) { hour=this.getHours(); str += " " + this.getAMPMHour() + ":" + this.getPaddedMinutes() }
+ return str;
+}
+
+Date.parseFormattedString = function (string) {
+ var regexp = '([0-9]{1,2})/(([0-9]{1,2})/(([0-9]{4})( ([0-9]{1,2}):([0-9]{2})? *)?)?)?';
+ var d = string.match(new RegExp(regexp, "i"));
+ if (d==null) return Date.parse(string); // at least give javascript a crack at it.
+ var offset = 0;
+ var date = new Date(d[5], 0, 1);
+ if (d[3]) { date.setMonth(d[3] - 1); }
+ if (d[5]) { date.setDate(d[1]); }
+ if (d[7]) {
+ date.setHours(parseInt(d[7], 10));
+ }
+ if (d[8]) { date.setMinutes(d[8]); }
+ if (d[10]) { date.setSeconds(d[10]); }
+ return date;
+}
10 public/javascripts/calendar_date_select/locale/fi.js
@@ -0,0 +1,10 @@
+Date.weekdays = $w("Ma Ti Ke To Pe La Su");
+Date.months = $w("Tammikuu Helmikuu Maaliskuu Huhtikuu Toukokuu Kesäkuu Heinäkuu Elokuu Syyskuu Lokakuu Marraskuu Joulukuu" );
+
+Date.first_day_of_week = 1
+
+_translations = {
+ "OK": "OK",
+ "Now": "Nyt",
+ "Today": "Tänään"
+}
10 public/javascripts/calendar_date_select/locale/fr.js
@@ -0,0 +1,10 @@
+Date.weekdays = $w('L Ma Me J V S D');
+Date.months = $w('Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre Décembre');
+
+Date.first_day_of_week = 1;
+
+_translations = {
+ "OK": "OK",
+ "Now": "Maintenant",
+ "Today": "Aujourd'hui"
+}
10 public/javascripts/calendar_date_select/locale/pl.js
@@ -0,0 +1,10 @@
+Date.weekdays = $w('P W Ś C P S N');
+Date.months = $w('Styczeń Luty Marzec Kwiecień Maj Czerwiec Lipiec Sierpień Wrzesień Październik Listopad Grudzień');
+
+Date.first_day_of_week = 1
+
+_translations = {
+ "OK": "OK",
+ "Now": "Teraz",
+ "Today": "Dziś"
+}
10 public/javascripts/calendar_date_select/locale/pt.js
@@ -0,0 +1,10 @@
+Date.weekdays = $w('D S T Q Q S S');
+Date.months = $w('Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Novembro Dezembro');
+
+Date.first_day_of_week = 0
+
+_translations = {
+ "OK": "OK",
+ "Now": "Agora",
+ "Today": "Hoje"
+}
963 public/javascripts/controls.js
@@ -0,0 +1,963 @@
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;