Initial revision

master
penguinc 2006-09-08 05:57:50 +00:00
commit 50fd1b0dd5
721 changed files with 94113 additions and 0 deletions

153
README Normal file
View File

@ -0,0 +1,153 @@
== Welcome to Rails
Rails is a web-application and persistence framework that includes everything
needed to create database-backed web-applications according to the
Model-View-Control pattern of separation. This pattern splits the view (also
called the presentation) into "dumb" templates that are primarily responsible
for inserting pre-built data in between HTML tags. The model contains the
"smart" domain objects (such as Account, Product, Person, Post) that holds all
the business logic and knows how to persist themselves to a database. The
controller handles the incoming requests (such as Save New Account, Update
Product, Show Post) by manipulating the model and directing data to the view.
In Rails, the model is handled by what's called an object-relational mapping
layer entitled Active Record. This layer allows you to present the data from
database rows as objects and embellish these data objects with business logic
methods. You can read more about Active Record in
link:files/vendor/rails/activerecord/README.html.
The controller and view are handled by the Action Pack, which handles both
layers by its two parts: Action View and Action Controller. These two layers
are bundled in a single package due to their heavy interdependence. This is
unlike the relationship between the Active Record and Action Pack that is much
more separate. Each of these packages can be used independently outside of
Rails. You can read more about Action Pack in
link:files/vendor/rails/actionpack/README.html.
== Getting started
1. Run the WEBrick servlet: <tt>ruby script/server</tt> (run with --help for options)
...or if you have lighttpd installed: <tt>ruby script/lighttpd</tt> (it's faster)
2. Go to http://localhost:3000/ and get "Congratulations, you've put Ruby on Rails!"
3. Follow the guidelines on the "Congratulations, you've put Ruby on Rails!" screen
== Example for Apache conf
<VirtualHost *:80>
ServerName rails
DocumentRoot /path/application/public/
ErrorLog /path/application/log/server.log
<Directory /path/application/public/>
Options ExecCGI FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny
</Directory>
</VirtualHost>
NOTE: Be sure that CGIs can be executed in that directory as well. So ExecCGI
should be on and ".cgi" should respond. All requests from 127.0.0.1 go
through CGI, so no Apache restart is necessary for changes. All other requests
go through FCGI (or mod_ruby), which requires a restart to show changes.
== Debugging Rails
Have "tail -f" commands running on both the server.log, production.log, and
test.log files. 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.
== Breakpoints
Breakpoint support is available through the script/breakpointer client. This
means that you can break out of execution at any point in the code, investigate
and change the model, AND then resume execution! Example:
class WeblogController < ActionController::Base
def index
@posts = Post.find_all
breakpoint "Breaking out from the list"
end
end
So the controller will accept the action, run the first line, then present you
with a IRB prompt in the breakpointer window. Here you can do things like:
Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in 'breakpoint'
>> @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 breakpoint"
=> "hello from a breakpoint"
...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 press CTRL-D
== Console
You can interact with the domain model by starting the console through script/console.
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>console production</tt>.
== Description of contents
app
Holds all the code that's specific to this particular application.
app/controllers
Holds controllers that should be named like weblog_controller.rb for
automated URL mapping. All controllers should descend 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
weblog/index.rhtml for the WeblogController#index action. All views use eRuby
syntax. This directory can also be used to keep stylesheets, images, and so on
that can be symlinked to public.
app/helpers
Holds view helpers that should be named like weblog_helper.rb.
config
Configuration files for the Rails environment, the routing map, the database, and other dependencies.
components
Self-contained mini-applications that can bundle together controllers, models, and views.
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.
script
Helper scripts for automation and generation.
test
Unit and functional tests along with fixtures.
vendor
External libraries that the application depends on. Also includes the plugins subdirectory.
This directory is in the load path.

10
Rakefile Normal file
View File

@ -0,0 +1,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/switchtower.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'

View File

@ -0,0 +1,19 @@
class ActivityController < ApplicationController
append_before_filter :verify_identity
append_before_filter :add_refresh_link, :only => [ 'index' ]
append_before_filter :find_fund, :only => [ 'index' ]
##
# This method will display a list of the purchases for the fund, starting
# with the oldest. Also handily paginated by default. Lookit, four lines!
#
def index
unless @fund.nil?
@purchase_pages, @purchases = paginate :ledger, :order =>
"ledgers.post_date DESC, ledgers.created_at DESC",
:conditions => [ 'ledgers.fund_id = ?', @fund.id ],
:joins => "LEFT JOIN baristas ON ledgers.barista_id = baristas.id"
end
end
end

View File

@ -0,0 +1,124 @@
class ApplicationController < ActionController::Base
append_before_filter :session_setup
append_before_filter :link_setup
layout 'grindable'
##
# Method to determine if a user is authenticated. This might be more
# complicated in the future.
#
def authenticated?
session[:authenticated] == true
end
##
# A filter check to ensure that the person using the fund is authenticated
# in some way or another...
#
def verify_identity
# escape check
return true if authenticated?
# make 'em authenticate before continuing
session[:return_to] = request.request_uri
# nice one, bruddah. it's a route helper.
redirect_to login_url
end
##
# Sends the user to the default url. This could either be stored in the
# sesion or in the home_url method.
#
def goto_default_redirect_url
if session[:return_to].nil?
redirect_to home_url
else
redirect_to session[:return_to]
session[:return_to] = nil
end
end
##
# Redirects to the index action, useful since it is used in lots of places
#
def goto_index
redirect_to :action => 'index'
end
##
# Adds a related link to refresh the current action
#
def add_refresh_link
add_related_link 'Refresh'
end
##
# This will add a submenu item to be displayed
#
def add_related_link(*args)
@related_links.push [ *args ]
end
##
# This will add a submenu item for a javascript function
#
def add_related_function(what, where)
@related_functions.push [ what, where ]
end
##
# Adds an AJAX call to the submenu list
#
def add_remote_function(*args)
@related_remote.push [ *args ]
end
##
# Ensures that the method in question was called from a form, ie. POST
#
def ensure_post
return false unless request.post?
true
end
##
# Just like ensure_post only for AJAX requests...
#
def ensure_xhr
return false unless request.xhr?
true
end
##
# This configures the @fund variable for several methods as a before_filter.
#
def find_fund
return unless session[:barista] and session[:barista][:fund_id]
@fund = Fund.find session[:barista][:fund_id].to_i unless
session[:barista].nil?
end
private
##
# This should ensure a minimum session environment
#
def session_setup
if session[:authenticated].nil?
session[:barista] = nil
session[:authenticated] = false
end
true
end
##
# Creates the environment for the submenu of links
#
def link_setup
@related_links ||= []
@related_functions ||= []
@related_remote ||= []
end
end

View File

@ -0,0 +1,79 @@
class BaristaController < ApplicationController
append_before_filter :ensure_post, :only => [ 'add', 'delete', 'edit' ]
append_before_filter :add_refresh_link, :only => [ 'index' ]
append_before_filter :find_fund, :only => [ 'index' ]
##
# Lists all of the baristas in the system
#
def index
@pages, @baristas = paginate :baristas, :order => 'baristas.name ASC',
:per_page => 10, :include => 'fund'
add_related_function 'Create Barista',
("dojo.widget.byId('baristaDialog').show();" +
"dojo.byId('barista_name').focus()")
end
##
# Adds a new barista to the system.
#
def add
b = Barista.new params['barista']
begin
b.save!
flash[:info] = 'Successfully created a new barista!'
rescue => exception
flash[:error] = "Failed to create the barista: #{exception.to_s}"
end
goto_index
end
def delete
# not implemented yet
end
def edit
# nothing to edit, only the password really. and there's none of that now
end
##
# This method will identify the user -- basically an authenticate.
#
def identify
# user should probably not be here if they are already authenticated
goto_default_redirect_url if authenticated?
if request.post?
# mirror mirror on the wall, who is da funkiest of them all?
user_to_auth = Barista.find :first, :conditions => [ "name = ?",
params[:name] ]
if user_to_auth.nil?
# busted
flash.now[:error] = "You're going to have to try harder than that."
else
# ballin'
session[:authenticated] = true
session[:barista] = user_to_auth
flash[:info] = "Welcome to the Grindable!"
# shot callin'
goto_default_redirect_url
end
end
end
##
# This method should reset the user state to basic -- a deauthenticate.
#
def anonymize
# blank out all knowledge of the user
reset_session
# go home
goto_default_redirect_url
end
end

View File

@ -0,0 +1,121 @@
class CafeController < ApplicationController
append_before_filter :verify_identity
append_before_filter :ensure_post, :only => [ 'make_contribution',
'make_purchase', 'milk_purchased' ]
append_before_filter :add_refresh_link, :only => [ 'index' ]
append_before_filter :find_fund, :only => [ 'index', 'make_contribution',
'make_purchase' ]
append_before_filter :find_next_milk_purchaser, :only => [ 'index' ]
##
# The main coffee page.
#
def index
unless @fund.nil?
add_related_function 'Make Contribution',
"dojo.widget.byId('contributionDialog').show()"
add_related_function 'Make Purchase',
"dojo.widget.byId('purchaseDialog').show()"
add_related_function 'Milk Purchased',
"dojo.byId('milk_form').submit()" unless @fund.contribution == 0.0
end
end
##
# The method to confirm you bought milk.
#
def milk_purchased
l = Ledger.new
l.fund_id = session[:barista][:fund_id]
l.barista_id = session[:barista][:id]
l.comment = 'MILK'
l.post_date = Date.today
begin
l.save!
session[:barista].update_attribute 'milk_last_bought_at', Time.now
flash[:info] = 'You just purchased milk!'
rescue => exception
flash[:error] = 'There was a problem: #{exception.to_s}'
end
goto_index
end
##
# The method to make a contribution to the fund.
#
def make_contribution
# this is one of the more complicated procedures in the app
new_contribution = Ledger.new
# set the contribution amount from the fund
if @fund.contribution.nil? or @fund.contribution == 0
new_contribution.credit_amount = params[:contribution].to_f rescue 0.0
else
new_contribution.credit_amount = @fund.contribution
end
# update the fund balance
@fund.make_contribution new_contribution.credit_amount
new_contribution.barista_id = params[:contribution][:barista_id]
new_contribution.fund_id = session[:barista][:fund_id]
new_contribution.comment = 'CONTRIBUTION'
new_contribution.post_date = Date.today
begin
new_contribution.save!
quantity = params[:contribution][:quantity].to_i
if quantity > 1
(2..quantity).each do |q|
c = Ledger.new
c.attributes = new_contribution.attributes
c.post_date = new_contribution.post_date >> 1
c.save!
end
end
session[:barista].save!
@fund.save!
flash[:info] =
"Successfully contributed to the fund <strong>#{@fund.name}</strong>!"
rescue => exception
flash[:error] = "Failed to properly work: #{exception.to_s}"
end
goto_index
end
##
# The method for making a purchase out of general funds.
#
def make_purchase
new_purchase = Ledger.new
new_purchase.debit_amount = params[:amount]
new_purchase.comment = params[:comment]
new_purchase.barista_id = session[:barista][:id]
new_purchase.fund_id = session[:barista][:fund_id]
new_purchase.post_date = Date.today
@fund.make_purchase new_purchase.debit_amount
begin
new_purchase.save!
session[:barista].save!
@fund.save!
flash[:info] = "Successfully purchased ... supplies!"
rescue => exception
flash[:error] = "Failed to work properly: #{exception.to_s}"
end
goto_index
end
private
##
# A simple helper to find the next person to buy milk.
#
def find_next_milk_purchaser
return if @fund.nil?
@next_milk_purchaser = Barista.find :first,
:order => "milk_last_bought_at ASC",
:conditions => [ 'fund_id = ?', @fund.id ]
end
end

View File

@ -0,0 +1,68 @@
class FundController < ApplicationController
in_place_edit_for :fund, :contribution
append_before_filter :ensure_post, :only => [ 'add', 'delete', 'use' ]
append_before_filter :add_refresh_link, :only => [ 'index' ]
def index
@funds = Fund.find :all, :include => [ 'baristas' ]
add_related_function 'Add Fund', "dojo.widget.byId('fundDialog').show()"
end
def add
allowed_parameters = [ 'name', 'contribution' ]
params.delete_if { |key, value| !allowed_parameters.include? key }
begin
fund = Fund.new params
fund.contribution = 0.0 if params[:contribution].nil? or
params[:contribution].empty?
fund.balance = 0.0
fund.save!
flash[:info] = 'Word, success!'
rescue => exception
flash[:error] = 'There was a problem saving the fund: ' +
exception.to_s
end
redirect_to :action => 'index'
end
def delete
fund = Fund.find params[:id].to_i
if fund.nil?
flash[:error] = 'That fund does not exist!'
else
old_name = fund[:name]
begin
fund.destroy
flash[:info] = "The fund #{old_name} has been deleted."
rescue => exception
flash[:error] = "Encountered a problem while removing the fund: " +
exception.to_s
end
end
goto_index
end
def use
fund = Fund.find params[:id].to_i
if fund.nil?
flash[:error] = 'That fund does not exist!'
else
session[:barista][:fund_id] = params[:id]
begin
session[:barista].save!
session[:barista].reload
rescue => exception
flash[:error] = "Failed while updating the user: #{exception.to_s}"
else
flash[:info] = 'Successfully updated the user fund.'
end
end
goto_index
end
end

View File

@ -0,0 +1,2 @@
module ActivityHelper
end

View File

@ -0,0 +1,21 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
def escape_preserving_linefeeds(text)
h(text).gsub(/\n/, '<br/>')
end
def escape_preserving_linefeeds_and_html(text)
text.gsub(/\n/, '<br/>')
end
def display_amount(amount)
return '' if amount.nil?
sprintf("$%0.2f", amount)
end
def display_date(date)
return '' if date.nil?
"#{date.month}-#{date.day}-#{date.year}"
end
end

View File

@ -0,0 +1,2 @@
module BaristaHelper
end

View File

@ -0,0 +1,2 @@
module CafeHelper
end

View File

@ -0,0 +1,2 @@
module FundHelper
end

37
app/models/barista.rb Normal file
View File

@ -0,0 +1,37 @@
class Barista < ActiveRecord::Base
has_many :ledgers, :order => "created_at ASC"
belongs_to :fund
validates_presence_of :fund
validates_length_of :name, :within => 6..64
def self.for_select(fund_id = nil)
if fund_id.nil?
arr = self.find :all, :order => 'name ASC', :select => 'id, name'
else
arr = self.find :all, :order => 'name ASC', :select => 'id, name',
:conditions => [ 'fund_id = ?', fund_id ]
end
arr.collect do |b|
[ b.name, b.id.to_s ]
end
end
def paid_this_month?
this_month = Date.new(Date.today.year, Date.today.month, 1)
next_month = (this_month >> 1) - 1
variables = { :this_month => this_month, :next_month => next_month,
:fund_id => self.fund_id }
query_str = []
query_str << 'post_date >= :this_month'
query_str << 'post_date <= :next_month'
query_str << 'credit_amount IS NOT NULL'
query_str << 'fund_id = :fund_id'
return false if (self.ledgers.find :first,
:conditions => [ query_str.join(' AND '), variables ]).nil?
true
end
end

23
app/models/fund.rb Normal file
View File

@ -0,0 +1,23 @@
class Fund < ActiveRecord::Base
validates_numericality_of :balance, :contribution
validates_uniqueness_of :name
has_many :baristas
has_many :ledgers, :dependent => true
def make_contribution(amount)
self[:balance] += amount
end
def make_purchase(amount)
self[:balance] -= amount
end
def self.for_select
self.find(:all, :select => 'id, name').collect { |f| [ f.name, f.id.to_s ] }
end
def before_destroy
raise "Fund still has baristas!" unless self.baristas.empty?
end
end

6
app/models/ledger.rb Normal file
View File

@ -0,0 +1,6 @@
class Ledger < ActiveRecord::Base
belongs_to :barista
belongs_to :fund
validates_numericality_of :debit_amount, :credit_amount, :allow_nil => true
end

View File

@ -0,0 +1,13 @@
<% @fund_counter ||= 0 -%>
<% if @fund_counter % 2 == 0 -%>
<tr id="line_<%= purchase.id -%>" class="even">
<% else -%>
<tr id="line_<%= purchase.id -%>" class="odd">
<% end -%>
<td><%= purchase.comment -%></td>
<td align="center"><%= purchase.name -%></td>
<td><%= display_date purchase.post_date -%></td>
<td align="right"><%= display_amount purchase.debit_amount -%></td>
<td align="right"><%= display_amount purchase.credit_amount -%></td>
</tr>
<% @fund_counter += 1 -%>

View File

@ -0,0 +1,26 @@
<% @content_title = "Fund Activity :: #{@fund.name rescue 'None!'}" -%>
<%= render :partial => 'shared/menu' %>
<% unless @fund.nil? -%>
<div class="formRequest">
<table cellspacing="0" class="collectionList" width="100%">
<tr>
<th width="35%"><strong>Comment</strong></th>
<th width="30%"><strong>Barista</strong></th>
<th width="15%"><strong>Date</strong></th>
<th width="10%"><strong>-</strong></th>
<th width="10%"><strong>+</strong></th>
</tr>
<tr><td colspan="5"><hr noshade /></td></tr>
<%= render :partial => "purchase", :collection => @purchases %>
<tr><td colspan="5"><hr noshade /></td></tr>
</table>
</div>
<div style="margin: 10px 0px 10px 0px" align="center"><%= pagination_links @purchase_pages %></div>
<% else -%>
<div class="formRequest">
<p>Visit the <%= link_to 'Fund Controller', :controller => 'fund' -%> to configure funds and change your associated fund.</p>
</div>
<% end -%>

View File

@ -0,0 +1,11 @@
<% @fund_counter ||= 0 -%>
<% if @fund_counter % 2 == 0 -%>
<tr id="line_<%= barista.id -%>" class="even">
<% else -%>
<tr id="line_<%= barista.id -%>" class="odd">
<% end -%>
<td><%= barista.name -%></td>
<td align="center"><%= barista.fund.name rescue 'None' -%></td>
<td align="center"><%= display_date barista.created_on -%></td>
</tr>
<% @fund_counter += 1 -%>

View File

@ -0,0 +1,8 @@
<% @content_title = 'Identification required' -%>
<div class="formRequest">
<%= form_tag :action => :identify %>
<p>Name: <%= text_field_tag "name", nil, :size => 32, :maxlength => 64, :class => "inputBox" %></p>
<p><%= submit_tag "Login", :class => "inputBox" %></p>
<%= end_form_tag %>
</div>

View File

@ -0,0 +1,37 @@
<% @content_title = 'Barista Summary' -%>
<%= render :partial => 'shared/menu' %>
<div class="formRequest">
<table cellspacing="0" class="collectionList" width="100%">
<tr>
<th><strong>Name</strong></th>
<th width="15%"><strong>Fund</strong></th>
<th width="15%"><strong>Date Joined</strong></th>
</tr>
<tr><td colspan="3"><hr noshade /></td></tr>
<%= render :partial => "barista", :collection => @baristas %>
<tr><td colspan="3"><hr noshade /></td></tr>
</table>
</div>
<div style="margin: 10px 0px 10px 0px" align="center"><%= pagination_links @pages %></div>
<script>dojo.require('dojo.widget.Dialog');</script>
<div id="baristaDialog" class="dialogBox" style="display:none">
<%= form_tag( { :action => 'add' }, { :id => 'barista_form' }) %>
<table>
<tr><th colspan="2"><h2>Add A Barista</h2></th></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td align="right">Name</td><td><%= text_field 'barista', 'name', :class => 'inputBox', :size => 16, :maxsize => 64 -%></td></tr>
<tr><td align="right">Fund</td><td><%= select('barista', 'fund_id', Fund.for_select, { :selected => (@fund.id.to_s rescue '') }, { :class => 'inputBox' }) -%></td></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td colspan="2"><%= submit_tag 'Create', :class => 'inputBox' -%> | <%= link_to_function 'Cancel', "dojo.widget.byId('baristaDialog').hide();dojo.byId('barista_form').reset()" -%></td></tr>
</table>
<%= end_form_tag %>
</div>
<%
@dojo_map ||= {}
@dojo_map['baristaDialog'] = ['dialog', '{bgColor: "black", bgOpacity: "0.5"}']
%>

View File

@ -0,0 +1,91 @@
<% @content_title = 'Grindable Home' -%>
<%= render :partial => 'shared/menu' %>
<div id="fundBox">
<h2>Fund details</h2>
<% if @fund.nil? -%>
<p><em><strong>You have no associated fund!</strong></em></p>
<p>Visit the <%= link_to 'Fund Controller', :controller => 'fund' -%> to configure funds and change your associated fund.</p>
<% else -%>
<ul>
<li>Fund name: <strong><%= h(@fund.name) -%></strong></li>
<li>Total fund balance is: <%= display_amount @fund.balance -%></li>
<% unless @fund.contribution == 0.0 -%>
<li>Monthly contribution: <%= display_amount @fund.contribution -%></li>
<% end -%>
</ul>
<% unless @fund.contribution == 0.0 -%>
<% if session[:barista].paid_this_month? -%>
<p>You have paid this month's contribution.</p>
<% else -%>
<em><p>You have not paid this month</p></em>
<% end -%>
<% end -%>
<% end -%>
</div>
<% unless @fund.nil? or @fund.contribution == 0.0 -%>
<div id="milkBox">
<h2>Milk Purchases</h2>
<%= form_tag({ :action => 'milk_purchased' }, { :id => 'milk_form' }) -%>
<%= end_form_tag -%>
<% unless session[:barista].milk_last_bought_at.nil? -%>
<p>You last bought milk <strong><%= time_ago_in_words session[:barista].milk_last_bought_at -%></strong> ago.</p>
<% else -%>
<em><p>You have never bought milk!</p></em>
<% end -%>
<% unless @next_milk_purchaser.id == session[:barista].id -%>
<p>The next person to buy milk will be: <strong><%= h(@next_milk_purchaser.name) -%></strong></p>
<% else -%>
<em><p>You will have to buy milk next.</p></em>
<% end -%>
</div>
<% end -%>
<% unless @fund.nil? -%>
<script>dojo.require('dojo.widget.Dialog');</script>
<div id="contributionDialog" class="dialogBox" style="display:none">
<%= form_tag( { :action => 'make_contribution' }, { :id => 'contribution_form' }) %>
<table>
<tr><th colspan="2"><h2>Make A Contribution</h2></th></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td align="right">Barista</td><td><%= select('contribution', 'barista_id', Barista.for_select(@fund.id), { :selected => session[:barista][:id] }, { :class => 'inputBox' }) -%></td></tr>
<% if @fund.contribution == 0.0 -%>
<tr><td align="right">Amount</td><td><%= text_field_tag 'contribution', nil, :class => 'inputBox', :size => 10, :maxsize => 12 -%></td></tr>
<% else -%>
<%
quantity_select = [ [ 'This month', 1 ] ]
(2..6).each do |i|
quantity_select << [ "Next #{i} months", i ]
end
%>
<tr><td align="right">Quantity</td><td><%= select 'contribution', 'quantity', quantity_select, {}, { :class => 'inputBox' } -%></td></tr>
<% end -%>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td colspan="2"><%= submit_tag 'Go', :class => 'inputBox' -%> | <%= link_to_function 'Cancel', "dojo.widget.byId('contributionDialog').hide();dojo.byId('contribution_form').reset()" -%></td></tr>
</table>
<%= end_form_tag %>
</div>
<div id="purchaseDialog" class="dialogBox" style="display:none">
<%= form_tag( { :action => 'make_purchase' }, { :id => 'purchase_form' }) %>
<table>
<tr><th colspan="2"><h2>Make A Purchase</h2></th></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td align="right">Amount:<br /><small>(<em><strong>XXX.XX</strong></em>)</small></td><td><%= text_field_tag 'amount', nil, :size => 10, :maxlength => 12, :class => 'inputBox' -%></td></tr>
<tr><td align="right">Comment:</td><td><%= text_field_tag 'comment', nil, :size => 32, :maxlength => 64, :class => 'inputBox' -%></td></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td colspan="2"><%= submit_tag 'Buy', :class => 'inputBox' -%> | <%= link_to_function 'Cancel', "dojo.widget.byId('purchaseDialog').hide();dojo.byId('purchase_form').reset()" -%></td></tr>
</table>
<%= end_form_tag %>
</div>
<%
@dojo_map ||= {}
@dojo_map['contributionDialog'] = ['dialog', '{bgColor: "black", bgOpacity: "0.5"}']
@dojo_map['purchaseDialog'] = ['dialog', '{bgColor: "black", bgOpacity: "0.5"}']
%>
<% end -%>

View File

@ -0,0 +1,14 @@
<% @fund_counter ||= 0 -%>
<% if @fund_counter % 2 == 0 -%>
<tr id="line_<%= @fund.id -%>" class="even">
<% else -%>
<tr id="line_<%= @fund.id -%>" class="odd">
<% end -%>
<td align="center"><%= link_to image_tag('go-home-16.png', :alt => 'Use', :title => 'Use this fund'), { :action => 'use', :id => @fund.id }, :post => true -%></td>
<td align="center"><%= link_to image_tag('edit-delete-16.png', :alt => 'Delete', :title => 'Delete Fund'), { :action => 'delete', :id => @fund.id }, :post => true -%></td>
<td><strong><%= @fund.name -%></strong></td>
<td align="right"><%= display_amount @fund.balance -%></td>
<td align="right"><%= in_place_editor_field :fund, :contribution -%></td>
<td align="right"><%= @fund.baristas.size -%></td>
</tr>
<% @fund_counter += 1 -%>

View File

@ -0,0 +1,35 @@
<% @content_title = 'Fund Summary' -%>
<%= render :partial => "shared/menu" %>
<div class="formRequest">
<table cellspacing="0" class="collectionList" width="100%">
<tr>
<th width="10%">Use</th>
<th width="10%">Delete</th>
<th width="40%">Name</th>
<th width="15%">Balance</th>
<th width="15%">Contribution</th>
<th width="10%">Size</th>
</tr>
<tr><td colspan="6"><hr noshade /></td></tr>
<% @funds.each do |@fund| -%>
<%= render :partial => 'fund_line' %>
<% end -%>
<tr><td colspan="6"><hr noshade /></td></tr>
</table>
</div>
<script>dojo.require('dojo.widget.Dialog');</script>
<div id="fundDialog" class="dialogBox" style="display:none">
<%= form_tag( { :action => 'add' }, { :id => 'add_fund_form' }) %>
<table>
<tr><th colspan="2"><h2>New Fund Details</h2></th></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td align="right">Name</td><td><%= text_field_tag 'name', nil, :class => 'inputBox', :size => 16, :maxlength => 64 -%></td></tr>
<tr><td align="right">Contribution<br /><small><strong>XXX.XX</strong></small></td><td><%= text_field_tag 'contribution', nil, :class => 'inputBox', :size => 10, :maxlength => 12 -%></td></tr>
<tr><td colspan="2"><hr noshade /></td></tr>
<tr><td colspan="2"><%= submit_tag 'Add', :class => 'inputBox' -%> | <%= link_to_function 'Cancel', "dojo.widget.byId('fundDialog').hide();dojo.byId('add_fund_form').reset()" -%></td></tr>
<%= end_form_tag %>
</div>
<% @dojo_map ||= {} ; @dojo_map['fundDialog'] = ['dialog', '{bgColor: "black", bgOpacity: "0.5"}'] %>

View File

@ -0,0 +1,102 @@
<!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">
<head>
<title>
Grindable :: The coffee funding
</title>
<script type="text/javascript">
djConfig = { isDebug: false };
</script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<%= stylesheet_link_tag "grindable", :media => :all %>
<%= javascript_include_tag :defaults %>
<%= javascript_include_tag 'dojo/dojo.js' %>
<script type="text/javascript">
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else {
window.onload = function() {
oldonload();
func();
}
}
}
// attach an event properly
function attachEvent(element, type, event) {
if(element.attachEvent) {
element.attachEvent('on' + type, event);
}
else {
element.addEventListener(type, event, false);
}
}
</script>
<% if @dojo_map and @dojo_map.length>0 %>
<script type="text/javascript">
//var widget_ids = {};
addLoadEvent( function() {
<% @dojo_map.each do |k,v| %>
var emt_<%= k %> = document.getElementById('<%= k %>');
if (!emt_<%= k %>) {
alert("MISSING ELEMENT FOR DOJO: <%= k %>");
} else {
var e = null;
try {
var widget_<%= k %> = dojo.widget.createWidget('<%= v[0] %>', <%= v[1] %>, emt_<%= k %>);
} catch (ex) {
e = ex;
}
if (e || !widget_<%= k %>) {
alert("Unable to create widget: <%= k %>: <%= v[0] %>: " + e);
}
else {
widget_<%= k %>.widgetId = '<%= k %>';
dojo.widget.manager.add(widget_<%= k %>);
}
}
<% end %>
});
</script>
<% end %>
<script type="text/javascript">
<%= @content_for_script %>
</script>
</head>
<body>
<div id="Container">
<div id="Content">
<% unless @content_title.nil? -%>
<h1><%= @content_title %></h1>
<% end -%>
<% if @flash[:error] -%>
<div id="errorExplanation"><%= escape_preserving_linefeeds_and_html @flash[:error] %></div>
<% end -%>
<% if @flash[:info] -%>
<div id="info"><%= escape_preserving_linefeeds_and_html @flash[:info] %></div>
<% end %>
<%= @content_for_layout %>
</div> <!-- Content -->
</div> <!-- Container -->
</body>
</html>

View File

@ -0,0 +1,19 @@
<div class="menu" id="menuBar">
<p>
<%= link_to_unless_current 'Cafe', :controller => 'cafe' -%> |
<%= link_to_unless_current 'Activity Log', :controller => 'activity' -%> |
<%= link_to_unless_current 'Fund Manager', :controller => 'fund' -%> |
<%= link_to_unless_current 'Barista Manager', :controller => 'barista' -%> |
<%= link_to "Logout", :controller => 'barista', :action => 'anonymize' -%>
</p>
</div>
<div id="relatedLinks">
<p>
<%= @related_links.collect { |*x| link_to *x[0] }.join(' | ') -%>
<%= " | " unless @related_links.empty? or @related_functions.empty? -%>
<%= @related_functions.collect { |what, where| link_to_function what, where }.join(' | ') %>
<%= " | " unless @related_functions.empty? or @related_remote.empty? -%>
<%= @related_remote.collect { |*x| link_to_remote *x[0] }.join(' | ') -%>
</p>
</div>

19
config/boot.rb Normal file
View File

@ -0,0 +1,19 @@
# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
unless defined?(RAILS_ROOT)
root_path = File.join(File.dirname(__FILE__), '..')
unless RUBY_PLATFORM =~ /mswin32/
require 'pathname'
root_path = Pathname.new(root_path).cleanpath(true).to_s
end
RAILS_ROOT = root_path
end
if File.directory?("#{RAILS_ROOT}/vendor/rails")
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
else
require 'rubygems'
require 'initializer'
end
Rails::Initializer.run(:set_load_path)

View File

@ -0,0 +1,35 @@
development:
development_postgres
test:
test_postgres
production:
production_postgres
development_postgres:
adapter: postgresql
socket: /tmp/s.PGSQL.5432
database: grindable_development
username: postgres
password:
test_postgres:
adapter: postgresql
socket: /tmp/s.PGSQL.5432
database: grindable_test
username: postgres
password:
production_postgres:
adapter: postgresql
socket: /tmp/s.PGSQL.5432
database: grindable_production
username: postgres
password:
development_sqlite3:
adapter: sqlite3
database: db/development.sqlite3
test_sqlite3:
adapter: sqlite3
database: db/test.sqlite3
production_sqlite3:
adapter: sqlite3
database: db/production.sqlite3

53
config/environment.rb Normal file
View File

@ -0,0 +1,53 @@
# Be sure to restart your web 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'
# 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 those specified here
# Skip frameworks you're not going to use
# config.frameworks -= [ :action_web_service, :action_mailer ]
# 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
# Use the database for sessions instead of the file system
# (create the session table with 'rake create_sessions_table')
# config.action_controller.session_store = :active_record_store
# Enable page/fragment caching by setting a file-based store
# (remember to create the caching directory and make it readable to the application)
# config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/cache"
# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector
# Make Active Record use UTC-base instead of local time
# config.active_record.default_timezone = :utc
# Use Active Record's schema dumper instead of SQL when creating the test database
# (enables use of different database adapters for development and test environments)
# config.active_record.schema_format = :ruby
# See Rails::Configuration for more options
end
# 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
# Include your application configuration below

View File

@ -0,0 +1,19 @@
# 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
# Enable the breakpoint server that script/breakpointer connects to
config.breakpoint_server = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false

View File

@ -0,0 +1,19 @@
# Settings specified here will take precedence over those in config/environment.rb
# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
config.cache_classes = true
# Use a different logger for distributed setups
# config.logger = SyslogLogger.new
# Full error reports are disabled and caching is turned on
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Disable delivery errors if you bad email addresses should just be ignored
# config.action_mailer.raise_delivery_errors = false

View File

@ -0,0 +1,19 @@
# Settings specified here will take precedence over those in config/environment.rb
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Tell ActionMailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test

9
config/routes.rb Normal file
View File

@ -0,0 +1,9 @@
ActionController::Routing::Routes.draw do |map|
map.connect '', :controller => 'cafe', :action => 'index'
map.home '', :controller => 'cafe', :action => 'index'
map.login '/barista/login', :controller => 'barista', :action => 'identify'
map.connect ':controller/service.wsdl', :action => 'wsdl'
map.connect ':controller/:action/:id'
end

View File

@ -0,0 +1,28 @@
class BaseSchema < ActiveRecord::Migration
def self.up
create_table :funds do |t|
t.column :name, :string, { :limit => 64 }
t.column :created_at, :datetime
t.column :balance, :float
t.column :contribution, :float
end
create_table :baristas do |t|
t.column :name, :string, { :limit => 64, :null => false }
t.column :milk_last_bought_at, :datetime
end
create_table :ledgers do |t|
t.column :barista_id, :integer, { :null => false }
t.column :created_at, :datetime
t.column :credit_amount, :float
t.column :debit_amount, :float
end
add_index :ledgers, :barista_id
end
def self.down
raise 'IrreversibleMigration: You cannot remove the base schema!'
end
end

View File

@ -0,0 +1,10 @@
class AddFindToBarista < ActiveRecord::Migration
def self.up
add_column :baristas, :fund_id, :integer
add_index :baristas, :fund_id
end
def self.down
drop_column :baristas, :fund_id
end
end

View File

@ -0,0 +1,9 @@
class AddLedgerComment < ActiveRecord::Migration
def self.up
add_column :ledgers, :comment, :string, { :limit => 64 }
end
def self.down
drop_column :ledgers, :comment
end
end

View File

@ -0,0 +1,11 @@
class AddLedgerFundRelationship < ActiveRecord::Migration
def self.up
add_column :ledgers, :fund_id, :integer
add_index :ledgers, :fund_id
end
def self.down
drop_column :ledgers, :fund_id
drop_index :ledgers, :fund_id
end
end

View File

@ -0,0 +1,9 @@
class AddBaristaCreateDate < ActiveRecord::Migration
def self.up
add_column :baristas, :created_on, :date
end
def self.down
drop_column :baristas, :created_on
end
end

View File

@ -0,0 +1,9 @@
class LedgerPostDate < ActiveRecord::Migration
def self.up
add_column :ledgers, :post_date, :date
end
def self.down
remove_column :ledgers, :post_date
end
end

36
db/schema.rb Normal file
View File

@ -0,0 +1,36 @@
# This file is autogenerated. Instead of editing this file, please use the
# migrations feature of ActiveRecord to incrementally modify your database, and
# then regenerate this schema definition.
ActiveRecord::Schema.define(:version => 6) do
create_table "baristas", :force => true do |t|
t.column "name", :string, :limit => 64, :null => false
t.column "milk_last_bought_at", :datetime
t.column "fund_id", :integer
t.column "created_on", :date
end
add_index "baristas", ["fund_id"], :name => "baristas_fund_id_index"
create_table "funds", :force => true do |t|
t.column "name", :string, :limit => 64
t.column "created_at", :datetime
t.column "balance", :float
t.column "contribution", :float
end
create_table "ledgers", :force => true do |t|
t.column "barista_id", :integer, :null => false
t.column "created_at", :datetime
t.column "credit_amount", :float
t.column "debit_amount", :float
t.column "comment", :string, :limit => 64
t.column "fund_id", :integer
t.column "post_date", :date
end
add_index "ledgers", ["barista_id"], :name => "ledgers_barista_id_index"
add_index "ledgers", ["fund_id"], :name => "ledgers_fund_id_index"
end

2
doc/README_FOR_APP Normal file
View File

@ -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 appdoc" to generate API documentation for your models and controllers.

91
grindable.kdevelop Normal file
View File

@ -0,0 +1,91 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>Andrew Coleman</author>
<email>mercury@penguincoder.org</email>
<version>$VERSION$</version>
<projectmanagement>KDevScriptProject</projectmanagement>
<primarylanguage>Ruby</primarylanguage>
<keywords>
<keyword>Ruby</keyword>
</keywords>
<ignoreparts>
<part>KDevDoxygen</part>
<part>KDevdistpart</part>
<part>KDevVisualBoyAdvance</part>
<part>KDevDebugger</part>
</ignoreparts>
</general>
<kdevscriptproject>
<general>
<activedir>src</activedir>
<includepatterns>*.rb</includepatterns>
<excludepatterns>*~</excludepatterns>
</general>
<run>
<directoryradio>executable</directoryradio>
</run>
</kdevscriptproject>
<kdevfileview>
<groups>
<group pattern="*.rb" name="Scripts" />
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
</tree>
</kdevfileview>
<kdevdoctreeview>
<ignoretocs>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>c++_bugs_gcc</toc>
<toc>clanlib</toc>
<toc>w3c-dom-level2-html</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>libc</toc>
<toc>libstdc++</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>sdl</toc>
<toc>stl</toc>
<toc>w3c-svg</toc>
<toc>sw</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoreqt_xml>
<toc>Guide to the Qt Translation Tools</toc>
<toc>Qt Assistant Manual</toc>
<toc>Qt Designer Manual</toc>
<toc>Qt Reference Documentation</toc>
<toc>qmake User Guide</toc>
</ignoreqt_xml>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevfilecreate>
<useglobaltypes>
<type ext="rb" />
</useglobaltypes>
</kdevfilecreate>
</kdevelop>

33
grindable.kdevses Normal file
View File

@ -0,0 +1,33 @@
<?xml version = '1.0' encoding = 'UTF-8'?>
<!DOCTYPE KDevPrjSession>
<KDevPrjSession>
<DocsAndViews NumberOfDocuments="6" >
<Doc0 NumberOfViews="1" URL="file:///home/andrew/Projects/grindable/app/controllers/fund_controller.rb" >
<View0 Type="Source" />
</Doc0>
<Doc1 NumberOfViews="1" URL="file:///home/andrew/Projects/grindable/app/views/fund/index.rhtml" >
<View0 Type="Source" />
</Doc1>
<Doc2 NumberOfViews="1" URL="file:///home/andrew/Projects/grindable/app/views/shared/_fund.rhtml" >
<View0 Type="Source" />
</Doc2>
<Doc3 NumberOfViews="1" URL="file:///home/andrew/Projects/grindable/app/views/fund/_fund_line.rhtml" >
<View0 Type="Source" />
</Doc3>
<Doc4 NumberOfViews="1" URL="file:///home/andrew/Projects/grindable/app/models/barista.rb" >
<View0 Type="Source" />
</Doc4>
<Doc5 NumberOfViews="1" URL="file:///home/andrew/Projects/grindable/app/controllers/application.rb" >
<View0 line="83" Type="Source" />
</Doc5>
</DocsAndViews>
<pluginList>
<kdevbookmarks>
<bookmarks/>
</kdevbookmarks>
<kdevrbdebugger>
<breakpointList/>
<watchExpressions/>
</kdevrbdebugger>
</pluginList>
</KDevPrjSession>

View File

@ -0,0 +1,9 @@
desc "Creates the fund for managing."
task :create_fund => :environment do
begin
fund = Fund.new
fund.save!
rescue => exception
puts "Failed: #{exception.inspect}"
end
end

View File

@ -0,0 +1,15 @@
desc "Makes an user without the use of the web interface"
task :create_user => :environment do
begin
account = Barista.new
print "Give me a username: "
account.name = STDIN.gets.chomp
#print "Password: "
#password = STDIN.gets.chomp
#account.set_password password, password
#account.activated = true
account.save_with_validation false
rescue => exception
puts "Failed: #{exception.inspect}"
end
end

40
public/.htaccess Normal file
View File

@ -0,0 +1,40 @@
# 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"

8
public/404.html Normal file
View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<h1>File not found</h1>
<p>Change this error message for pages not found in public/404.html</p>
</body>
</html>

8
public/500.html Normal file
View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<h1>Application error (Apache)</h1>
<p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p>
</body>
</html>

10
public/dispatch.cgi Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/ruby18
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 Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/ruby18
#
# 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 Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/ruby18
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 Normal file
View File

BIN
public/images/balance.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/images/rails.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

750
public/javascripts/controls.js vendored Normal file
View File

@ -0,0 +1,750 @@
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// See scriptaculous.js for full license.
// 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.
var Autocompleter = {}
Autocompleter.Base = function() {};
Autocompleter.Base.prototype = {
baseInitialize: function(element, update, options) {
this.element = $(element);
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
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);
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
(navigator.appVersion.indexOf('MSIE')>0) &&
(navigator.userAgent.indexOf('Opera')<0) &&
(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);
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
if(this.active)
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.markPrevious();
this.render();
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN)
return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
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;
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++
else this.index = 0;
},
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
getCurrentEntry: function() {
return this.getEntry(this.index);
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var lastTokenPos = this.findLastToken();
if (lastTokenPos != -1) {
var newValue = this.element.value.substr(0, lastTokenPos + 1);
var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
this.element.value = newValue + value;
} else {
this.element.value = value;
}
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.firstChild);
if(this.update.firstChild && this.update.firstChild.childNodes) {
this.entryCount =
this.update.firstChild.childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
this.render();
}
},
addObservers: function(element) {
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},
onObserverEvent: function() {
this.changed = false;
if(this.getToken().length>=this.options.minChars) {
this.startIndicator();
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
},
getToken: function() {
var tokenPos = this.findLastToken();
if (tokenPos != -1)
var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
else
var ret = this.element.value;
return /\n/.test(ret) ? '' : ret;
},
findLastToken: function() {
var lastTokenPos = -1;
for (var i=0; i<this.options.tokens.length; i++) {
var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
if (thisTokenPos > lastTokenPos)
lastTokenPos = thisTokenPos;
}
return lastTokenPos;
}
}
Ajax.Autocompleter = Class.create();
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
Autocompleter.Local = Class.create();
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
},
getUpdatedChoices: function() {
this.updateChoices(this.options.selector(this));
},
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
return "<ul>" + ret.join('') + "</ul>";
}
}, options || {});
}
});
// AJAX in-place editor
//
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
}
Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = {
initialize: function(element, url, options) {
this.url = url;
this.element = $(element);
this.options = Object.extend({
okText: "ok",
cancelText: "cancel",
savingText: "Saving...",
clickToEditText: "Click to edit",
okText: "ok",
rows: 1,
onComplete: function(transport, element) {
new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
},
onFailure: function(transport) {
alert("Error communicating with the server: " + transport.responseText.stripTags());
},
callback: function(form) {
return Form.serialize(form);
},
handleLineBreaks: true,
loadingText: 'Loading...',
savingClassName: 'inplaceeditor-saving',
loadingClassName: 'inplaceeditor-loading',
formClassName: 'inplaceeditor-form',
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
highlightendcolor: "#FFFFFF",
externalControl: null,
ajaxOptions: {}
}, options || {});
if(!this.options.formId && this.element.id) {
this.options.formId = this.element.id + "-inplaceeditor";
if ($(this.options.formId)) {
// there's already a form with that name, don't specify an id
this.options.formId = null;
}
}
if (this.options.externalControl) {
this.options.externalControl = $(this.options.externalControl);
}
this.originalBackground = Element.getStyle(this.element, 'background-color');
if (!this.originalBackground) {
this.originalBackground = "transparent";
}
this.element.title = this.options.clickToEditText;
this.onclickListener = this.enterEditMode.bindAsEventListener(this);
this.mouseoverListener = this.enterHover.bindAsEventListener(this);
this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
Event.observe(this.element, 'click', this.onclickListener);
Event.observe(this.element, 'mouseover', this.mouseoverListener);
Event.observe(this.element, 'mouseout', this.mouseoutListener);
if (this.options.externalControl) {
Event.observe(this.options.externalControl, 'click', this.onclickListener);
Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
}
},
enterEditMode: function(evt) {
if (this.saving) return;
if (this.editing) return;
this.editing = true;
this.onEnterEditMode();
if (this.options.externalControl) {
Element.hide(this.options.externalControl);
}
Element.hide(this.element);
this.createForm();
this.element.parentNode.insertBefore(this.form, this.element);
Field.scrollFreeActivate(this.editField);
// stop the event to avoid a page refresh in Safari
if (evt) {
Event.stop(evt);
}
return false;
},
createForm: function() {
this.form = document.createElement("form");
this.form.id = this.options.formId;
Element.addClassName(this.form, this.options.formClassName)
this.form.onsubmit = this.onSubmit.bind(this);
this.createEditField();
if (this.options.textarea) {
var br = document.createElement("br");
this.form.appendChild(br);
}
okButton = document.createElement("input");
okButton.type = "submit";
okButton.value = this.options.okText;
this.form.appendChild(okButton);
cancelLink = document.createElement("a");
cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(this.options.cancelText));
cancelLink.onclick = this.onclickCancel.bind(this);
this.form.appendChild(cancelLink);
},
hasHTMLLineBreaks: function(string) {
if (!this.options.handleLineBreaks) return false;
return string.match(/<br/i) || string.match(/<p>/i);
},
convertHTMLLineBreaks: function(string) {
return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
},
createEditField: function() {
var text;
if(this.options.loadTextURL) {
text = this.options.loadingText;
} else {
text = this.getText();
}
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
this.options.textarea = false;
var textField = document.createElement("input");
textField.type = "text";
textField.name = "value";
textField.value = text;
textField.style.backgroundColor = this.options.highlightcolor;
var size = this.options.size || this.options.cols || 0;
if (size != 0) textField.size = size;
this.editField = textField;
} else {
this.options.textarea = true;
var textArea = document.createElement("textarea");
textArea.name = "value";
textArea.value = this.convertHTMLLineBreaks(text);
textArea.rows = this.options.rows;
textArea.cols = this.options.cols || 40;
this.editField = textArea;
}
if(this.options.loadTextURL) {
this.loadExternalText();
}
this.form.appendChild(this.editField);
},
getText: function() {
return this.element.innerHTML;
},
loadExternalText: function() {
Element.addClassName(this.form, this.options.loadingClassName);
this.editField.disabled = true;
new Ajax.Request(
this.options.loadTextURL,
Object.extend({
asynchronous: true,
onComplete: this.onLoadedExternalText.bind(this)
}, this.options.ajaxOptions)
);
},
onLoadedExternalText: function(transport) {
Element.removeClassName(this.form, this.options.loadingClassName);
this.editField.disabled = false;
this.editField.value = transport.responseText.stripTags();
},
onclickCancel: function() {
this.onComplete();
this.leaveEditMode();
return false;
},
onFailure: function(transport) {
this.options.onFailure(transport);
if (this.oldInnerHTML) {
this.element.innerHTML = this.oldInnerHTML;
this.oldInnerHTML = null;
}
return false;
},
onSubmit: function() {
// onLoading resets these so we need to save them away for the Ajax call
var form = this.form;
var value = this.editField.value;
// do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
// which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
// to be displayed indefinitely
this.onLoading();
new Ajax.Updater(
{
success: this.element,
// don't update on failure (this could be an option)
failure: null
},
this.url,
Object.extend({
parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this)
}, this.options.ajaxOptions)
);
// stop the event to avoid a page refresh in Safari
if (arguments.length > 1) {
Event.stop(arguments[0]);
}
return false;
},
onLoading: function() {
this.saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
showSaving: function() {
this.oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
Element.addClassName(this.element, this.options.savingClassName);
this.element.style.backgroundColor = this.originalBackground;
Element.show(this.element);
},
removeForm: function() {
if(this.form) {
if (this.form.parentNode) Element.remove(this.form);
this.form = null;
}
},
enterHover: function() {
if (this.saving) return;
this.element.style.backgroundColor = this.options.highlightcolor;
if (this.effect) {
this.effect.cancel();
}
Element.addClassName(this.element, this.options.hoverClassName)
},
leaveHover: function() {
if (this.options.backgroundColor) {
this.element.style.backgroundColor = this.oldBackground;
}
Element.removeClassName(this.element, this.options.hoverClassName)
if (this.saving) return;
this.effect = new Effect.Highlight(this.element, {
startcolor: this.options.highlightcolor,
endcolor: this.options.highlightendcolor,
restorecolor: this.originalBackground
});
},
leaveEditMode: function() {
Element.removeClassName(this.element, this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this.originalBackground;
Element.show(this.element);
if (this.options.externalControl) {
Element.show(this.options.externalControl);
}
this.editing = false;
this.saving = false;
this.oldInnerHTML = null;
this.onLeaveEditMode();
},
onComplete: function(transport) {
this.leaveEditMode();
this.options.onComplete.bind(this)(transport, this.element);
},
onEnterEditMode: function() {},
onLeaveEditMode: function() {},
dispose: function() {
if (this.oldInnerHTML) {
this.element.innerHTML = this.oldInnerHTML;
}
this.leaveEditMode();
Event.stopObserving(this.element, 'click', this.onclickListener);
Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
if (this.options.externalControl) {
Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
}
}
};
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create();
Form.Element.DelayedObserver.prototype = {
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
};

View File

@ -0,0 +1,195 @@
Dojo is availble under *either* the terms of the modified BSD license *or* the
Academic Free License version 2.1. As a recipient of Dojo, you may choose which
license to receive this code under (except as noted in per-module LICENSE
files). Some modules may not be the copyright of the Dojo Foundation. These
modules contain explicit declarations of copyright in both the LICENSE files in
the directories in which they reside and in the code itself. No external
contributions are allowed under licenses which are fundamentally incompatible
with the AFL or BSD licenses that Dojo is distributed under.
The text of the AFL and BSD licenses is reproduced below.
-------------------------------------------------------------------------------
The "New" BSD License:
**********************
Copyright (c) 2005, The Dojo Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Dojo Foundation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
The Academic Free License, v. 2.1:
**********************************
This Academic Free License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the
following notice immediately following the copyright notice for the Original
Work:
Licensed under the Academic Free License version 2.1
1) Grant of Copyright License. Licensor hereby grants You a world-wide,
royalty-free, non-exclusive, perpetual, sublicenseable license to do the
following:
a) to reproduce the Original Work in copies;
b) to prepare derivative works ("Derivative Works") based upon the Original
Work;
c) to distribute copies of the Original Work and Derivative Works to the
public;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor hereby grants You a world-wide,
royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
claims owned or controlled by the Licensor that are embodied in the Original
Work as furnished by the Licensor, to make, use, sell and offer for sale the
Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred
form of the Original Work for making modifications to it and all available
documentation describing how to modify the Original Work. Licensor hereby
agrees to provide a machine-readable copy of the Source Code of the Original
Work along with each copy of the Original Work that Licensor distributes.
Licensor reserves the right to satisfy this obligation by placing a
machine-readable copy of the Source Code in an information repository
reasonably calculated to permit inexpensive and convenient access by You for as
long as Licensor continues to distribute the Original Work, and by publishing
the address of that information repository in a notice immediately following
the copyright notice that applies to the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
of any contributors to the Original Work, nor any of their trademarks or
service marks, may be used to endorse or promote products derived from this
Original Work without express prior written permission of the Licensor. Nothing
in this License shall be deemed to grant any rights to trademarks, copyrights,
patents, trade secrets or any other intellectual property of Licensor except as
expressly stated herein. No patent license is granted to make, use, sell or
offer to sell embodiments of any patent claims other than the licensed claims
defined in Section 2. No right is granted to the trademarks of Licensor even if
such marks are included in the Original Work. Nothing in this License shall be
interpreted to prohibit Licensor from licensing under different terms from this
License any Original Work that Licensor otherwise would have a right to
license.
5) This section intentionally omitted.
6) Attribution Rights. You must retain, in the Source Code of any Derivative
Works that You create, all copyright, patent or trademark notices from the
Source Code of the Original Work, as well as any notices of licensing and any
descriptive text identified therein as an "Attribution Notice." You must cause
the Source Code for any Derivative Works that You create to carry a prominent
Attribution Notice reasonably calculated to inform recipients that You have
modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
the copyright in and to the Original Work and the patent rights granted herein
by Licensor are owned by the Licensor or are sublicensed to You under the terms
of this License with the permission of the contributor(s) of those copyrights
and patent rights. Except as expressly stated in the immediately proceeding
sentence, the Original Work is provided under this License on an "AS IS" BASIS
and WITHOUT WARRANTY, either express or implied, including, without limitation,
the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
license to Original Work is granted hereunder except under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory,
whether in tort (including negligence), contract, or otherwise, shall the
Licensor be liable to any person for any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License
or the use of the Original Work including, without limitation, damages for loss
of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. This limitation of liability shall not
apply to liability for death or personal injury resulting from Licensor's
negligence to the extent applicable law prohibits such limitation. Some
jurisdictions do not allow the exclusion or limitation of incidental or
consequential damages, so this exclusion and limitation may not apply to You.
9) Acceptance and Termination. If You distribute copies of the Original Work or
a Derivative Work, You must make a reasonable effort under the circumstances to
obtain the express assent of recipients to the terms of this License. Nothing
else but this License (or another written agreement between Licensor and You)
grants You permission to create Derivative Works based upon the Original Work
or to exercise any of the rights granted in Section 1 herein, and any attempt
to do so except under the terms of this License (or another written agreement
between Licensor and You) is expressly prohibited by U.S. copyright law, the
equivalent laws of other countries, and by international treaty. Therefore, by
exercising any of the rights granted to You in Section 1 herein, You indicate
Your acceptance of this License and all of its terms and conditions.
10) Termination for Patent Action. This License shall terminate automatically
and You may no longer exercise any of the rights granted to You by this License
as of the date You commence an action, including a cross-claim or counterclaim,
against Licensor or any licensee alleging that the Original Work infringes a
patent. This termination provision shall not apply for an action alleging
patent infringement by combinations of the Original Work with other software or
hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
License may be brought only in the courts of a jurisdiction wherein the
Licensor resides or in which Licensor conducts its primary business, and under
the laws of that jurisdiction excluding its conflict-of-law provisions. The
application of the United Nations Convention on Contracts for the International
Sale of Goods is expressly excluded. Any use of the Original Work outside the
scope of this License or after its termination shall be subject to the
requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et
seq., the equivalent laws of other countries, and international treaty. This
section shall survive the termination of this License.
12) Attorneys Fees. In any action to enforce the terms of this License or
seeking damages relating thereto, the prevailing party shall be entitled to
recover its costs and expenses, including, without limitation, reasonable
attorneys' fees and costs incurred in connection with such action, including
any appeal of such action. This section shall survive the termination of this
License.
13) Miscellaneous. This License represents the complete agreement concerning
the subject matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent necessary to
make it enforceable.
14) Definition of "You" in This License. "You" throughout this License, whether
in upper or lower case, means an individual or a legal entity exercising rights
under, and complying with all of the terms of, this License. For legal
entities, "You" includes any entity that controls, is controlled by, or is
under common control with you. For purposes of this definition, "control" means
(i) the power, direct or indirect, to cause the direction or management of such
entity, whether by contract or otherwise, or (ii) ownership of fifty percent
(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
entity.
15) Right to Use. You may use the Original Work in all ways not otherwise
restricted or conditioned by this License or by law, and Licensor promises not
to interfere with or be responsible for such uses by You.
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
Permission is hereby granted to copy and distribute this license without
modification. This license may not be modified without the express written
permission of its copyright owner.

View File

@ -0,0 +1,176 @@
The Dojo Toolkit
----------------
Dojo is a portable JavaScript toolkit for web application developers and
JavaScript professionals. Dojo solves real-world problems by providing powerful
abstractions and solid, tested implementations.
Getting Started
---------------
To use Dojo in your application, download one of the pre-built editions from the
Dojo website, http://dojotoolkit.org. Once you have downloaded the file you will
need to unzip the archive in your website root. At a minimum, you will need to
extract:
src/ (folder)
dojo.js
iframe_history.html
To begin using dojo, include dojo in your pages by using:
<script type="text/javascript" src="/path/to/dojo.js"></script>
Depending on the edition that you have downloaded, this base dojo.js file may or
may not include the modules you wish to use in your application. The files which
have been "baked in" to the dojo.js that is part of your distribution are listed
in the file build.txt that is part of the top-level directory that is created
when you unpack the archive. To ensure modules you wish to use are available,
use dojo.require() to request them. A very rich application might include:
<script type="text/javascript" src="/path/to/dojo.js"></script>
<script type="text/javascript">
dojo.require("dojo.event.*"); // sophisticated AOP event handling
dojo.require("dojo.io.*"); // for Ajax requests
dojo.require("dojo.storage.*"); // a persistent local data cache
dojo.require("dojo.json"); // serialization to JSON
dojo.require("dojo.dnd.*"); // drag-and-drop
dojo.require("dojo.lfx.*"); // animations and eye candy
dojo.require("dojo.widget.Editor2");// stable, portable HTML WYSIWYG
</script>
Note that only those modules which are *not* already "baked in" to dojo.js by
the edition's build process are requested by dojo.require(). This helps make
your application faster without forcing you to use a build tool while in
development. See "Building Dojo" and "Working From Source" for more details.
Compatibility
-------------
In addition to it's suite of unit-tests for core system components, Dojo has
been tested on almost every modern browser, including:
- IE 5.5+
- Mozilla 1.5+, Firefox 1.0+
- Safari 1.3.9+
- Konqueror 3.4+
- Opera 8.5+
Note that some widgets and features may not perform exactly the same on every
browser due to browser implementation differences.
For those looking to use Dojo in non-browser environments, please see "Working
From Source".
Documentation and Getting Help
------------------------------
Articles outlining major Dojo systems are linked from:
http://dojotoolkit.org/docs/
Toolkit APIs are listed in outline form at:
http://dojotoolkit.org/docs/apis/
And documented in full at:
http://manual.dojotoolkit.org/
The project also maintains a JotSpot Wiki at:
http://dojo.jot.com/
A FAQ has been extracted from mailing list traffic:
http://dojo.jot.com/FAQ
And the main Dojo user mailing list is archived and made searchable at:
http://news.gmane.org/gmane.comp.web.dojo.user/
You can sign up for this list, which is a great place to ask questions, at:
http://dojotoolkit.org/mailman/listinfo/dojo-interest
The Dojo developers also tend to hang out in IRC and help people with Dojo
problems. You're most likely to find them at:
irc.freenode.net #dojo
Note that 2PM Wed PST in this channel is reserved for a weekly meeting between
project developers, although anyone is welcome to participate.
Working From Source
-------------------
The core of Dojo is a powerful package system that allows developers to optimize
Dojo for deployment while using *exactly the same* application code in
development. Therefore, working from source is almost exactly like working from
a pre-built edition. Pre-built editions are significantly faster to load than
working from source, but are not as flexible when in development.
There are multiple ways to get the source. Nightly snapshots of the Dojo source
repository are available at:
http://archive.dojotoolkit.org/nightly.tgz
Anonymous Subversion access is also available:
%> svn co http://svn.dojootoolkit.org/dojo/trunk/ dojo
Each of these sources will include some extra directories not included in the
pre-packaged editions, including command-line tests and build tools for
constructing your own packages.
Running the command-line unit test suite requires Ant 1.6. If it is installed
and in your path, you can run the tests using:
%> cd buildscripts
%> ant test
The command-line test harness makes use of Rhino, a JavaScript interpreter
written in Java. Once you have a copy of Dojo's source tree, you have a copy of
Rhino. From the root directory, you can use Rhino interactively to load Dojo:
%> java -jar buildscripts/lib/js.jar
Rhino 1.5 release 3 2002 01 27
js> load("dojo.js");
js> print(dojo);
[object Object]
js> quit();
This environment is wonderful for testing raw JavaScript functionality in, or
even for scripting your system. Since Rhino has full access to anything in
Java's classpath, the sky is the limit!
Building Dojo
-------------
Dojo requires Ant 1.6.x in order to build correctly. While using Dojo from
source does *NOT* require that you make a build, speeding up your application by
constructing a custom profile build does.
Once you have Ant and a source snapshot of Dojo, you can make your own profile
build ("edition") which includes only those modules your application uses by
customizing one of the files in:
[dojo]/buildscripts/profiles/
These files are named *.profile.js and each one contains a list of modules to
include in a build. If we created a new profile called "test.profile.js", we
could then make a profile build using it by doing:
%> cd buildscripts
%> ant -Dprofile=test -Ddocless=true release intern-strings
If the build is successful, your newly minted and compressed profile build will
be placed in [dojo]/releae/dojo/
-------------------------------------------------------------------------------
Copyright (c) 2004-2006, The Dojo Foundation, All Rights Reserved
vim:ts=4:et:tw=80:shiftwidth=4:

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
<h2 id="dojo.alg">dojo.alg</h2><h3>Methods</h3><pre>find (arr, val)
inArray (arr, val)
inArr (arr, val)
getNameInObj (ns, _99)
has (obj, name)
forEach (arr, _101, _102)
for_each (arr, _101, _102)
map (arr, obj, _104)
tryThese ()
delayThese (farr, cb, _107, _108)
for_each_call (arr, obj, _104)
</pre>

View File

@ -0,0 +1,36 @@
<h2 id="dojo.animation">dojo.animation</h2><h3>Methods</h3><pre>Animation (_536, _537, _538, _539)
AnimationEvent (anim, type, _548, _549, _550, _551, dur, pct, fps)
AnimationSequence (_555)
</pre><h2 id="dojo.animation.Animation Object">dojo.animation.Animation Object</h2><h3>Methods</h3><pre>play (_542)
pause ()
playPause ()
gotoPercent (pct, _544)
stop (_545)
status ()
</pre><h3>Properties</h3><pre>undefined curve
undefined duration
undefined accel
Number repeatCount
undefined onBegin
undefined onAnimate
undefined onEnd
undefined onPlay
undefined onPause
undefined onStop
undefined handler
</pre><h2 id="dojo.animation.AnimationSequence Object">dojo.animation.AnimationSequence Object</h2><h3>Methods</h3><pre>add ()
remove (anim)
removeAll ()
play (_558)
pause ()
playPause ()
stop ()
status ()
setCurrent (anim)
playNext ()
</pre><h3>Properties</h3><pre>Number repeatCount
undefined onBegin
undefined onEnd
undefined onNext
undefined handler
</pre>

View File

@ -0,0 +1,19 @@
<h2 id="dojo.dnd">dojo.dnd</h2><h3>Methods</h3><pre>DragSource ()
DropTarget ()
DragObject ()
DragManager ()
DragEvent ()
HtmlDragManager ()
HtmlDragSource (node, type)
HtmlDropTarget (node, _663)
HtmlDragObject (node, type)
</pre><h3>Properties</h3><pre>Object <a href="#dojo.dnd.dragManager">dragManager</a>
</pre><h2 id="dojo.dnd.DragEvent Object">dojo.dnd.DragEvent Object</h2><h3>Properties</h3><pre>undefined dragSource
undefined dragObject
undefined target
String eventSatus
</pre><h2 id="dojo.dnd.HtmlDropTarget Object">dojo.dnd.HtmlDropTarget Object</h2><h3>Properties</h3><pre>undefined domNode
Array acceptedTypes
</pre><h2 id="dojo.dnd.HtmlDragObject Object">dojo.dnd.HtmlDragObject Object</h2><h3>Properties</h3><pre>undefined type
undefined domNode
</pre>

View File

@ -0,0 +1,39 @@
<h2>Globals</h2>
<pre>dj_undef
dj_eval_object_path
dj_error_to_string
dj_eval
dj_load
dj_last_script_src
dj_addNodeEvtHdlr</pre>
<pre>djConfig
dj_global
dojo
DJ_XMLHTTP_PROGIDS
dojo_ie_clobber</pre>
<h2 id="dojo">dojo</h2><h3>Methods</h3><pre>loaded ()
addOnLoad (obj, fcnName)
require ()
requireIf ()
requireAfterIf ()
provide ()
</pre><h3>Properties</h3><pre>Object <a href="version.html">version</a>
Object <a href="render.html">render</a>
Object <a href="hostenv.html">hostenv</a>
Object <a href="alg.html">alg</a>
Object <a href="lang.html">lang</a>
Object <a href="event.html">event</a>
Object <a href="logging.html">logging</a>
Object <a href="log.html">log</a>
Object <a href="io.html">io</a>
Object <a href="text.html">text</a>
Object <a href="graphics.html">graphics</a>
Object <a href="xml.html">xml</a>
Object <a href="uri.html">uri</a>
Object <a href="math.html">math</a>
Object <a href="animation.html">animation</a>
Object <a href="dnd.html">dnd</a>
Object <a href="widget.html">widget</a>
</pre>

View File

@ -0,0 +1,41 @@
<h2 id="dojo.event">dojo.event</h2><h3>Methods</h3><pre>nameAnonFunc (_120, _121)
createFunctionPair (obj, cb)
matchSignature (args, _123)
matchSignatureSets (args)
connect ()
connectBefore ()
connectAround ()
kwConnect (_133)
disconnect ()
kwDisconnect (_134)
MethodInvocation (_135, obj, args)
MethodJoinPoint (obj, _138)
</pre><h3>Properties</h3><pre>Object anon
Object <a href="#dojo.event.topic">topic</a>
Object <a href="#dojo.event.browser">browser</a>
</pre><h2 id="dojo.event.MethodJoinPoint Object">dojo.event.MethodJoinPoint Object</h2><h3>Properties</h3><pre>Object <a href="#dojo.event.MethodJoinPoint%20Object.object">object</a>
undefined methodname
undefined methodfunc
Array before
Array after
Array around
</pre><h2 id="dojo.event.topic">dojo.event.topic</h2><h3>Methods</h3><pre>getTopic (_173)
registerPublisher (_174, obj, _175)
subscribe (_176, obj, _177)
unsubscribe (_178, obj, _179)
publish (_180, _181)
TopicImpl (_182)
</pre><h3>Properties</h3><pre>Object topics
</pre><h2 id="dojo.event.topic.TopicImpl Object">dojo.event.topic.TopicImpl Object</h2><h3>Methods</h3><pre>subscribe (_184, _185)
unsubscribe (_186, _187)
registerPublisher (_188, _189)
sendMessage (_190)
</pre><h3>Properties</h3><pre>undefined topicName
</pre><h2 id="dojo.event.browser">dojo.event.browser</h2><h3>Methods</h3><pre>clean (node)
addClobberAttr (type)
addClobberAttrs ()
addClobberNode (node)
addListener (node, _201, fp, _202)
fixEvent (evt)
stopEvent (ev)
</pre>

View File

@ -0,0 +1,47 @@
<h2 id="dojo.graphics">dojo.graphics</h2><h3>Properties</h3><pre>Object <a href="#dojo.graphics.color">color</a>
Object <a href="#dojo.graphics.htmlEffects">htmlEffects</a>
</pre><h2 id="dojo.graphics.color">dojo.graphics.color</h2><h3>Methods</h3><pre>blend (a, b, _346)
blendHex (a, b, _349)
extractRGB (_350)
hex2rgb (hex)
rgb2hex (r, g, b)
</pre><h2 id="dojo.graphics.htmlEffects">dojo.graphics.htmlEffects</h2><h3>Methods</h3><pre>fadeOut (node, _559, _560)
fadeIn (node, _561, _562)
fadeHide (node, _563, _564)
fadeShow (node, _565, _566)
fade (node, _567, _568, _569, _570)
slideTo (node, _571, _572, _573)
slideBy (node, _574, _575, _576)
slide (node, _577, _578, _579, _580)
colorFadeIn (node, _581, _582, _583, _584)
highlight (node, _581, _582, _583, _584)
colorFadeFrom (node, _581, _582, _583, _584)
colorFadeOut (node, _588, _589, _590, _591)
unhighlight (node, _588, _589, _590, _591)
colorFadeTo (node, _588, _589, _590, _591)
colorFade (node, _593, _594, _595, _596, _597)
wipeIn (node, _598, _599, _600)
wipeOut (node, _604, _605, _606)
explode (_610, _611, _612, _613)
explodeFromBox (_615, _616, _617, _618)
implode (_621, _622, _623, _624)
implodeToBox (_626, _627, _628, _629)
Exploder (_631, _632)
</pre><h2 id="dojo.graphics.htmlEffects.Exploder Object">dojo.graphics.htmlEffects.Exploder Object</h2><h3>Methods</h3><pre>timeShow ()
show ()
timeHide ()
hide ()
</pre><h3>Properties</h3><pre>Number waitToHide
Number timeToShow
Number waitToShow
Number timeToHide
Boolean autoShow
Boolean autoHide
Boolean showing
undefined onBeforeExplode
undefined onAfterExplode
undefined onBeforeImplode
undefined onAfterImplode
undefined onExploding
undefined onImploding
</pre>

View File

@ -0,0 +1,33 @@
<h2 id="dojo.hostenv">dojo.hostenv</h2><h3>Methods</h3><pre>setModulePrefix (_31, _32)
getModulePrefix (_33)
getName ()
getVersion ()
getText (uri, _81, _82)
getBaseScriptUri ()
loadPath (_37, _38, cb)
loadUri (uri, cb)
getDepsForEval (_42)
loadUriAndCheck (uri, _46, cb)
loaded ()
modulesLoaded ()
loadModule (_52, _53, _54)
startPackage (_64)
findModule (_66, _67)
getXmlhttpObject ()
println (s)
makeWidgets ()
writeIncludes ()
kwCompoundRequire (_91)
require (_52, _53, _54)
provide (_64)
</pre><h3>Properties</h3><pre>String pkgFileName
Array addedToLoadingCount
Array removedFromLoadingCount
Number inFlightCount
Array getTextStack
Array loadUriStack
Array loadedUris
Boolean modulesLoadedFired
Array modulesLoadedListeners
Array searchIds
</pre>

View File

@ -0,0 +1,57 @@
<h2 id="dojo.io">dojo.io</h2><h3>Methods</h3><pre>Request (url, mt, _239, curl)
IOEvent (type, data, _250, _251, _252, _253)
Error (msg, type, num)
bind (_255)
argsFromMap (map)
checkChildrenForFile (node)
formHasFile (_263)
buildFormGetString (_264)
setIFrameSrc (_271, src, _272)
createIFrame (_275)
cancelDOMEvent (evt)
</pre><h3>Properties</h3><pre>Array transports
Array hdlrFuncNames
Object <a href="#dojo.io.XMLHTTPTransport">XMLHTTPTransport</a>
Object <a href="#dojo.io.cookies">cookies</a>
</pre><h2 id="dojo.io.Request Object">dojo.io.Request Object</h2><h3>Methods</h3><pre>error (type, _242)
load (type, data, evt)
backButton ()
forwardButton ()
</pre><h3>Properties</h3><pre>undefined url
undefined mimetype
undefined transport
undefined changeUrl
undefined formNode
</pre><h2 id="dojo.io.IOEvent Object">dojo.io.IOEvent Object</h2><h3>Properties</h3><pre>undefined type
undefined data
undefined request
undefined errorMessage
undefined errorUrl
undefined errorCode
</pre><h2 id="dojo.io.Error Object">dojo.io.Error Object</h2><h3>Properties</h3><pre>undefined message
String type
Number number
</pre><h2 id="dojo.io.XMLHTTPTransport">dojo.io.XMLHTTPTransport</h2><h3>Methods</h3><pre>clearCache ()
addToHistory (args)
checkLocation ()
iframeLoaded (evt, _302)
handleBackButton ()
handleForwardButton ()
canHandle (_308)
bind (_309)
</pre><h3>Properties</h3><pre>String initialHref
String initialHash
Boolean moveForward
Boolean useCache
Array historyStack
Array forwardStack
undefined historyIframe
undefined bookmarkAnchor
undefined locationTimer
</pre><h2 id="dojo.io.cookies">dojo.io.cookies</h2><h3>Methods</h3><pre>setCookie (name, _317, days, path)
getCookie (name)
deleteCookie (name)
setObjectCookie (name, obj, days, path, _323)
getObjectCookie (name)
isSupported ()
</pre>

View File

@ -0,0 +1,12 @@
<h2 id="dojo.lang">dojo.lang</h2><h3>Methods</h3><pre>mixin (obj, _109)
extend (ctor, _112)
extendPrototype (obj, _113)
setTimeout (func, _115)
isObject (wh)
isArray (wh)
isFunction (wh)
isString (wh)
isNumber (wh)
isBoolean (wh)
isUndefined (wh)
</pre>

View File

@ -0,0 +1,13 @@
<h2 id="dojo.log">dojo.log</h2><h3>Methods</h3><pre>getLogger (name)
getLevelName (lvl)
addLevelName (name, lvl)
getLevel (name)
</pre><h3>Properties</h3><pre>Number cutOffLevel
Boolean propagate
undefined parent
Array data
Array filters
Array handlers
Array levels
Object loggers
</pre>

View File

@ -0,0 +1,41 @@
<h2 id="dojo.logging">dojo.logging</h2><h3>Methods</h3><pre>Logger ()
Record (lvl, msg)
LogFilter (_214)
LogHandler (_224)
MemoryLogHandler (_230, _231, _232, _233)
</pre><h3>Properties</h3><pre>Object <a href="#dojo.logging.log">log</a>
Object <a href="#dojo.logging.logQueueHandler">logQueueHandler</a>
</pre><h2 id="dojo.logging.Logger Object">dojo.logging.Logger Object</h2><h3>Properties</h3><pre>Number cutOffLevel
Boolean propagate
undefined parent
Array data
Array filters
Array handlers
</pre><h2 id="dojo.logging.Record Object">dojo.logging.Record Object</h2><h3>Properties</h3><pre>undefined level
undefined message
Object time
</pre><h2 id="dojo.logging.LogFilter Object">dojo.logging.LogFilter Object</h2><h3>Methods</h3><pre>filter (_215)
</pre><h3>Properties</h3><pre>String passChain
</pre><h2 id="dojo.logging.LogHandler Object">dojo.logging.LogHandler Object</h2><h3>Properties</h3><pre>Number cutOffLevel
undefined formatter
Array data
Array filters
</pre><h2 id="dojo.logging.MemoryLogHandler Object">dojo.logging.MemoryLogHandler Object</h2><h3>Properties</h3><pre>Number numRecords
Number postType
Number postInterval
</pre><h2 id="dojo.logging.log">dojo.logging.log</h2><h3>Methods</h3><pre>getLogger (name)
getLevelName (lvl)
addLevelName (name, lvl)
getLevel (name)
</pre><h3>Properties</h3><pre>Number cutOffLevel
Boolean propagate
undefined parent
Array data
Array filters
Array handlers
Array levels
Object loggers
</pre><h2 id="dojo.logging.logQueueHandler">dojo.logging.logQueueHandler</h2><h3>Properties</h3><pre>Number numRecords
Number postType
Number postInterval
</pre>

View File

@ -0,0 +1,39 @@
<h2 id="dojo.math">dojo.math</h2><h3>Methods</h3><pre>degToRad (x)
radToDeg (x)
factorial (n)
permutations (n, k)
combinations (n, r)
bernstein (t, n, i)
</pre><h3>Properties</h3><pre>Object <a href="#dojo.math.curves">curves</a>
Object <a href="#dojo.math.points">points</a>
</pre><h2 id="dojo.math.curves">dojo.math.curves</h2><h3>Methods</h3><pre>Line (_493, end)
Bezier (pnts)
CatmullRom (pnts, c)
Arc (_513, end, ccw)
CenteredArc (_519, _520, _521, end)
Circle (_524, _525)
Path ()
</pre><h2 id="dojo.math.curves.Bezier Object">dojo.math.curves.Bezier Object</h2><h3>Methods</h3><pre>getValue (step)
</pre><h3>Properties</h3><pre>undefined p
</pre><h2 id="dojo.math.curves.CatmullRom Object">dojo.math.curves.CatmullRom Object</h2><h3>Methods</h3><pre>getValue (step)
</pre><h3>Properties</h3><pre>Number c
undefined p
</pre><h2 id="dojo.math.curves.CenteredArc Object">dojo.math.curves.CenteredArc Object</h2><h3>Methods</h3><pre>getValue (n)
</pre><h3>Properties</h3><pre>undefined center
undefined radius
Number start
undefined end
</pre><h2 id="dojo.math.curves.Circle Object">dojo.math.curves.Circle Object</h2><h3>Methods</h3><pre>getValue (n)
</pre><h3>Properties</h3><pre>undefined center
undefined radius
Number start
Number end
</pre><h2 id="dojo.math.curves.Path Object">dojo.math.curves.Path Object</h2><h3>Methods</h3><pre>add (_530, _531)
remove (_532)
removeAll ()
getValue (n)
</pre><h2 id="dojo.math.points">dojo.math.points</h2><h3>Methods</h3><pre>translate (a, b)
midpoint (a, b)
invert (a)
distance (a, b)
</pre>

View File

@ -0,0 +1,48 @@
<h2 id="dojo.render">dojo.render</h2><h3>Properties</h3><pre>String name
Number ver
Object <a href="#dojo.render.os">os</a>
Object <a href="#dojo.render.html">html</a>
Object <a href="#dojo.render.svg">svg</a>
Object <a href="#dojo.render.swf">swf</a>
Object <a href="#dojo.render.swt">swt</a>
</pre><h2 id="dojo.render.os">dojo.render.os</h2><h3>Properties</h3><pre>Boolean win
Boolean linux
Boolean osx
Boolean mac
</pre><h2 id="dojo.render.html">dojo.render.html</h2><h3>Properties</h3><pre>Boolean capable
Object <a href="#dojo.render.html.support">support</a>
Boolean ie
Boolean opera
Boolean khtml
Boolean safari
Boolean moz
Array prefixes
String UA
String AV
Boolean mozilla
Boolean ie50
Boolean ie55
Boolean ie60
</pre><h2 id="dojo.render.html.support">dojo.render.html.support</h2><h3>Properties</h3><pre>Boolean builtin
Boolean plugin
</pre><h2 id="dojo.render.svg">dojo.render.svg</h2><h3>Properties</h3><pre>Boolean capable
Object <a href="#dojo.render.svg.support">support</a>
Boolean corel
Boolean adobe
Boolean batik
Array prefixes
</pre><h2 id="dojo.render.svg.support">dojo.render.svg.support</h2><h3>Properties</h3><pre>Boolean builtin
Boolean plugin
</pre><h2 id="dojo.render.swf">dojo.render.swf</h2><h3>Properties</h3><pre>Boolean capable
Object <a href="#dojo.render.swf.support">support</a>
Boolean mm
Array prefixes
</pre><h2 id="dojo.render.swf.support">dojo.render.swf.support</h2><h3>Properties</h3><pre>Boolean builtin
Boolean plugin
</pre><h2 id="dojo.render.swt">dojo.render.swt</h2><h3>Properties</h3><pre>Boolean capable
Object <a href="#dojo.render.swt.support">support</a>
Boolean ibm
Array prefixes
</pre><h2 id="dojo.render.swt.support">dojo.render.swt.support</h2><h3>Properties</h3><pre>Boolean builtin
Boolean plugin
</pre>

View File

@ -0,0 +1,12 @@
<h2 id="dojo.text">dojo.text</h2><h3>Methods</h3><pre>trim (_330)
paramString (str, _332, _333)
capitalize (str)
isBlank (str)
Builder (str)
</pre><h2 id="dojo.text.Builder Object">dojo.text.Builder Object</h2><h3>Methods</h3><pre>append (s)
clear ()
remove (f, l)
replace (o, n)
insert (idx, s)
</pre><h3>Properties</h3><pre>Number length
</pre>

View File

@ -0,0 +1,4 @@
<h2 id="dojo.uri">dojo.uri</h2><h3>Methods</h3><pre>joinPath ()
dojoUri (uri)
Uri ()
</pre>

View File

@ -0,0 +1,5 @@
<h2 id="dojo.version">dojo.version</h2><h3>Properties</h3><pre>Number major
Number minor
Number patch
Number revision
</pre>

View File

@ -0,0 +1,52 @@
<h2 id="dojo.widget">dojo.widget</h2><h3>Methods</h3><pre>Widget ()
buildWidgetFromParseTree (type, frag, _736, _737, _738)
Parse (_743)
getParser (name)
fromScript (name, _777, _778, _779)
DomWidget ()
buildFromTemplate (obj, _785, _786, _787)
attachTemplateNodes (_795, _796, _797, _798)
getDojoEventsFromStr (str)
buildAndAttachTemplate (obj, _816, _817, _818, _819)
HtmlWidget (args)
</pre><h3>Properties</h3><pre>Object <a href="#dojo.widget.manager">manager</a>
Object <a href="#dojo.widget.tags">tags</a>
String attachProperty
String eventAttachProperty
String subTemplateProperty
String onBuildProperty
</pre><h2 id="dojo.widget.Widget Object">dojo.widget.Widget Object</h2><h3>Properties</h3><pre>Array children
Array rightClickItems
Object extraArgs
</pre><h2 id="dojo.widget.Parse Object">dojo.widget.Parse Object</h2><h3>Methods</h3><pre>createComponents (_743, _744)
parsePropertySets (_749)
parseProperties (_751)
getDataProvider (_756, _757)
getPropertySetById (_759)
getPropertySetsByType (_760)
getPropertySets (_764)
createComponentFromScript (_770, _771, _772, _773)
</pre><h3>Properties</h3><pre>Array propertySetsList
undefined fragment
</pre><h2 id="dojo.widget.manager">dojo.widget.manager</h2><h3>Methods</h3><pre>getUniqueId ()
add (_676)
destroyAll ()
remove (_677)
removeById (id)
getWidgetById (id)
getWidgetsByType (type)
getWidgetsOfType (id)
getWidgetsByFilter (_680)
registerWidgetPackage (_683)
getImplementation (_684, _685, _686)
getImplementationName (_689)
getWidgetFromPrimitive (_695)
getWidgetFromEvent (_696)
</pre><h3>Properties</h3><pre>Array widgets
Array widgetIds
undefined root
</pre><h2 id="dojo.widget.tags">dojo.widget.tags</h2><h3>Methods</h3><pre>addParseTreeHandler (type)
dojo:widget (_724, _725, _726, _727)
dojo:propertyset (_728, _729, _730)
dojo:connect (_732, _733, _734)
</pre></body></html>

View File

@ -0,0 +1,84 @@
<h2 id="dojo.xml">dojo.xml</h2><h3>Methods</h3><pre>Parse ()
</pre><h3>Properties</h3><pre>Object <a href="#dojo.xml.domUtil">domUtil</a>
Object <a href="#dojo.xml.htmlUtil">htmlUtil</a>
</pre><h2 id="dojo.xml.Parse Object">dojo.xml.Parse Object</h2><h3>Methods</h3><pre>parseFragment (_402)
parseElement (node, _409, _410, _411)
parseAttributes (node)
</pre><h2 id="dojo.xml.domUtil">dojo.xml.domUtil</h2><h3>Methods</h3><pre>getTagName (node)
getUniqueId ()
getFirstChildTag (_362)
getLastChildTag (_363)
getNextSiblingTag (node)
getPreviousSiblingTag (node)
forEachChildTag (node, _364)
moveChildren (_366, _367, trim)
copyChildren (_370, _371, trim)
clearChildren (node)
replaceChildren (node, _374)
getStyle (_375, _376)
toCamelCase (_378)
toSelectorCase (_379)
getAncestors (node)
isChildOf (node, _381, _382)
createDocumentFromText (str, _383)
createNodesFromText (txt, wrap)
extractRGB ()
hex2rgb ()
rgb2hex ()
insertBefore (node, ref)
before (node, ref)
insertAfter (node, ref)
after (node, ref)
insert (node, ref, _395)
insertAtIndex (node, ref, _396)
textContent (node, text)
renderedTextContent (node)
remove (node)
</pre><h3>Properties</h3><pre>Object <a href="#dojo.xml.domUtil.nodeTypes">nodeTypes</a>
String dojoml
Number idIncrement
</pre><h2 id="dojo.xml.htmlUtil">dojo.xml.htmlUtil</h2><h3>Methods</h3><pre>disableSelect ()
enableSelect ()
getInnerWidth (node)
getOuterWidth (node)
getInnerHeight (node)
getOuterHeight (node)
getTotalOffset (node, type)
totalOffsetLeft (node)
getAbsoluteX (node)
totalOffsetTop (node)
getAbsoluteY (node)
getEventTarget (evt)
getScrollTop ()
getScrollLeft ()
evtTgt (evt)
getParentOfType (node, type)
getAttribute (node, attr)
getAttr (node, attr)
hasAttribute (node, attr)
hasAttr (node, attr)
getClass (node)
hasClass (node, _436)
prependClass (node, _438)
addClass (node, _439)
setClass (node, _440)
removeClass (node, _442)
getElementsByClass (_444, _445, _446, _447)
getElementsByClassName (_444, _445, _446, _447)
setOpacity (node, _456, _457)
getOpacity (node)
clearOpacity (node)
gravity (node, e)
overElement (_465, e)
insertCssRule (_472, _473, _474)
insertCSSRule (_476, _477, _478)
removeCssRule (_479)
removeCSSRule (_480)
insertCssFile (URI, doc, _483)
insertCSSFile (URI, doc, _487)
getBackgroundColor (node)
getUniqueId ()
getStyle (el, css)
</pre><h3>Properties</h3><pre>undefined styleSheet
Object <a href="#dojo.xml.htmlUtil.classMatchType">classMatchType</a>
</pre>

View File

@ -0,0 +1,51 @@
Files baked into this package:
dojoGuardStart.js,
../src/bootstrap1.js,
../src/loader.js,
dojoGuardEnd.js,
../src/hostenv_browser.js,
../src/bootstrap2.js,
../src/string/common.js,
../src/string.js,
../src/lang/common.js,
../src/lang/extras.js,
../src/io.js,
../src/lang/array.js,
../src/lang/func.js,
../src/string/extras.js,
../src/dom.js,
../src/undo/browser.js,
../src/io/BrowserIO.js,
../src/io/cookie.js,
../src/io/__package__.js,
../src/event.js,
../src/event/topic.js,
../src/event/browser.js,
../src/event/__package__.js,
../src/xml/Parse.js,
../src/lang/declare.js,
../src/widget/Manager.js,
../src/widget/Widget.js,
../src/namespace.js,
../src/widget/Parse.js,
../src/namespaces/dojo.js,
../src/html/style.js,
../src/uri/Uri.js,
../src/uri/__package__.js,
../src/widget/DomWidget.js,
../src/html/common.js,
../src/html/layout.js,
../src/html/util.js,
../src/html/display.js,
../src/lfx/Animation.js,
../src/graphics/color.js,
../src/html/color.js,
../src/lfx/html.js,
../src/lfx/__package__.js,
../src/lfx/toggle.js,
../src/widget/HtmlWidget.js,
../src/widget/__package__.js

7822
public/javascripts/dojo/dojo.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,54 @@
<!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>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
<script type="text/javascript">
// <!--
var noInit = false;
var domain = "";
// document.domain = "localhost";
function init(){
// parse the query string if there is one to try to get args that
// we can act on
var sparams = document.location.search;
if(sparams.length >= 0){
if(sparams.charAt(0) == "?"){
sparams = sparams.substring(1);
}
var ss = (sparams.indexOf("&amp;") >= 0) ? "&amp;" : "&";
sparams = sparams.split(ss);
for(var x=0; x<sparams.length; x++){
var tp = sparams[x].split("=");
if(typeof window[tp[0]] != "undefined"){
window[tp[0]] = ((tp[1]=="true")||(tp[1]=="false")) ? eval(tp[1]) : tp[1];
}
}
}
if(noInit){ return; }
if(domain.length > 0){
document.domain = domain;
}
if((window.parent != window)&&(window.parent["dojo"])){
//Set the page title so IE history shows up with a somewhat correct name.
document.title = window.parent.document.title;
//Notify parent that we are loaded.
var pdj = window.parent.dojo;
if(pdj["undo"] && pdj["undo"]["browser"]){
pdj.undo.browser.iframeLoaded(null, window.location);
}
}
}
// -->
</script>
</head>
<body onload="try{ init(); }catch(e){ alert(e); }">
<h4>The Dojo Toolkit -- iframe_history.html</h4>
<p>This file is used in Dojo's back/fwd button management.</p>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More