moving to vm on desktop
This commit is contained in:
parent
c15cb0813f
commit
b5c15da9ff
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
BUNDLE_WITHOUT: ""
|
|
@ -0,0 +1,207 @@
|
|||
# DO NOT MODIFY THIS FILE
|
||||
|
||||
require 'digest/sha1'
|
||||
require "rubygems"
|
||||
|
||||
module Gem
|
||||
class Dependency
|
||||
if !instance_methods.map { |m| m.to_s }.include?("requirement")
|
||||
def requirement
|
||||
version_requirements
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Bundler
|
||||
module SharedHelpers
|
||||
|
||||
def default_gemfile
|
||||
gemfile = find_gemfile
|
||||
gemfile or raise GemfileNotFound, "The default Gemfile was not found"
|
||||
Pathname.new(gemfile)
|
||||
end
|
||||
|
||||
def in_bundle?
|
||||
find_gemfile
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_gemfile
|
||||
return ENV['BUNDLE_GEMFILE'] if ENV['BUNDLE_GEMFILE']
|
||||
|
||||
previous = nil
|
||||
current = File.expand_path(Dir.pwd)
|
||||
|
||||
until !File.directory?(current) || current == previous
|
||||
filename = File.join(current, 'Gemfile')
|
||||
return filename if File.file?(filename)
|
||||
current, previous = File.expand_path("..", current), current
|
||||
end
|
||||
end
|
||||
|
||||
def clean_load_path
|
||||
# handle 1.9 where system gems are always on the load path
|
||||
if defined?(::Gem)
|
||||
me = File.expand_path("../../", __FILE__)
|
||||
$LOAD_PATH.reject! do |p|
|
||||
next if File.expand_path(p).include?(me)
|
||||
p != File.dirname(__FILE__) &&
|
||||
Gem.path.any? { |gp| p.include?(gp) }
|
||||
end
|
||||
$LOAD_PATH.uniq!
|
||||
end
|
||||
end
|
||||
|
||||
def reverse_rubygems_kernel_mixin
|
||||
# Disable rubygems' gem activation system
|
||||
::Kernel.class_eval do
|
||||
if private_method_defined?(:gem_original_require)
|
||||
alias rubygems_require require
|
||||
alias require gem_original_require
|
||||
end
|
||||
|
||||
undef gem
|
||||
end
|
||||
end
|
||||
|
||||
def cripple_rubygems(specs)
|
||||
reverse_rubygems_kernel_mixin
|
||||
|
||||
executables = specs.map { |s| s.executables }.flatten
|
||||
|
||||
:: Kernel.class_eval do
|
||||
private
|
||||
def gem(*) ; end
|
||||
end
|
||||
Gem.source_index # ensure RubyGems is fully loaded
|
||||
|
||||
::Kernel.send(:define_method, :gem) do |dep, *reqs|
|
||||
if executables.include? File.basename(caller.first.split(':').first)
|
||||
return
|
||||
end
|
||||
opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
|
||||
|
||||
unless dep.respond_to?(:name) && dep.respond_to?(:requirement)
|
||||
dep = Gem::Dependency.new(dep, reqs)
|
||||
end
|
||||
|
||||
spec = specs.find { |s| s.name == dep.name }
|
||||
|
||||
if spec.nil?
|
||||
e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile."
|
||||
e.name = dep.name
|
||||
e.version_requirement = dep.requirement
|
||||
raise e
|
||||
elsif dep !~ spec
|
||||
e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \
|
||||
"Make sure all dependencies are added to Gemfile."
|
||||
e.name = dep.name
|
||||
e.version_requirement = dep.requirement
|
||||
raise e
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# === Following hacks are to improve on the generated bin wrappers ===
|
||||
|
||||
# Yeah, talk about a hack
|
||||
source_index_class = (class << Gem::SourceIndex ; self ; end)
|
||||
source_index_class.send(:define_method, :from_gems_in) do |*args|
|
||||
source_index = Gem::SourceIndex.new
|
||||
source_index.spec_dirs = *args
|
||||
source_index.add_specs(*specs)
|
||||
source_index
|
||||
end
|
||||
|
||||
# OMG more hacks
|
||||
gem_class = (class << Gem ; self ; end)
|
||||
gem_class.send(:define_method, :bin_path) do |name, *args|
|
||||
exec_name, *reqs = args
|
||||
|
||||
spec = nil
|
||||
|
||||
if exec_name
|
||||
spec = specs.find { |s| s.executables.include?(exec_name) }
|
||||
spec or raise Gem::Exception, "can't find executable #{exec_name}"
|
||||
else
|
||||
spec = specs.find { |s| s.name == name }
|
||||
exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}"
|
||||
end
|
||||
|
||||
File.join(spec.full_gem_path, spec.bindir, exec_name)
|
||||
end
|
||||
end
|
||||
|
||||
extend self
|
||||
end
|
||||
end
|
||||
|
||||
module Bundler
|
||||
LOCKED_BY = '0.9.11'
|
||||
FINGERPRINT = "bc067d01abbb21b054cfc123f404a7874dfc8f94"
|
||||
AUTOREQUIRES = {:test=>[["faker", false], ["shoulda", false], ["factory_girl", false]], :default=>[["mysql", false], ["formtastic", false], ["paperclip", false], ["will_paginate", false], ["clearance", false]], :development=>[["mongrel", false]], :developemtn=>[["faker", false]]}
|
||||
SPECS = [
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/faker-0.3.1.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/faker-0.3.1/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/mongrel-1.1.5.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/mongrel-1.1.5/lib", "/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/mongrel-1.1.5/ext"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/fastthread-1.0.7.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/fastthread-1.0.7/lib", "/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/fastthread-1.0.7/ext"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/mysql-2.8.1.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/mysql-2.8.1/lib", "/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/mysql-2.8.1/ext"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/shoulda-2.10.3.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/shoulda-2.10.3/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/formtastic-0.9.7.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/formtastic-0.9.7/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/rack-1.0.1.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/rack-1.0.1/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/gem_plugin-0.2.3.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/gem_plugin-0.2.3/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/cgi_multipart_eof_fix-2.5.0.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/cgi_multipart_eof_fix-2.5.0/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/paperclip-2.3.1.1.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/paperclip-2.3.1.1/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/will_paginate-2.3.12.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/will_paginate-2.3.12/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/factory_girl-1.2.3.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/factory_girl-1.2.3/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/actionpack-2.3.5.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/actionpack-2.3.5/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/daemons-1.0.10.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/daemons-1.0.10/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/clearance-0.8.8.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/clearance-0.8.8/lib"]},
|
||||
{:loaded_from=>"/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/specifications/activesupport-2.3.5.gemspec", :load_paths=>["/Users/sdavis/.rvm/gems/ruby-1.8.7-p249/gems/activesupport-2.3.5/lib"]},
|
||||
].map do |hash|
|
||||
spec = eval(File.read(hash[:loaded_from]), binding, hash[:loaded_from])
|
||||
spec.loaded_from = hash[:loaded_from]
|
||||
spec.require_paths = hash[:load_paths]
|
||||
spec
|
||||
end
|
||||
|
||||
extend SharedHelpers
|
||||
|
||||
def self.match_fingerprint
|
||||
print = Digest::SHA1.hexdigest(File.read(File.expand_path('../../Gemfile', __FILE__)))
|
||||
unless print == FINGERPRINT
|
||||
abort 'Gemfile changed since you last locked. Please `bundle lock` to relock.'
|
||||
end
|
||||
end
|
||||
|
||||
def self.setup(*groups)
|
||||
match_fingerprint
|
||||
clean_load_path
|
||||
cripple_rubygems(SPECS)
|
||||
SPECS.each do |spec|
|
||||
Gem.loaded_specs[spec.name] = spec
|
||||
$LOAD_PATH.unshift(*spec.require_paths)
|
||||
end
|
||||
end
|
||||
|
||||
def self.require(*groups)
|
||||
groups = [:default] if groups.empty?
|
||||
groups.each do |group|
|
||||
(AUTOREQUIRES[group.to_sym] || []).each do |file, explicit|
|
||||
if explicit
|
||||
Kernel.require file
|
||||
else
|
||||
begin
|
||||
Kernel.require file
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Setup bundle when it's required.
|
||||
setup
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
# A sample Gemfile
|
||||
source :gemcutter
|
||||
#
|
||||
#gem "rails", "2.3.5"
|
||||
|
||||
gem 'clearance'
|
||||
gem 'will_paginate'
|
||||
|
||||
gem 'paperclip'
|
||||
gem 'formtastic'
|
||||
gem 'mysql'
|
||||
#gem "matthuhiggins-foreigner", :require => "foreigner"
|
||||
|
||||
|
||||
group :test do
|
||||
gem 'shoulda'
|
||||
gem 'factory_girl'
|
||||
gem 'faker', :group => [:test, :developemtn]
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'mongrel'
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
dependencies:
|
||||
faker:
|
||||
group:
|
||||
- :test
|
||||
- :developemtn
|
||||
version: ">= 0"
|
||||
mongrel:
|
||||
group:
|
||||
- :development
|
||||
version: ">= 0"
|
||||
mysql:
|
||||
group:
|
||||
- :default
|
||||
version: ">= 0"
|
||||
shoulda:
|
||||
group:
|
||||
- :test
|
||||
version: ">= 0"
|
||||
formtastic:
|
||||
group:
|
||||
- :default
|
||||
version: ">= 0"
|
||||
factory_girl:
|
||||
group:
|
||||
- :test
|
||||
version: ">= 0"
|
||||
paperclip:
|
||||
group:
|
||||
- :default
|
||||
version: ">= 0"
|
||||
will_paginate:
|
||||
group:
|
||||
- :default
|
||||
version: ">= 0"
|
||||
clearance:
|
||||
group:
|
||||
- :default
|
||||
version: ">= 0"
|
||||
specs:
|
||||
- faker:
|
||||
version: 0.3.1
|
||||
- fastthread:
|
||||
version: 1.0.7
|
||||
- mongrel:
|
||||
version: 1.1.5
|
||||
- mysql:
|
||||
version: 2.8.1
|
||||
- shoulda:
|
||||
version: 2.10.3
|
||||
- rack:
|
||||
version: 1.0.1
|
||||
- gem_plugin:
|
||||
version: 0.2.3
|
||||
- cgi_multipart_eof_fix:
|
||||
version: 2.5.0
|
||||
- formtastic:
|
||||
version: 0.9.7
|
||||
- will_paginate:
|
||||
version: 2.3.12
|
||||
- paperclip:
|
||||
version: 2.3.1.1
|
||||
- factory_girl:
|
||||
version: 1.2.3
|
||||
- daemons:
|
||||
version: 1.0.10
|
||||
- clearance:
|
||||
version: 0.8.8
|
||||
- actionpack:
|
||||
version: 2.3.5
|
||||
- activesupport:
|
||||
version: 2.3.5
|
||||
hash: bc067d01abbb21b054cfc123f404a7874dfc8f94
|
||||
sources:
|
||||
- Rubygems:
|
||||
uri: http://gemcutter.org
|
|
@ -11,4 +11,6 @@ class ApplicationController < ActionController::Base
|
|||
def set_page
|
||||
@page_title = "Collab"
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -10,12 +10,35 @@ class ProjectsController < ApplicationController
|
|||
format.xml { render :xml => @projects }
|
||||
end
|
||||
end
|
||||
|
||||
def join
|
||||
@project = Project.find(params[:project_id])
|
||||
@project.users << current_user
|
||||
if @project.save
|
||||
flash[:success] = "You have joined #{@project.name}"
|
||||
else
|
||||
flash[:error] = "There was a problem joining this project"
|
||||
end
|
||||
redirect_to project_path(@project)
|
||||
end
|
||||
|
||||
def leave
|
||||
@project = Project.find(params[:project_id])
|
||||
@project.users.delete current_user
|
||||
if @project.save
|
||||
flash[:success] = "You have been removed from #{@project.name}"
|
||||
else
|
||||
flash[:error] = "There was an error removing you form this project"
|
||||
end
|
||||
redirect_to project_path(@project)
|
||||
end
|
||||
|
||||
# GET /projects/1
|
||||
# GET /projects/1.xml
|
||||
def show
|
||||
@project = Project.find(params[:id], :include => [:users])
|
||||
@project = Project.find(params[:id], :include => [:users, :wall_posts])
|
||||
@tasks = @project.tasks.parents.paginate(:per_page => 30, :page => params[:page], :include => :tasks)
|
||||
@wall_posts = @project.wall_posts.paginate(:per_page => 15, :page => params[:post_page])
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.xml { render :xml => @project }
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
class WallController < ApplicationController
|
||||
before_filter :authenticate, :load_project
|
||||
|
||||
def create
|
||||
@wall = Wall.new(params[:wall])
|
||||
@wall.project = @project
|
||||
@wall.author = current_user
|
||||
@wall.save
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def load_project
|
||||
@project = Project.find(params[:project_id])
|
||||
end
|
||||
|
||||
end
|
|
@ -1,2 +1,13 @@
|
|||
module ProjectsHelper
|
||||
|
||||
def parse_wall_string(string)
|
||||
user_matches = string.scan(/@([a-zA-Z_0-9]+)/).flatten
|
||||
return string if user_matches.empty?
|
||||
User.find_all_by_short_name(user_matches).each do |user|
|
||||
string.gsub!("@#{user.short_name}", link_to("@#{user.short_name}", user_path(user.short_name)))
|
||||
end
|
||||
string
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module WallHelper
|
||||
include ProjectsHelper
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
class Project < ActiveRecord::Base
|
||||
has_many :tasks
|
||||
has_many :wall_posts, :class_name => "Wall", :foreign_key => "project_id", :order => "created_at DESC"
|
||||
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
|
||||
validates_presence_of :name
|
||||
has_and_belongs_to_many :users
|
||||
|
|
|
@ -7,7 +7,7 @@ class Task < ActiveRecord::Base
|
|||
named_scope :parents, :conditions => {:parent => nil}
|
||||
#validations
|
||||
validates_presence_of :name, :description, :project_id
|
||||
validates_associated :project
|
||||
|
||||
validate :assignee_validation, :owner_validation
|
||||
|
||||
def assignee_validation
|
||||
|
|
|
@ -5,13 +5,29 @@ class User < ActiveRecord::Base
|
|||
has_many :owned_tasks, :class_name => "Task", :foreign_key => "owner_id"
|
||||
has_many :assigned_tasks, :class_name => "Task", :foreign_key => "assigned_id"
|
||||
validates_uniqueness_of :short_name
|
||||
validates_presence_of :short_name
|
||||
validates_presence_of :email, :password, :short_name
|
||||
validates_format_of :phone, :with => /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/, :if => Proc.new {|user| !user.phone.blank?}
|
||||
validates_format_of :mobile, :with => /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/, :if => Proc.new {|user| !user.mobile.blank?}
|
||||
|
||||
before_validation :set_short_name
|
||||
|
||||
def set_short_name
|
||||
if short_name.blank?
|
||||
short_name = email.split('@')[0]
|
||||
end
|
||||
end
|
||||
|
||||
def gravatar(size = 48)
|
||||
hash = Digest::MD5.hexdigest email
|
||||
"http://www.gravatar.com/avatar/#{hash}.jpg?s=#{size}"
|
||||
end
|
||||
|
||||
def send_post_notification(post)
|
||||
project_id = post.project_id
|
||||
end
|
||||
|
||||
def send_project_notification(project)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
class Wall < ActiveRecord::Base
|
||||
|
||||
belongs_to :author, :class_name => "User", :foreign_key => "user_id"
|
||||
belongs_to :project
|
||||
|
||||
after_create :check_for_mentions, :check_for_hash_tags
|
||||
|
||||
def check_for_mentions
|
||||
mentions = text.scan(/@([a-zA-Z_0-9])/).flatten
|
||||
User.find_all_by_short_name(mentions).each{ |user| user.send_post_notification(self) }
|
||||
end
|
||||
|
||||
def check_for_hash_tags
|
||||
tags = text.scan(/#([a-zA-Z0-9_]+)/).flatten
|
||||
send_notice_to_members(project) if tags.include?('project')
|
||||
end
|
||||
|
||||
def send_notice_to_members(project)
|
||||
project.users.each {|user| user.send_project_notification(project)}
|
||||
end
|
||||
|
||||
end
|
|
@ -1,15 +1,40 @@
|
|||
<p>
|
||||
<b>Name:</b>
|
||||
<%=h @project.name %>
|
||||
</p>
|
||||
<div id='project_users'>
|
||||
<% @project.users.each do |user| %>
|
||||
<%= image_tag user.gravatar %> <%= link_to "@#{user.short_name}", user_path(user.short_name) %>
|
||||
<% end %>
|
||||
<h1><%=h @project.name.titleize %></h1>
|
||||
<p><%= link_to 'Edit', edit_project_path(@project) %></p>
|
||||
<div id='project_right'>
|
||||
<div id='project_users'>
|
||||
<h2>Users</h2>
|
||||
<% @project.users.each do |user| %>
|
||||
<div class='project_user_info'>
|
||||
<%= image_tag user.gravatar %> <%= link_to "@#{user.short_name}", user_path(user.short_name) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% unless @project.users.include?(current_user) %>
|
||||
<%= link_to "Join Project", join_project_path(@project), :method => :post %>
|
||||
<% else %>
|
||||
<%= link_to "Leave Project", leave_project_path(@project), :method => :delete %>
|
||||
<% end %>
|
||||
</div>
|
||||
<h2>Wall</h2>
|
||||
<div id='project_wall'>
|
||||
<div id='add_post'>
|
||||
<% remote_form_for :wall, :url => project_wall_index_path(@project) do |f| %>
|
||||
<%= f.text_area :text, :cols => 35, :rows => 10, :id=> :new_post %>
|
||||
<%= f.submit :Submit %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div id='post_list'>
|
||||
<% @wall_posts.each do |post| %>
|
||||
<%= render :partial => 'wall/wall_posts', :locals => {:post => post} %>
|
||||
<% end %>
|
||||
<%= will_paginate @wall_posts, :param_name => :post_page %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id='project_tasks'>
|
||||
<h2>Tasks</h2>
|
||||
<%= render :partial => 'tasks/task_list' %>
|
||||
<%= will_paginate @tasks %>
|
||||
</div>
|
||||
<%= will_paginate @tasks %>
|
||||
<%= link_to 'Edit', edit_project_path(@project) %> |
|
||||
<br style='clear:both'/>
|
||||
<%= link_to 'Back', projects_path %>
|
|
@ -1,21 +1,23 @@
|
|||
<% unless @tasks.empty? %>
|
||||
<table class='task_list'>
|
||||
<table class='task_list' cellspacing='0' cellpadding='0'>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Project</th>
|
||||
<th>Description</th>
|
||||
<th>Children</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
|
||||
<% @tasks.each do |task| %>
|
||||
<tr class="<%= cycle(:even, :odd)%>">
|
||||
<td><%=h task.name %></td>
|
||||
<td><%= link_to h(task.name), project_task_path(@project, task) %></td>
|
||||
<td><%= link_to h(task.project.name), project_path(task.project) %></td>
|
||||
<td><%=h task.description %></td>
|
||||
<td><%=h task.tasks.size %></td>
|
||||
<td><%= link_to 'Show', project_task_path(@project, task) %></td>
|
||||
<td><%= link_to 'Edit', edit_project_task_path(@project, task) %></td>
|
||||
<td><%= link_to 'Destroy', project_task_path(@project, task), :confirm => 'Are you sure?', :method => :delete %></td>
|
||||
<td><%=h truncate(task.description, :length => 158) %></td>
|
||||
<td><%= link_to h(task.tasks.size), project_task_path(@project, task) %></td>
|
||||
<td>
|
||||
<%= link_to 'Edit', edit_project_task_path(@project, task) %>
|
||||
<%= link_to 'Destroy', project_task_path(@project, task), :confirm => 'Are you sure?', :method => :delete %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
<p>
|
||||
<b>Name:</b>
|
||||
<%=h @task.name %>
|
||||
</p>
|
||||
<h1><%=h @task.name %></h1>
|
||||
|
||||
<p>
|
||||
<b>Project:</b>
|
||||
<%=h @task.project.name %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<p id='task_description'>
|
||||
<b>Description:</b>
|
||||
<%=h @task.description %>
|
||||
</p>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<div class='post'>
|
||||
<%= image_tag post.author.gravatar(16), :alt => post.author.short_name %>
|
||||
<%= parse_wall_string(post.text) %>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
if @wall.save
|
||||
page.insert_html :prepend, :post_list, :partial => 'wall_posts', :locals => {:post => @wall }
|
||||
page[:post_list].visual_effect :highlight
|
||||
page[:new_post].val('')
|
||||
else
|
||||
page.alert("Wall post is invalid")
|
||||
end
|
|
@ -108,3 +108,21 @@ end
|
|||
|
||||
# All that for this:
|
||||
Rails.boot!
|
||||
|
||||
class Rails::Boot
|
||||
def run
|
||||
load_initializer
|
||||
extend_environment
|
||||
Rails::Initializer.run(:set_load_path)
|
||||
end
|
||||
|
||||
def extend_environment
|
||||
Rails::Initializer.class_eval do
|
||||
old_load = instance_method(:load_environment)
|
||||
define_method(:load_environment) do
|
||||
Bundler.require :default, Rails.env
|
||||
old_load.bind(self).call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,11 +2,14 @@ ActionController::Routing::Routes.draw do |map|
|
|||
Clearance::Routes.draw(map)
|
||||
map.user '/users/:id', :controller => :users, :action => :show
|
||||
map.user_inline_edit '/users/:id/inline', :controller => :users, :action => :inline, :conditions => { :method => :post }
|
||||
map.join_project '/projects/:project_id/join', :controller => :projects, :action => :join, :conditions => {:method => :post}
|
||||
map.leave_project '/projects/:project_id/leave', :controller => :projects, :action => :leave, :conditions => {:method => :delete}
|
||||
#map.dashboard '/dashboard', :controller => :users, :action => :dashboard
|
||||
|
||||
|
||||
map.resources :projects do |projects|
|
||||
projects.resources :tasks
|
||||
projects.resources :wall
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
class CreateWalls < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :walls do |t|
|
||||
t.belongs_to :project
|
||||
t.text :text
|
||||
t.belongs_to :user
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :walls
|
||||
end
|
||||
end
|
10
db/schema.rb
10
db/schema.rb
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20100305060621) do
|
||||
ActiveRecord::Schema.define(:version => 20100312004836) do
|
||||
|
||||
create_table "projects", :force => true do |t|
|
||||
t.string "name"
|
||||
|
@ -59,6 +59,14 @@ ActiveRecord::Schema.define(:version => 20100305060621) do
|
|||
add_index "users", ["id", "confirmation_token"], :name => "index_users_on_id_and_confirmation_token"
|
||||
add_index "users", ["remember_token"], :name => "index_users_on_remember_token"
|
||||
|
||||
create_table "walls", :force => true do |t|
|
||||
t.integer "project_id"
|
||||
t.text "text"
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_foreign_key "projects", "users", :name => "projects_owner_id_fk", :column => "owner_id"
|
||||
|
||||
add_foreign_key "tasks", "users", :name => "tasks_owner_id_fk", :column => "owner_id"
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
require 'factory_girl'
|
||||
require 'faker'
|
||||
|
||||
Factory.define :user do |f|
|
||||
f.sequence(:email) { |n| "email_#{n}@localhost.com" }
|
||||
f.sequence(:password) { |n| "password#{n}" }
|
||||
f.sequence(:short_name) { |n| "short_#{n}" }
|
||||
end
|
||||
|
||||
Factory.define :project do |f|
|
||||
f.sequence(:name) {|n| "project #{n}"}
|
||||
end
|
||||
|
||||
Factory.define :task do |f|
|
||||
f.sequence(:name) {|n| "task #{n}"}
|
||||
f.description Faker::Lorem.words(50)
|
||||
end
|
||||
|
||||
Factory.define :wall do |f|
|
||||
f.text "@short_2 This is a wall post of fun and goodness"
|
||||
end
|
|
@ -1,7 +1,5 @@
|
|||
path = File.join(RAILS_ROOT, 'factories')
|
||||
require 'factory_girl'
|
||||
["user", "task", "project"].each {|factory| require File.join(path, "#{factory}_factory")}
|
||||
|
||||
require 'factories/factories'
|
||||
class FactoryLoader
|
||||
|
||||
def self.up
|
||||
|
@ -30,6 +28,7 @@ class FactoryLoader
|
|||
10.times do |i|
|
||||
p = Factory.create(:project, :owner => user, :users => [user])
|
||||
self.create_tasks(p, user)
|
||||
self.create_wall_posts(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -46,5 +45,11 @@ class FactoryLoader
|
|||
end
|
||||
end
|
||||
|
||||
def self.create_wall_posts(project)
|
||||
User.all.each do |user|
|
||||
Factory.create(:wall, :author => user, :project => project)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
require 'factory_girl'
|
||||
|
||||
Factory.define :project do |f|
|
||||
f.sequence(:name) {|n| "project #{n}"}
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
require 'factory_girl'
|
||||
require 'faker'
|
||||
Factory.define :task do |f|
|
||||
f.sequence(:name) {|n| "task #{n}"}
|
||||
f.description Faker::Lorem.paragraphs(1)
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
require 'factory_girl'
|
||||
|
||||
|
||||
Factory.define :user do |f|
|
||||
f.sequence(:email) { |n| "email_#{n}@localhost.com" }
|
||||
f.sequence(:password) { |n| "password#{n}" }
|
||||
f.sequence(:short_name) { |n| "short_#{n}" }
|
||||
end
|
|
@ -1,2 +1,3 @@
|
|||
|
||||
// Place your application-specific JavaScript functions and classes here
|
||||
// This file is automatically included by javascript_include_tag :defaults
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
(function($){$().ajaxSend(function(a,xhr,s){xhr.setRequestHeader("Accept","text/javascript, text/html, application/xml, text/xml, */*")})})(jQuery);(function($){$.fn.reset=function(){return this.each(function(){if(typeof this.reset=="function"||(typeof this.reset=="object"&&!this.reset.nodeType)){this.reset()}})};$.fn.enable=function(){return this.each(function(){this.disabled=false})};$.fn.disable=function(){return this.each(function(){this.disabled=true})}})(jQuery);(function($){$.extend({fieldEvent:function(el,obs){var field=el[0]||el,e="change";if(field.type=="radio"||field.type=="checkbox"){e="click"}else{if(obs&&field.type=="text"||field.type=="textarea"){e="keyup"}}return e}});$.fn.extend({delayedObserver:function(delay,callback){var el=$(this);if(typeof window.delayedObserverStack=="undefined"){window.delayedObserverStack=[]}if(typeof window.delayedObserverCallback=="undefined"){window.delayedObserverCallback=function(stackPos){observed=window.delayedObserverStack[stackPos];if(observed.timer){clearTimeout(observed.timer)}observed.timer=setTimeout(function(){observed.timer=null;observed.callback(observed.obj,observed.obj.formVal())},observed.delay*1000);observed.oldVal=observed.obj.formVal()}}window.delayedObserverStack.push({obj:el,timer:null,delay:delay,oldVal:el.formVal(),callback:callback});var stackPos=window.delayedObserverStack.length-1;if(el[0].tagName=="FORM"){$(":input",el).each(function(){var field=$(this);field.bind($.fieldEvent(field,delay),function(){observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.obj.oldVal){return}else{window.delayedObserverCallback(stackPos)}})})}else{el.bind($.fieldEvent(el,delay),function(){observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.obj.oldVal){return}else{window.delayedObserverCallback(stackPos)}})}},formVal:function(){var el=this[0];if(el.tagName=="FORM"){return this.serialize()}if(el.type=="checkbox"||self.type=="radio"){return this.filter("input:checked").val()||""}else{return this.val()}}})})(jQuery);(function($){$.fn.extend({visualEffect:function(o){e=o.replace(/\_(.)/g,function(m,l){return l.toUpperCase()});return eval("$(this)."+e+"()")},appear:function(speed,callback){return this.fadeIn(speed,callback)},blindDown:function(speed,callback){return this.show("blind",{direction:"vertical"},speed,callback)},blindUp:function(speed,callback){return this.hide("blind",{direction:"vertical"},speed,callback)},blindRight:function(speed,callback){return this.show("blind",{direction:"horizontal"},speed,callback)},blindLeft:function(speed,callback){this.hide("blind",{direction:"horizontal"},speed,callback);return this},dropOut:function(speed,callback){return this.hide("drop",{direction:"down"},speed,callback)},dropIn:function(speed,callback){return this.show("drop",{direction:"up"},speed,callback)},fade:function(speed,callback){return this.fadeOut(speed,callback)},fadeToggle:function(speed,callback){return this.animate({opacity:"toggle"},speed,callback)},fold:function(speed,callback){return this.hide("fold",{},speed,callback)},foldOut:function(speed,callback){return this.show("fold",{},speed,callback)},grow:function(speed,callback){return this.show("scale",{},speed,callback)},highlight:function(speed,callback){return this.show("highlight",{},speed,callback)},puff:function(speed,callback){return this.hide("puff",{},speed,callback)},pulsate:function(speed,callback){return this.show("pulsate",{},speed,callback)},shake:function(speed,callback){return this.show("shake",{},speed,callback)},shrink:function(speed,callback){return this.hide("scale",{},speed,callback)},squish:function(speed,callback){return this.hide("scale",{origin:["top","left"]},speed,callback)},slideUp:function(speed,callback){return this.hide("slide",{direction:"up"},speed,callback)},slideDown:function(speed,callback){return this.show("slide",{direction:"up"},speed,callback)},switchOff:function(speed,callback){return this.hide("clip",{},speed,callback)},switchOn:function(speed,callback){return this.show("clip",{},speed,callback)}})})(jQuery);
|
||||
(function($){$.ajaxSettings.accepts._default="text/javascript, text/html, application/xml, text/xml, */*"})(jQuery);(function($){$.fn.reset=function(){return this.each(function(){if(typeof this.reset=="function"||(typeof this.reset=="object"&&!this.reset.nodeType)){this.reset()}})};$.fn.enable=function(){return this.each(function(){this.disabled=false})};$.fn.disable=function(){return this.each(function(){this.disabled=true})}})(jQuery);(function($){$.extend({fieldEvent:function(el,obs){var field=el[0]||el,e="change";if(field.type=="radio"||field.type=="checkbox"){e="click"}else{if(obs&&(field.type=="text"||field.type=="textarea"||field.type=="password")){e="keyup"}}return e}});$.fn.extend({delayedObserver:function(delay,callback){var el=$(this);if(typeof window.delayedObserverStack=="undefined"){window.delayedObserverStack=[]}if(typeof window.delayedObserverCallback=="undefined"){window.delayedObserverCallback=function(stackPos){var observed=window.delayedObserverStack[stackPos];if(observed.timer){clearTimeout(observed.timer)}observed.timer=setTimeout(function(){observed.timer=null;observed.callback(observed.obj,observed.obj.formVal())},observed.delay*1000);observed.oldVal=observed.obj.formVal()}}window.delayedObserverStack.push({obj:el,timer:null,delay:delay,oldVal:el.formVal(),callback:callback});var stackPos=window.delayedObserverStack.length-1;if(el[0].tagName=="FORM"){$(":input",el).each(function(){var field=$(this);field.bind($.fieldEvent(field,delay),function(){var observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.oldVal){return}else{window.delayedObserverCallback(stackPos)}})})}else{el.bind($.fieldEvent(el,delay),function(){var observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.oldVal){return}else{window.delayedObserverCallback(stackPos)}})}},formVal:function(){var el=this[0];if(el.tagName=="FORM"){return this.serialize()}if(el.type=="checkbox"||el.type=="radio"){return this.filter("input:checked").val()||""}else{return this.val()}}})})(jQuery);(function($){$.fn.extend({visualEffect:function(o,options){if(options){speed=options.duration*1000}else{speed=null}e=o.replace(/\_(.)/g,function(m,l){return l.toUpperCase()});return eval("$(this)."+e+"("+speed+")")},appear:function(speed,callback){return this.fadeIn(speed,callback)},blindDown:function(speed,callback){return this.show("blind",{direction:"vertical"},speed,callback)},blindUp:function(speed,callback){return this.hide("blind",{direction:"vertical"},speed,callback)},blindRight:function(speed,callback){return this.show("blind",{direction:"horizontal"},speed,callback)},blindLeft:function(speed,callback){this.hide("blind",{direction:"horizontal"},speed,callback);return this},dropOut:function(speed,callback){return this.hide("drop",{direction:"down"},speed,callback)},dropIn:function(speed,callback){return this.show("drop",{direction:"up"},speed,callback)},fade:function(speed,callback){return this.fadeOut(speed,callback)},fadeToggle:function(speed,callback){return this.animate({opacity:"toggle"},speed,callback)},fold:function(speed,callback){return this.hide("fold",{},speed,callback)},foldOut:function(speed,callback){return this.show("fold",{},speed,callback)},grow:function(speed,callback){return this.show("scale",{},speed,callback)},highlight:function(speed,callback){return this.show("highlight",{},speed,callback)},puff:function(speed,callback){return this.hide("puff",{},speed,callback)},pulsate:function(speed,callback){return this.show("pulsate",{},speed,callback)},shake:function(speed,callback){return this.show("shake",{},speed,callback)},shrink:function(speed,callback){return this.hide("scale",{},speed,callback)},squish:function(speed,callback){return this.hide("scale",{origin:["top","left"]},speed,callback)},slideUp:function(speed,callback){return this.hide("slide",{direction:"up"},speed,callback)},slideDown:function(speed,callback){return this.show("slide",{direction:"up"},speed,callback)},switchOff:function(speed,callback){return this.hide("clip",{},speed,callback)},switchOn:function(speed,callback){return this.show("clip",{},speed,callback)}})})(jQuery);
|
|
@ -4,7 +4,11 @@
|
|||
}
|
||||
|
||||
h1 {
|
||||
margin-top:10px
|
||||
margin:10px
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin:5px;
|
||||
}
|
||||
|
||||
div.flash {
|
||||
|
@ -21,6 +25,11 @@ div#flash_error {
|
|||
border:red 5px solid;
|
||||
}
|
||||
|
||||
div#flash_failure{
|
||||
color:red;
|
||||
border:red 5px solid;
|
||||
}
|
||||
|
||||
div#flash_notice {
|
||||
color:blue;
|
||||
border:blue 5px solid;
|
||||
|
@ -31,6 +40,9 @@ div#flash_success {
|
|||
border:green 5px solid;
|
||||
}
|
||||
|
||||
div#content {
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
table.task_list tr.odd{
|
||||
background-color:#ddd;
|
||||
|
@ -59,3 +71,47 @@ div#wrapper {
|
|||
margin-top:30px;
|
||||
background-color:white;
|
||||
}
|
||||
|
||||
/** Projects **/
|
||||
|
||||
div#project_right {
|
||||
width:30%;
|
||||
float:right;
|
||||
}
|
||||
|
||||
div#project_tasks {
|
||||
float:left;
|
||||
width:60%;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
div.project_user_info a{
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
div#post_list {
|
||||
border:1px solid #ccc;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
div.post {
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
table.task_list tr {
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
table.task_list tr td {
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
table.task_list tr th {
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
/** Tasks **/
|
||||
|
||||
div#task_description {
|
||||
|
||||
}
|
|
@ -1,13 +1 @@
|
|||
Factory.sequence :email do |n|
|
||||
"user#{n}@example.com"
|
||||
end
|
||||
|
||||
Factory.define :user do |user|
|
||||
user.email { Factory.next :email }
|
||||
user.password { "password" }
|
||||
user.password_confirmation { "password" }
|
||||
end
|
||||
|
||||
Factory.define :email_confirmed_user, :parent => :user do |user|
|
||||
user.email_confirmed { true }
|
||||
end
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
|
||||
one:
|
||||
belongs_to:
|
||||
text: MyText
|
||||
|
||||
two:
|
||||
belongs_to:
|
||||
text: MyText
|
|
@ -1,6 +1,12 @@
|
|||
require 'test_helper'
|
||||
|
||||
class ProjectsControllerTest < ActionController::TestCase
|
||||
|
||||
def setup
|
||||
@user = Factory(:user)
|
||||
sign_in_as(@user)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get :index
|
||||
assert_response :success
|
||||
|
@ -13,31 +19,32 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||
end
|
||||
|
||||
test "should create project" do
|
||||
|
||||
assert_difference('Project.count') do
|
||||
post :create, :project => { }
|
||||
post :create, :project => Factory.attributes_for(:project)
|
||||
end
|
||||
|
||||
assert_redirected_to project_path(assigns(:project))
|
||||
end
|
||||
|
||||
test "should show project" do
|
||||
get :show, :id => projects(:one).to_param
|
||||
get :show, :id => Factory(:project).id
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get :edit, :id => projects(:one).to_param
|
||||
get :edit, :id => Factory(:project).id
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update project" do
|
||||
put :update, :id => projects(:one).to_param, :project => { }
|
||||
put :update, :id => Factory(:project).id, :project => Factory.attributes_for(:project)
|
||||
assert_redirected_to project_path(assigns(:project))
|
||||
end
|
||||
|
||||
test "should destroy project" do
|
||||
project = Factory(:project)
|
||||
assert_difference('Project.count', -1) do
|
||||
delete :destroy, :id => projects(:one).to_param
|
||||
delete :destroy, :id => project.id
|
||||
end
|
||||
|
||||
assert_redirected_to projects_path
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
require 'test_helper'
|
||||
|
||||
class WallControllerTest < ActionController::TestCase
|
||||
# Replace this with your real tests.
|
||||
test "the truth" do
|
||||
assert true
|
||||
end
|
||||
end
|
|
@ -37,4 +37,17 @@ class ActiveSupport::TestCase
|
|||
#fixtures :all
|
||||
|
||||
# Add more helper methods to be used by all tests here...
|
||||
|
||||
def sign_in_as(user)
|
||||
@controller.current_user = user
|
||||
return user
|
||||
end
|
||||
|
||||
def sign_in
|
||||
sign_in_as Factory(:email_confirmed_user)
|
||||
end
|
||||
|
||||
def sign_out
|
||||
@controller.current_user = nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
require 'test_helper'
|
||||
|
||||
class WallHelperTest < ActionView::TestCase
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
require 'test_helper'
|
||||
|
||||
class WallTest < ActiveSupport::TestCase
|
||||
# Replace this with your real tests.
|
||||
test "the truth" do
|
||||
assert true
|
||||
end
|
||||
end
|
|
@ -1,11 +1,19 @@
|
|||
SVN
|
||||
0.5.0 (31 July 2009)
|
||||
* Gemification
|
||||
* Support for Ruby 1.9.X
|
||||
* Updated to jQuery 1.3.2
|
||||
* Updated to jQuery UI 1.7.2
|
||||
* Created a jrails binary (runs rake tasks) because rails does not (yet?) pickup
|
||||
tasks from gem plugins
|
||||
* Changed default to use jQuery compatibility name (not $)
|
||||
* Created a scrub task that will remove the prototype / script.aculo.us
|
||||
javascript files
|
||||
* better approximate scriptaculous effect names
|
||||
* add support for page[:element_id].visual_effect(:effect) as well as page.visual_effect(:effect, :element_id)
|
||||
* added a reset form function to jrails.js (stolen from jquery form)
|
||||
* can now use jquery selectors in all functions
|
||||
* added javascript_function helper to render inline rjs helpers
|
||||
* better support for sortable_element
|
||||
* updated to jquery-ui 1.5.1
|
||||
|
||||
0.4.0 (16 June 2008)
|
||||
* updated to jquery-ui 1.5 & merged js into single file
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
Copyright (c) 2008 Aaron Eisenberger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,21 @@
|
|||
= jRails
|
||||
|
||||
jRails is a drop-in jQuery replacement for the Rails Prototype/script.aculo.us helpers.
|
||||
|
||||
== Resources
|
||||
|
||||
Install
|
||||
|
||||
* .script/plugin install git://github.com/aaronchi/jrails.git
|
||||
|
||||
Project Site
|
||||
|
||||
* http://code.google.com/p/ennerchi
|
||||
|
||||
Web Site
|
||||
|
||||
* http://www.ennerchi.com/projects/jrails
|
||||
|
||||
Group Site
|
||||
|
||||
* http://groups.google.com/group/jrails
|
|
@ -0,0 +1,19 @@
|
|||
require 'rubygems'
|
||||
require 'rake'
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |gem|
|
||||
gem.name = "jrails"
|
||||
gem.summary = "jRails is a drop-in jQuery replacement for the Rails Prototype/script.aculo.us helpers."
|
||||
gem.description = "Using jRails, you can get all of the same default Rails helpers for javascript functionality using the lighter jQuery library."
|
||||
gem.email = "aaronchi@gmail.com"
|
||||
gem.homepage = "http://ennerchi.com/projects/jrails"
|
||||
gem.authors = ["Aaron Eisenberger", "Patrick Hurley"]
|
||||
gem.rubyforge_project = "jrails"
|
||||
gem.files = FileList["[A-Z]*.rb","{bin,javascripts,lib,rails,tasks}/**/*"]
|
||||
end
|
||||
Jeweler::GemcutterTasks.new
|
||||
rescue LoadError
|
||||
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
:build:
|
||||
:patch: 0
|
||||
:major: 0
|
||||
:minor: 6
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rubygems'
|
||||
require 'rake'
|
||||
|
||||
RAILS_ROOT = Dir.pwd
|
||||
rakeapp = Rake.application
|
||||
fname =File.join(File.dirname(__FILE__), '..', 'tasks', 'jrails.rake')
|
||||
load fname
|
||||
|
||||
task :help do
|
||||
puts "jrails [command]\n\n"
|
||||
rakeapp.options.show_task_pattern = Regexp.new('^[hius]')
|
||||
rakeapp.display_tasks_and_comments
|
||||
end
|
||||
|
||||
desc 'Installs the jQuery and jRails javascripts to public/javascripts'
|
||||
task :install do
|
||||
Rake::Task['jrails:js:install'].invoke
|
||||
end
|
||||
|
||||
desc 'Remove the prototype / script.aculo.us javascript files'
|
||||
task :scrub do
|
||||
Rake::Task['jrails:js:scrub'].invoke
|
||||
end
|
||||
|
||||
rakeapp.init("jrails")
|
||||
task :default => [:help]
|
||||
|
||||
rakeapp.top_level
|
|
@ -1,6 +1 @@
|
|||
# uncomment to use jQuery.noConflict()
|
||||
#ActionView::Helpers::PrototypeHelper::JQUERY_VAR = 'jQuery'
|
||||
|
||||
ActionView::Helpers::AssetTagHelper::JAVASCRIPT_DEFAULT_SOURCES = ['jrails']
|
||||
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
|
||||
require 'jrails'
|
||||
require 'rails/init.rb'
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,128 +1 @@
|
|||
(function($){$().ajaxSend(function(a,xhr,s){xhr.setRequestHeader("Accept","text/javascript, text/html, application/xml, text/xml, */*")})})(jQuery);(function($){$.fn.reset=function(){return this.each(function(){if(typeof this.reset=="function"||(typeof this.reset=="object"&&!this.reset.nodeType)){this.reset()}})};$.fn.enable=function(){return this.each(function(){this.disabled=false})};$.fn.disable=function(){return this.each(function(){this.disabled=true})}})(jQuery);(function($){$.extend({fieldEvent:function(el,obs){var field=el[0]||el,e="change";if(field.type=="radio"||field.type=="checkbox"){e="click"}else{if(obs&&field.type=="text"||field.type=="textarea"){e="keyup"}}return e}});$.fn.extend({delayedObserver:function(delay,callback){var el=$(this);if(typeof window.delayedObserverStack=="undefined"){window.delayedObserverStack=[]}if(typeof window.delayedObserverCallback=="undefined"){window.delayedObserverCallback=function(stackPos){observed=window.delayedObserverStack[stackPos];if(observed.timer){clearTimeout(observed.timer)}observed.timer=setTimeout(function(){observed.timer=null;observed.callback(observed.obj,observed.obj.formVal())},observed.delay*1000);observed.oldVal=observed.obj.formVal()}}window.delayedObserverStack.push({obj:el,timer:null,delay:delay,oldVal:el.formVal(),callback:callback});var stackPos=window.delayedObserverStack.length-1;if(el[0].tagName=="FORM"){$(":input",el).each(function(){var field=$(this);field.bind($.fieldEvent(field,delay),function(){observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.obj.oldVal){return}else{window.delayedObserverCallback(stackPos)}})})}else{el.bind($.fieldEvent(el,delay),function(){observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.obj.oldVal){return}else{window.delayedObserverCallback(stackPos)}})}},formVal:function(){var el=this[0];if(el.tagName=="FORM"){return this.serialize()}if(el.type=="checkbox"||self.type=="radio"){return this.filter("input:checked").val()||""}else{return this.val()}}})})(jQuery);(function($){$.fn.extend({visualEffect:function(o){e=o.replace(/\_(.)/g,function(m,l){return l.toUpperCase()});return eval("$(this)."+e+"()")},appear:function(speed,callback){return this.fadeIn(speed,callback)},blindDown:function(speed,callback){return this.show("blind",{direction:"vertical"},speed,callback)},blindUp:function(speed,callback){return this.hide("blind",{direction:"vertical"},speed,callback)},blindRight:function(speed,callback){return this.show("blind",{direction:"horizontal"},speed,callback)},blindLeft:function(speed,callback){this.hide("blind",{direction:"horizontal"},speed,callback);return this},dropOut:function(speed,callback){return this.hide("drop",{direction:"down"},speed,callback)},dropIn:function(speed,callback){return this.show("drop",{direction:"up"},speed,callback)},fade:function(speed,callback){return this.fadeOut(speed,callback)},fadeToggle:function(speed,callback){return this.animate({opacity:"toggle"},speed,callback)},fold:function(speed,callback){return this.hide("fold",{},speed,callback)},foldOut:function(speed,callback){return this.show("fold",{},speed,callback)},grow:function(speed,callback){return this.show("scale",{},speed,callback)},highlight:function(speed,callback){return this.show("highlight",{},speed,callback)},puff:function(speed,callback){return this.hide("puff",{},speed,callback)},pulsate:function(speed,callback){return this.show("pulsate",{},speed,callback)},shake:function(speed,callback){return this.show("shake",{},speed,callback)},shrink:function(speed,callback){return this.hide("scale",{},speed,callback)},squish:function(speed,callback){return this.hide("scale",{origin:["top","left"]},speed,callback)},slideUp:function(speed,callback){return this.hide("slide",{direction:"up"},speed,callback)},slideDown:function(speed,callback){return this.show("slide",{direction:"up"},speed,callback)},switchOff:function(speed,callback){return this.hide("clip",{},speed,callback)},switchOn:function(speed,callback){return this.show("clip",{},speed,callback)}})})(jQuery);
|
||||
|
||||
jQuery(function ($) {
|
||||
var csrf_token = $('meta[name=csrf-token]').attr('content'),
|
||||
csrf_param = $('meta[name=csrf-param]').attr('content');
|
||||
|
||||
$.fn.extend({
|
||||
/**
|
||||
* Triggers a custom event on an element and returns the event result
|
||||
* this is used to get around not being able to ensure callbacks are placed
|
||||
* at the end of the chain.
|
||||
*
|
||||
* TODO: deprecate with jQuery 1.4.2 release, in favor of subscribing to our
|
||||
* own events and placing ourselves at the end of the chain.
|
||||
*/
|
||||
triggerAndReturn: function (name, data) {
|
||||
var event = new $.Event(name);
|
||||
this.trigger(event, data);
|
||||
|
||||
return event.result !== false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles execution of remote calls firing overridable events along the way
|
||||
*/
|
||||
callRemote: function () {
|
||||
var el = this,
|
||||
data = el.is('form') ? el.serializeArray() : [],
|
||||
method = el.attr('method') || el.attr('data-method') || 'GET',
|
||||
url = el.attr('action') || el.attr('href');
|
||||
|
||||
if (url === undefined) {
|
||||
throw "No URL specified for remote call (action or href must be present).";
|
||||
} else {
|
||||
if (el.triggerAndReturn('ajax:before')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: data,
|
||||
dataType: 'script',
|
||||
type: method.toUpperCase(),
|
||||
beforeSend: function (xhr) {
|
||||
el.trigger('ajax:loading', xhr);
|
||||
},
|
||||
success: function (data, status, xhr) {
|
||||
el.trigger('ajax:success', [data, status, xhr]);
|
||||
},
|
||||
complete: function (xhr) {
|
||||
el.trigger('ajax:complete', xhr);
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
el.trigger('ajax:failure', [xhr, status, error]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
el.trigger('ajax:after');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* confirmation handler
|
||||
*/
|
||||
$('a[data-confirm],input[data-confirm]').live('click', function () {
|
||||
var el = $(this);
|
||||
if (el.triggerAndReturn('confirm')) {
|
||||
if (!confirm(el.attr('data-confirm'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* remote handlers
|
||||
*/
|
||||
$('form[data-remote]').live('submit', function (e) {
|
||||
$(this).callRemote();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('a[data-remote],input[data-remote]').live('click', function (e) {
|
||||
$(this).callRemote();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('a[data-method]:not([data-remote])').live('click', function (e){
|
||||
var link = $(this),
|
||||
href = link.attr('href'),
|
||||
method = link.attr('data-method'),
|
||||
form = $('<form method="post" action="'+href+'">'),
|
||||
metadata_input = '<input name="_method" value="'+method+'" type="hidden" />';
|
||||
|
||||
if (csrf_param != null && csrf_token != null) {
|
||||
metadata_input += '<input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" />';
|
||||
}
|
||||
|
||||
form.hide()
|
||||
.append(metadata_input)
|
||||
.appendTo('body');
|
||||
|
||||
e.preventDefault();
|
||||
form.submit();
|
||||
});
|
||||
|
||||
/**
|
||||
* disable-with handlers
|
||||
*/
|
||||
var disable_with_input_selector = 'input[data-disable-with]';
|
||||
var disable_with_form_selector = 'form[data-remote]:has(' + disable_with_input_selector + ')';
|
||||
|
||||
$(disable_with_form_selector).live('ajax:before', function () {
|
||||
$(this).find(disable_with_input_selector).each(function () {
|
||||
var input = $(this);
|
||||
input.data('enable-with', input.val())
|
||||
.attr('value', input.attr('data-disable-with'))
|
||||
.attr('disabled', 'disabled');
|
||||
});
|
||||
});
|
||||
|
||||
$(disable_with_form_selector).live('ajax:after', function () {
|
||||
$(this).find(disable_with_input_selector).each(function () {
|
||||
var input = $(this);
|
||||
input.removeAttr('disabled')
|
||||
.val(input.data('enable-with'));
|
||||
});
|
||||
});
|
||||
});
|
||||
(function($){$.ajaxSettings.accepts._default="text/javascript, text/html, application/xml, text/xml, */*"})(jQuery);(function($){$.fn.reset=function(){return this.each(function(){if(typeof this.reset=="function"||(typeof this.reset=="object"&&!this.reset.nodeType)){this.reset()}})};$.fn.enable=function(){return this.each(function(){this.disabled=false})};$.fn.disable=function(){return this.each(function(){this.disabled=true})}})(jQuery);(function($){$.extend({fieldEvent:function(el,obs){var field=el[0]||el,e="change";if(field.type=="radio"||field.type=="checkbox"){e="click"}else{if(obs&&(field.type=="text"||field.type=="textarea"||field.type=="password")){e="keyup"}}return e}});$.fn.extend({delayedObserver:function(delay,callback){var el=$(this);if(typeof window.delayedObserverStack=="undefined"){window.delayedObserverStack=[]}if(typeof window.delayedObserverCallback=="undefined"){window.delayedObserverCallback=function(stackPos){var observed=window.delayedObserverStack[stackPos];if(observed.timer){clearTimeout(observed.timer)}observed.timer=setTimeout(function(){observed.timer=null;observed.callback(observed.obj,observed.obj.formVal())},observed.delay*1000);observed.oldVal=observed.obj.formVal()}}window.delayedObserverStack.push({obj:el,timer:null,delay:delay,oldVal:el.formVal(),callback:callback});var stackPos=window.delayedObserverStack.length-1;if(el[0].tagName=="FORM"){$(":input",el).each(function(){var field=$(this);field.bind($.fieldEvent(field,delay),function(){var observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.oldVal){return}else{window.delayedObserverCallback(stackPos)}})})}else{el.bind($.fieldEvent(el,delay),function(){var observed=window.delayedObserverStack[stackPos];if(observed.obj.formVal()==observed.oldVal){return}else{window.delayedObserverCallback(stackPos)}})}},formVal:function(){var el=this[0];if(el.tagName=="FORM"){return this.serialize()}if(el.type=="checkbox"||el.type=="radio"){return this.filter("input:checked").val()||""}else{return this.val()}}})})(jQuery);(function($){$.fn.extend({visualEffect:function(o,options){if(options){speed=options.duration*1000}else{speed=null}e=o.replace(/\_(.)/g,function(m,l){return l.toUpperCase()});return eval("$(this)."+e+"("+speed+")")},appear:function(speed,callback){return this.fadeIn(speed,callback)},blindDown:function(speed,callback){return this.show("blind",{direction:"vertical"},speed,callback)},blindUp:function(speed,callback){return this.hide("blind",{direction:"vertical"},speed,callback)},blindRight:function(speed,callback){return this.show("blind",{direction:"horizontal"},speed,callback)},blindLeft:function(speed,callback){this.hide("blind",{direction:"horizontal"},speed,callback);return this},dropOut:function(speed,callback){return this.hide("drop",{direction:"down"},speed,callback)},dropIn:function(speed,callback){return this.show("drop",{direction:"up"},speed,callback)},fade:function(speed,callback){return this.fadeOut(speed,callback)},fadeToggle:function(speed,callback){return this.animate({opacity:"toggle"},speed,callback)},fold:function(speed,callback){return this.hide("fold",{},speed,callback)},foldOut:function(speed,callback){return this.show("fold",{},speed,callback)},grow:function(speed,callback){return this.show("scale",{},speed,callback)},highlight:function(speed,callback){return this.show("highlight",{},speed,callback)},puff:function(speed,callback){return this.hide("puff",{},speed,callback)},pulsate:function(speed,callback){return this.show("pulsate",{},speed,callback)},shake:function(speed,callback){return this.show("shake",{},speed,callback)},shrink:function(speed,callback){return this.hide("scale",{},speed,callback)},squish:function(speed,callback){return this.hide("scale",{origin:["top","left"]},speed,callback)},slideUp:function(speed,callback){return this.hide("slide",{direction:"up"},speed,callback)},slideDown:function(speed,callback){return this.show("slide",{direction:"up"},speed,callback)},switchOff:function(speed,callback){return this.hide("clip",{},speed,callback)},switchOn:function(speed,callback){return this.show("clip",{},speed,callback)}})})(jQuery);
|
|
@ -7,9 +7,7 @@
|
|||
*/
|
||||
|
||||
(function($) {
|
||||
$().ajaxSend(function(a, xhr, s){ //Set request headers globally
|
||||
xhr.setRequestHeader("Accept", "text/javascript, text/html, application/xml, text/xml, */*");
|
||||
});
|
||||
$.ajaxSettings.accepts._default = "text/javascript, text/html, application/xml, text/xml, */*";
|
||||
})(jQuery);
|
||||
|
||||
|
||||
|
@ -59,7 +57,7 @@
|
|||
fieldEvent: function(el, obs) {
|
||||
var field = el[0] || el, e = 'change';
|
||||
if (field.type == 'radio' || field.type == 'checkbox') e = 'click';
|
||||
else if (obs && field.type == 'text' || field.type == 'textarea') e = 'keyup';
|
||||
else if (obs && (field.type == 'text' || field.type == 'textarea' || field.type == 'password')) e = 'keyup';
|
||||
return e;
|
||||
}
|
||||
});
|
||||
|
@ -119,9 +117,14 @@
|
|||
|
||||
(function($) {
|
||||
$.fn.extend({
|
||||
visualEffect : function(o) {
|
||||
visualEffect : function(o, options) {
|
||||
if (options) {
|
||||
speed = options.duration * 1000;
|
||||
} else {
|
||||
speed = null;
|
||||
}
|
||||
e = o.replace(/\_(.)/g, function(m, l){return l.toUpperCase()});
|
||||
return eval('$(this).'+e+'()');
|
||||
return eval('$(this).'+e+'('+ speed + ')');
|
||||
},
|
||||
appear : function(speed, callback) {
|
||||
return this.fadeIn(speed, callback);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{jrails}
|
||||
s.version = "0.6.0"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Aaron Eisenberger", "Patrick Hurley"]
|
||||
s.date = %q{2009-10-20}
|
||||
s.default_executable = %q{jrails}
|
||||
s.description = %q{Using jRails, you can get all of the same default Rails helpers for javascript functionality using the lighter jQuery library.}
|
||||
s.email = %q{aaronchi@gmail.com}
|
||||
s.executables = ["jrails"]
|
||||
s.extra_rdoc_files = [
|
||||
"CHANGELOG",
|
||||
"LICENSE",
|
||||
"README.rdoc"
|
||||
]
|
||||
s.files = [
|
||||
"bin/jrails",
|
||||
"init.rb",
|
||||
"install.rb",
|
||||
"javascripts/jquery-ui.js",
|
||||
"javascripts/jquery.js",
|
||||
"javascripts/jrails.js",
|
||||
"javascripts/sources/jrails.js",
|
||||
"lib/jquery_selector_assertions.rb",
|
||||
"lib/jrails.rb",
|
||||
"rails/init.rb",
|
||||
"tasks/jrails.rake"
|
||||
]
|
||||
s.homepage = %q{http://ennerchi.com/projects/jrails}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubyforge_project = %q{jrails}
|
||||
s.rubygems_version = %q{1.3.5}
|
||||
s.summary = %q{jRails is a drop-in jQuery replacement for the Rails Prototype/script.aculo.us helpers.}
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||
else
|
||||
end
|
||||
else
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
#
|
||||
# jQuery Selector Assertions (modifications to the prototype/scriptaculous assertions)
|
||||
#
|
||||
# From http://pastie.org/303776
|
||||
#
|
||||
# 1. Make sure to use '#' prefix when referring to element IDs in assert_select_rjs(),
|
||||
# like this:
|
||||
# assert_select_rjs :replace_html, '#someid'
|
||||
# instead of prototype convention:
|
||||
# assert_select_rjs :replace_html, 'someid'
|
||||
#
|
||||
# We monkey-patch some RJS-matching constants for assert_select_rjs to work
|
||||
# with jQuery-based code as opposed to Prototype's:
|
||||
#
|
||||
module ActionController
|
||||
module Assertions
|
||||
module SelectorAssertions
|
||||
silence_warnings do
|
||||
RJS_PATTERN_HTML = "\"((\\\\\"|[^\"])*)\""
|
||||
# RJS_ANY_ID = "\"([^\"])*\""
|
||||
# better match with single or double quoted ids
|
||||
RJS_ANY_ID = "[\"']([^\"])*[\"']"
|
||||
|
||||
RJS_STATEMENTS = {
|
||||
:chained_replace => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.replaceWith\\(#{RJS_PATTERN_HTML}\\)",
|
||||
:chained_replace_html => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.updateWith\\(#{RJS_PATTERN_HTML}\\)",
|
||||
:replace_html => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.html\\(#{RJS_PATTERN_HTML}\\)",
|
||||
:replace => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.replaceWith\\(#{RJS_PATTERN_HTML}\\)",
|
||||
:insert_top => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.prepend\\(#{RJS_PATTERN_HTML}\\)",
|
||||
:insert_bottom => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.append\\(#{RJS_PATTERN_HTML}\\)",
|
||||
:effect => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.effect\\(",
|
||||
:highlight => "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.effect\\('highlight'"
|
||||
|
||||
=begin TODO:
|
||||
|
||||
I've never used the chained_* so I don't know if they work.
|
||||
|
||||
I couldn't seem to get assert_select_rjs to actually match the single quoted ids
|
||||
which are created by some of the effects like ...
|
||||
... jQuery('#item_1559').effect('highlight',{},1000);
|
||||
so I modified jrails/lib/jrails.rb line 337
|
||||
... javascript = "#{JQUERY_VAR}('#{jquery_id(element_id)}').#{mode || 'effect'}('#{name}'"
|
||||
to
|
||||
... javascript = "#{JQUERY_VAR}(\"#{jquery_id(element_id)}\").#{mode || 'effect'}('#{name}'"
|
||||
so it writes double quotes like most of the others. This change should probably be
|
||||
done to the others, but as I don't use them so haven't tested them.
|
||||
|
||||
My other option seemed to require modifying rails' selector_assertions.rb line 427
|
||||
... id ? statement.gsub(RJS_ANY_ID, "\"#{id}\"") : statement
|
||||
which forces the expectation that the id is double quoted. If I changed it to
|
||||
... statement.gsub(RJS_ANY_ID, "[\"']{1}#{id}[\"']{1}")
|
||||
I believe that it would work as the logic seemed to work in some testing.
|
||||
I have not actually tried to modify rails, as this file doesn't seem to
|
||||
actually be in the git repository.
|
||||
|
||||
|
||||
jrails now uses a nonconflict option so $ is jQuery. I put both in the pattern in case it gets changed.
|
||||
|
||||
:insert_after => "",
|
||||
:insert_before => "",
|
||||
=end
|
||||
|
||||
}
|
||||
|
||||
[:remove, :show, :hide, :toggle, :reset ].each do |action|
|
||||
RJS_STATEMENTS[action] = "\(jQuery|$\)\\(#{RJS_ANY_ID}\\)\\.#{action}\\(\\)"
|
||||
end
|
||||
|
||||
# TODO:
|
||||
#RJS_STATEMENTS[:insert_html] = "Element.insert\\(#{RJS_ANY_ID}, \\{ (#{RJS_INSERTIONS.join('|')}):
|
||||
#{RJS_PATTERN_HTML} \\}\\)"
|
||||
|
||||
RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})")
|
||||
RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,406 +1,427 @@
|
|||
module ActionView
|
||||
module Helpers
|
||||
|
||||
module JavaScriptHelper
|
||||
|
||||
# This function can be used to render rjs inline
|
||||
#
|
||||
# <%= javascript_function do |page|
|
||||
# page.replace_html :list, :partial => 'list', :object => @list
|
||||
# end %>
|
||||
#
|
||||
def javascript_function(*args, &block)
|
||||
html_options = args.extract_options!
|
||||
function = args[0] || ''
|
||||
module Helpers
|
||||
|
||||
module JavaScriptHelper
|
||||
|
||||
# This function can be used to render rjs inline
|
||||
#
|
||||
# <%= javascript_function do |page|
|
||||
# page.replace_html :list, :partial => 'list', :object => @list
|
||||
# end %>
|
||||
#
|
||||
def javascript_function(*args, &block)
|
||||
html_options = args.extract_options!
|
||||
function = args[0] || ''
|
||||
|
||||
html_options.symbolize_keys!
|
||||
function = update_page(&block) if block_given?
|
||||
javascript_tag(function)
|
||||
end
|
||||
|
||||
def jquery_id(id)
|
||||
id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
|
||||
end
|
||||
|
||||
def jquery_ids(ids)
|
||||
Array(ids).map{|id| jquery_id(id)}.join(',')
|
||||
end
|
||||
html_options.symbolize_keys!
|
||||
function = update_page(&block) if block_given?
|
||||
javascript_tag(function)
|
||||
end
|
||||
|
||||
def jquery_id(id)
|
||||
id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
|
||||
end
|
||||
|
||||
def jquery_ids(ids)
|
||||
Array(ids).map{|id| jquery_id(id)}.join(',')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module PrototypeHelper
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = '$'
|
||||
end
|
||||
|
||||
unless const_defined? :JQCALLBACKS
|
||||
JQCALLBACKS = Set.new([ :beforeSend, :complete, :error, :success ] + (100..599).to_a)
|
||||
AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
|
||||
:asynchronous, :method, :insertion, :position,
|
||||
:form, :with, :update, :script ]).merge(JQCALLBACKS)
|
||||
end
|
||||
|
||||
def periodically_call_remote(options = {})
|
||||
frequency = options[:frequency] || 10 # every ten seconds by default
|
||||
code = "setInterval(function() {#{remote_function(options)}}, #{frequency} * 1000)"
|
||||
javascript_tag(code)
|
||||
end
|
||||
|
||||
def remote_function(options)
|
||||
javascript_options = options_for_ajax(options)
|
||||
end
|
||||
|
||||
module PrototypeHelper
|
||||
|
||||
USE_PROTECTION = const_defined?(:DISABLE_JQUERY_FORGERY_PROTECTION) ? !DISABLE_JQUERY_FORGERY_PROTECTION : true
|
||||
|
||||
update = ''
|
||||
if options[:update] && options[:update].is_a?(Hash)
|
||||
update = []
|
||||
update << "success:'#{options[:update][:success]}'" if options[:update][:success]
|
||||
update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure]
|
||||
update = '{' + update.join(',') + '}'
|
||||
elsif options[:update]
|
||||
update << "'#{options[:update]}'"
|
||||
end
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = 'jQuery'
|
||||
end
|
||||
|
||||
unless const_defined? :JQCALLBACKS
|
||||
JQCALLBACKS = Set.new([ :beforeSend, :complete, :error, :success ] + (100..599).to_a)
|
||||
#instance_eval { remove_const :AJAX_OPTIONS }
|
||||
remove_const(:AJAX_OPTIONS) if const_defined?(:AJAX_OPTIONS)
|
||||
AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
|
||||
:asynchronous, :method, :insertion, :position,
|
||||
:form, :with, :update, :script ]).merge(JQCALLBACKS)
|
||||
end
|
||||
|
||||
def periodically_call_remote(options = {})
|
||||
frequency = options[:frequency] || 10 # every ten seconds by default
|
||||
code = "setInterval(function() {#{remote_function(options)}}, #{frequency} * 1000)"
|
||||
javascript_tag(code)
|
||||
end
|
||||
|
||||
def remote_function(options)
|
||||
javascript_options = options_for_ajax(options)
|
||||
|
||||
function = "#{JQUERY_VAR}.ajax(#{javascript_options})"
|
||||
update = ''
|
||||
if options[:update] && options[:update].is_a?(Hash)
|
||||
update = []
|
||||
update << "success:'#{options[:update][:success]}'" if options[:update][:success]
|
||||
update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure]
|
||||
update = '{' + update.join(',') + '}'
|
||||
elsif options[:update]
|
||||
update << "'#{options[:update]}'"
|
||||
end
|
||||
|
||||
function = "#{options[:before]}; #{function}" if options[:before]
|
||||
function = "#{function}; #{options[:after]}" if options[:after]
|
||||
function = "if (#{options[:condition]}) { #{function}; }" if options[:condition]
|
||||
function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm]
|
||||
return function
|
||||
end
|
||||
|
||||
class JavaScriptGenerator
|
||||
module GeneratorMethods
|
||||
|
||||
def insert_html(position, id, *options_for_render)
|
||||
insertion = position.to_s.downcase
|
||||
insertion = 'append' if insertion == 'bottom'
|
||||
insertion = 'prepend' if insertion == 'top'
|
||||
call "#{JQUERY_VAR}(\"#{jquery_id(id)}\").#{insertion}", render(*options_for_render)
|
||||
end
|
||||
|
||||
def replace_html(id, *options_for_render)
|
||||
insert_html(:html, id, *options_for_render)
|
||||
end
|
||||
|
||||
def replace(id, *options_for_render)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_id(id)}\").replaceWith", render(*options_for_render)
|
||||
end
|
||||
|
||||
def remove(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").remove"
|
||||
end
|
||||
|
||||
def show(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").show"
|
||||
end
|
||||
|
||||
def hide(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").hide"
|
||||
end
|
||||
function = "#{JQUERY_VAR}.ajax(#{javascript_options})"
|
||||
|
||||
def toggle(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").toggle"
|
||||
end
|
||||
|
||||
def jquery_id(id)
|
||||
id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
|
||||
end
|
||||
|
||||
def jquery_ids(ids)
|
||||
Array(ids).map{|id| jquery_id(id)}.join(',')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def options_for_ajax(options)
|
||||
js_options = build_callbacks(options)
|
||||
|
||||
url_options = options[:url]
|
||||
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
|
||||
js_options['url'] = "'#{url_for(url_options)}'"
|
||||
js_options['async'] = false if options[:type] == :synchronous
|
||||
js_options['type'] = options[:method] ? method_option_to_s(options[:method]) : ( options[:form] ? "'post'" : nil )
|
||||
js_options['dataType'] = options[:datatype] ? "'#{options[:datatype]}'" : (options[:update] ? nil : "'script'")
|
||||
|
||||
if options[:form]
|
||||
js_options['data'] = "#{JQUERY_VAR}.param(#{JQUERY_VAR}(this).serializeArray())"
|
||||
elsif options[:submit]
|
||||
js_options['data'] = "#{JQUERY_VAR}(\"##{options[:submit]} :input\").serialize()"
|
||||
elsif options[:with]
|
||||
js_options['data'] = options[:with].gsub("Form.serialize(this.form)","#{JQUERY_VAR}.param(#{JQUERY_VAR}(this.form).serializeArray())")
|
||||
end
|
||||
|
||||
js_options['type'] ||= "'post'"
|
||||
if options[:method]
|
||||
if method_option_to_s(options[:method]) == "'put'" || method_option_to_s(options[:method]) == "'delete'"
|
||||
js_options['type'] = "'post'"
|
||||
if js_options['data']
|
||||
js_options['data'] << " + '&"
|
||||
else
|
||||
js_options['data'] = "'"
|
||||
end
|
||||
js_options['data'] << "_method=#{options[:method]}'"
|
||||
end
|
||||
end
|
||||
|
||||
if respond_to?('protect_against_forgery?') && protect_against_forgery?
|
||||
if js_options['data']
|
||||
js_options['data'] << " + '&"
|
||||
else
|
||||
js_options['data'] = "'"
|
||||
end
|
||||
js_options['data'] << "#{request_forgery_protection_token}=' + encodeURIComponent('#{escape_javascript form_authenticity_token}')"
|
||||
end
|
||||
js_options['data'] = "''" if js_options['type'] == "'post'" && js_options['data'].nil?
|
||||
options_for_javascript(js_options.reject {|key, value| value.nil?})
|
||||
end
|
||||
|
||||
def build_update_for_success(html_id, insertion=nil)
|
||||
insertion = build_insertion(insertion)
|
||||
"#{JQUERY_VAR}('#{jquery_id(html_id)}').#{insertion}(request);"
|
||||
end
|
||||
function = "#{options[:before]}; #{function}" if options[:before]
|
||||
function = "#{function}; #{options[:after]}" if options[:after]
|
||||
function = "if (#{options[:condition]}) { #{function}; }" if options[:condition]
|
||||
function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm]
|
||||
return function
|
||||
end
|
||||
|
||||
class JavaScriptGenerator
|
||||
module GeneratorMethods
|
||||
|
||||
def insert_html(position, id, *options_for_render)
|
||||
insertion = position.to_s.downcase
|
||||
insertion = 'append' if insertion == 'bottom'
|
||||
insertion = 'prepend' if insertion == 'top'
|
||||
call "#{JQUERY_VAR}(\"#{jquery_id(id)}\").#{insertion}", render(*options_for_render)
|
||||
end
|
||||
|
||||
def replace_html(id, *options_for_render)
|
||||
insert_html(:html, id, *options_for_render)
|
||||
end
|
||||
|
||||
def replace(id, *options_for_render)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_id(id)}\").replaceWith", render(*options_for_render)
|
||||
end
|
||||
|
||||
def remove(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").remove"
|
||||
end
|
||||
|
||||
def show(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").show"
|
||||
end
|
||||
|
||||
def hide(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").hide"
|
||||
end
|
||||
|
||||
def build_update_for_error(html_id, insertion=nil)
|
||||
insertion = build_insertion(insertion)
|
||||
"#{JQUERY_VAR}('#{jquery_id(html_id)}').#{insertion}(request.responseText);"
|
||||
end
|
||||
def toggle(*ids)
|
||||
call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").toggle"
|
||||
end
|
||||
|
||||
def jquery_id(id)
|
||||
id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
|
||||
end
|
||||
|
||||
def jquery_ids(ids)
|
||||
Array(ids).map{|id| jquery_id(id)}.join(',')
|
||||
end
|
||||
|
||||
def prepend(id, *option_for_render)
|
||||
insert_html(:prepend, id, *options_for_render)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def options_for_ajax(options)
|
||||
js_options = build_callbacks(options)
|
||||
|
||||
url_options = options[:url]
|
||||
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
|
||||
js_options['url'] = "'#{url_for(url_options)}'"
|
||||
js_options['async'] = false if options[:type] == :synchronous
|
||||
js_options['type'] = options[:method] ? method_option_to_s(options[:method]) : ( options[:form] ? "'post'" : nil )
|
||||
js_options['dataType'] = options[:datatype] ? "'#{options[:datatype]}'" : (options[:update] ? nil : "'script'")
|
||||
|
||||
if options[:form]
|
||||
js_options['data'] = "#{JQUERY_VAR}.param(#{JQUERY_VAR}(this).serializeArray())"
|
||||
elsif options[:submit]
|
||||
js_options['data'] = "#{JQUERY_VAR}(\"##{options[:submit]} :input\").serialize()"
|
||||
elsif options[:with]
|
||||
js_options['data'] = options[:with].gsub("Form.serialize(this.form)","#{JQUERY_VAR}.param(#{JQUERY_VAR}(this.form).serializeArray())")
|
||||
end
|
||||
|
||||
js_options['type'] ||= "'post'"
|
||||
if options[:method]
|
||||
if method_option_to_s(options[:method]) == "'put'" || method_option_to_s(options[:method]) == "'delete'"
|
||||
js_options['type'] = "'post'"
|
||||
if js_options['data']
|
||||
js_options['data'] << " + '&"
|
||||
else
|
||||
js_options['data'] = "'"
|
||||
end
|
||||
js_options['data'] << "_method=#{options[:method]}'"
|
||||
end
|
||||
end
|
||||
|
||||
if USE_PROTECTION && respond_to?('protect_against_forgery?') && protect_against_forgery?
|
||||
if js_options['data']
|
||||
js_options['data'] << " + '&"
|
||||
else
|
||||
js_options['data'] = "'"
|
||||
end
|
||||
js_options['data'] << "#{request_forgery_protection_token}=' + encodeURIComponent('#{escape_javascript form_authenticity_token}')"
|
||||
end
|
||||
js_options['data'] = "''" if js_options['type'] == "'post'" && js_options['data'].nil?
|
||||
options_for_javascript(js_options.reject {|key, value| value.nil?})
|
||||
end
|
||||
|
||||
def build_update_for_success(html_id, insertion=nil)
|
||||
insertion = build_insertion(insertion)
|
||||
"#{JQUERY_VAR}('#{jquery_id(html_id)}').#{insertion}(request);"
|
||||
end
|
||||
|
||||
def build_insertion(insertion)
|
||||
insertion = insertion ? insertion.to_s.downcase : 'html'
|
||||
insertion = 'append' if insertion == 'bottom'
|
||||
insertion = 'prepend' if insertion == 'top'
|
||||
insertion
|
||||
end
|
||||
def build_update_for_error(html_id, insertion=nil)
|
||||
insertion = build_insertion(insertion)
|
||||
"#{JQUERY_VAR}('#{jquery_id(html_id)}').#{insertion}(request.responseText);"
|
||||
end
|
||||
|
||||
def build_observer(klass, name, options = {})
|
||||
if options[:with] && (options[:with] !~ /[\{=(.]/)
|
||||
options[:with] = "'#{options[:with]}=' + value"
|
||||
else
|
||||
options[:with] ||= 'value' unless options[:function]
|
||||
end
|
||||
def build_insertion(insertion)
|
||||
insertion = insertion ? insertion.to_s.downcase : 'html'
|
||||
insertion = 'append' if insertion == 'bottom'
|
||||
insertion = 'prepend' if insertion == 'top'
|
||||
insertion
|
||||
end
|
||||
|
||||
callback = options[:function] || remote_function(options)
|
||||
javascript = "#{JQUERY_VAR}('#{jquery_id(name)}').delayedObserver("
|
||||
javascript << "#{options[:frequency] || 0}, "
|
||||
javascript << "function(element, value) {"
|
||||
javascript << "#{callback}}"
|
||||
#javascript << ", '#{options[:on]}'" if options[:on]
|
||||
javascript << ")"
|
||||
javascript_tag(javascript)
|
||||
end
|
||||
|
||||
def build_callbacks(options)
|
||||
callbacks = {}
|
||||
options[:beforeSend] = '';
|
||||
[:uninitialized,:loading,:loaded].each do |key|
|
||||
options[:beforeSend] << (options[key].last == ';' ? options.delete(key) : options.delete(key) << ';') if options[key]
|
||||
end
|
||||
options.delete(:beforeSend) if options[:beforeSend].blank?
|
||||
options[:error] = options.delete(:failure) if options[:failure]
|
||||
if options[:update]
|
||||
if options[:update].is_a?(Hash)
|
||||
options[:update][:error] = options[:update].delete(:failure) if options[:update][:failure]
|
||||
if options[:update][:success]
|
||||
options[:success] = build_update_for_success(options[:update][:success], options[:position]) << (options[:success] ? options[:success] : '')
|
||||
end
|
||||
if options[:update][:error]
|
||||
options[:error] = build_update_for_error(options[:update][:error], options[:position]) << (options[:error] ? options[:error] : '')
|
||||
end
|
||||
else
|
||||
options[:success] = build_update_for_success(options[:update], options[:position]) << (options[:success] ? options[:success] : '')
|
||||
end
|
||||
end
|
||||
options.each do |callback, code|
|
||||
if JQCALLBACKS.include?(callback)
|
||||
callbacks[callback] = "function(request){#{code}}"
|
||||
end
|
||||
end
|
||||
callbacks
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class JavaScriptElementProxy < JavaScriptProxy #:nodoc:
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = ActionView::Helpers::PrototypeHelper::JQUERY_VAR
|
||||
end
|
||||
|
||||
def initialize(generator, id)
|
||||
id = id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
|
||||
@id = id
|
||||
super(generator, "#{JQUERY_VAR}(\"#{id}\")")
|
||||
end
|
||||
|
||||
def replace_html(*options_for_render)
|
||||
call 'html', @generator.send(:render, *options_for_render)
|
||||
end
|
||||
def build_observer(klass, name, options = {})
|
||||
if options[:with] && (options[:with] !~ /[\{=(.]/)
|
||||
options[:with] = "'#{options[:with]}=' + value"
|
||||
else
|
||||
options[:with] ||= 'value' unless options[:function]
|
||||
end
|
||||
|
||||
def replace(*options_for_render)
|
||||
call 'replaceWith', @generator.send(:render, *options_for_render)
|
||||
end
|
||||
|
||||
def value()
|
||||
call 'val()'
|
||||
end
|
||||
callback = options[:function] || remote_function(options)
|
||||
javascript = "#{JQUERY_VAR}('#{jquery_id(name)}').delayedObserver("
|
||||
javascript << "#{options[:frequency] || 0}, "
|
||||
javascript << "function(element, value) {"
|
||||
javascript << "#{callback}}"
|
||||
#javascript << ", '#{options[:on]}'" if options[:on]
|
||||
javascript << ")"
|
||||
javascript_tag(javascript)
|
||||
end
|
||||
|
||||
def build_callbacks(options)
|
||||
callbacks = {}
|
||||
options[:beforeSend] = '';
|
||||
[:uninitialized,:loading].each do |key|
|
||||
options[:beforeSend] << (options[key].last == ';' ? options.delete(key) : options.delete(key) << ';') if options[key]
|
||||
end
|
||||
options.delete(:beforeSend) if options[:beforeSend].blank?
|
||||
options[:complete] = options.delete(:loaded) if options[:loaded]
|
||||
options[:error] = options.delete(:failure) if options[:failure]
|
||||
if options[:update]
|
||||
if options[:update].is_a?(Hash)
|
||||
options[:update][:error] = options[:update].delete(:failure) if options[:update][:failure]
|
||||
if options[:update][:success]
|
||||
options[:success] = build_update_for_success(options[:update][:success], options[:position]) << (options[:success] ? options[:success] : '')
|
||||
end
|
||||
if options[:update][:error]
|
||||
options[:error] = build_update_for_error(options[:update][:error], options[:position]) << (options[:error] ? options[:error] : '')
|
||||
end
|
||||
else
|
||||
options[:success] = build_update_for_success(options[:update], options[:position]) << (options[:success] ? options[:success] : '')
|
||||
end
|
||||
end
|
||||
options.each do |callback, code|
|
||||
if JQCALLBACKS.include?(callback)
|
||||
callbacks[callback] = "function(request){#{code}}"
|
||||
end
|
||||
end
|
||||
callbacks
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class JavaScriptElementProxy < JavaScriptProxy #:nodoc:
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = PrototypeHelper::JQUERY_VAR
|
||||
end
|
||||
|
||||
def initialize(generator, id)
|
||||
id = id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
|
||||
@id = id
|
||||
super(generator, "#{JQUERY_VAR}(\"#{id}\")")
|
||||
end
|
||||
|
||||
def replace_html(*options_for_render)
|
||||
call 'html', @generator.send(:render, *options_for_render)
|
||||
end
|
||||
|
||||
def value=(value)
|
||||
call 'val', value
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = ActionView::Helpers::PrototypeHelper::JQUERY_VAR
|
||||
end
|
||||
|
||||
def initialize(generator, pattern)
|
||||
super(generator, "#{JQUERY_VAR}(#{pattern.to_json})")
|
||||
end
|
||||
end
|
||||
|
||||
module ScriptaculousHelper
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = ActionView::Helpers::PrototypeHelper::JQUERY_VAR
|
||||
end
|
||||
|
||||
unless const_defined? :SCRIPTACULOUS_EFFECTS
|
||||
SCRIPTACULOUS_EFFECTS = {
|
||||
:appear => {:method => 'fadeIn'},
|
||||
:blind_down => {:method => 'blind', :mode => 'show', :options => {:direction => 'vertical'}},
|
||||
:blind_up => {:method => 'blind', :mode => 'hide', :options => {:direction => 'vertical'}},
|
||||
:blind_right => {:method => 'blind', :mode => 'show', :options => {:direction => 'horizontal'}},
|
||||
:blind_left => {:method => 'blind', :mode => 'hide', :options => {:direction => 'horizontal'}},
|
||||
:bounce_in => {:method => 'bounce', :mode => 'show', :options => {:direction => 'up'}},
|
||||
:bounce_out => {:method => 'bounce', :mode => 'hide', :options => {:direction => 'up'}},
|
||||
:drop_in => {:method => 'drop', :mode => 'show', :options => {:direction => 'up'}},
|
||||
:drop_out => {:method => 'drop', :mode => 'hide', :options => {:direction => 'down'}},
|
||||
:fade => {:method => 'fadeOut'},
|
||||
:fold_in => {:method => 'fold', :mode => 'hide'},
|
||||
:fold_out => {:method => 'fold', :mode => 'show'},
|
||||
:grow => {:method => 'scale', :mode => 'show'},
|
||||
:shrink => {:method => 'scale', :mode => 'hide'},
|
||||
:slide_down => {:method => 'slide', :mode => 'show', :options => {:direction => 'up'}},
|
||||
:slide_up => {:method => 'slide', :mode => 'hide', :options => {:direction => 'up'}},
|
||||
:slide_right => {:method => 'slide', :mode => 'show', :options => {:direction => 'left'}},
|
||||
:slide_left => {:method => 'slide', :mode => 'hide', :options => {:direction => 'left'}},
|
||||
:squish => {:method => 'scale', :mode => 'hide', :options => {:origin => "['top','left']"}},
|
||||
:switch_on => {:method => 'clip', :mode => 'show', :options => {:direction => 'vertical'}},
|
||||
:switch_off => {:method => 'clip', :mode => 'hide', :options => {:direction => 'vertical'}},
|
||||
:toggle_appear => {:method => 'fadeToggle'},
|
||||
:toggle_slide => {:method => 'slide', :mode => 'toggle', :options => {:direction => 'up'}},
|
||||
:toggle_blind => {:method => 'blind', :mode => 'toggle', :options => {:direction => 'vertical'}},
|
||||
}
|
||||
end
|
||||
|
||||
def visual_effect(name, element_id = false, js_options = {})
|
||||
element = element_id ? element_id : "this"
|
||||
|
||||
if SCRIPTACULOUS_EFFECTS.has_key? name.to_sym
|
||||
effect = SCRIPTACULOUS_EFFECTS[name.to_sym]
|
||||
name = effect[:method]
|
||||
mode = effect[:mode]
|
||||
js_options = js_options.merge(effect[:options]) if effect[:options]
|
||||
end
|
||||
|
||||
[:color, :direction].each do |option|
|
||||
js_options[option] = "'#{js_options[option]}'" if js_options[option]
|
||||
end
|
||||
|
||||
if js_options.has_key? :duration
|
||||
speed = js_options.delete :duration
|
||||
speed = (speed * 1000).to_i unless speed.nil?
|
||||
else
|
||||
speed = js_options.delete :speed
|
||||
end
|
||||
|
||||
if ['fadeIn','fadeOut','fadeToggle'].include?(name)
|
||||
javascript = "#{JQUERY_VAR}('#{jquery_id(element_id)}').#{name}("
|
||||
javascript << "#{speed}" unless speed.nil?
|
||||
javascript << ");"
|
||||
else
|
||||
javascript = "#{JQUERY_VAR}('#{jquery_id(element_id)}').#{mode || 'effect'}('#{name}'"
|
||||
javascript << ",#{options_for_javascript(js_options)}" unless speed.nil? && js_options.empty?
|
||||
javascript << ",#{speed}" unless speed.nil?
|
||||
javascript << ");"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def sortable_element_js(element_id, options = {}) #:nodoc:
|
||||
#convert similar attributes
|
||||
options[:handle] = ".#{options[:handle]}" if options[:handle]
|
||||
if options[:tag] || options[:only]
|
||||
options[:items] = "> "
|
||||
options[:items] << options.delete(:tag) if options[:tag]
|
||||
options[:items] << ".#{options.delete(:only)}" if options[:only]
|
||||
end
|
||||
options[:connectWith] = options.delete(:containment).map {|x| "##{x}"} if options[:containment]
|
||||
options[:containment] = options.delete(:container) if options[:container]
|
||||
options[:dropOnEmpty] = false unless options[:dropOnEmpty]
|
||||
options[:helper] = "'clone'" if options[:ghosting] == true
|
||||
options[:axis] = case options.delete(:constraint)
|
||||
when "vertical"
|
||||
"y"
|
||||
when "horizontal"
|
||||
"x"
|
||||
when false
|
||||
nil
|
||||
when nil
|
||||
"y"
|
||||
end
|
||||
options.delete(:axis) if options[:axis].nil?
|
||||
options.delete(:overlap)
|
||||
options.delete(:ghosting)
|
||||
|
||||
if options[:onUpdate] || options[:url]
|
||||
options[:with] ||= "#{JQUERY_VAR}(this).sortable('serialize',{key:'#{element_id}'})"
|
||||
options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
|
||||
end
|
||||
|
||||
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
|
||||
options[:update] = options.delete(:onUpdate) if options[:onUpdate]
|
||||
|
||||
[:axis, :cancel, :containment, :cursor, :handle, :tolerance, :items, :placeholder].each do |option|
|
||||
options[option] = "'#{options[option]}'" if options[option]
|
||||
end
|
||||
|
||||
options[:connectWith] = array_or_string_for_javascript(options[:connectWith]) if options[:connectWith]
|
||||
|
||||
%(#{JQUERY_VAR}('#{jquery_id(element_id)}').sortable(#{options_for_javascript(options)});)
|
||||
end
|
||||
|
||||
def draggable_element_js(element_id, options = {})
|
||||
%(#{JQUERY_VAR}("#{jquery_id(element_id)}").draggable(#{options_for_javascript(options)});)
|
||||
end
|
||||
|
||||
def drop_receiving_element_js(element_id, options = {})
|
||||
#convert similar options
|
||||
options[:hoverClass] = options.delete(:hoverclass) if options[:hoverclass]
|
||||
options[:drop] = options.delete(:onDrop) if options[:onDrop]
|
||||
|
||||
if options[:drop] || options[:url]
|
||||
options[:with] ||= "'id=' + encodeURIComponent(#{JQUERY_VAR}(ui.draggable).attr('id'))"
|
||||
options[:drop] ||= "function(ev, ui){" + remote_function(options) + "}"
|
||||
end
|
||||
|
||||
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
|
||||
def replace(*options_for_render)
|
||||
call 'replaceWith', @generator.send(:render, *options_for_render)
|
||||
end
|
||||
|
||||
def reload(options_for_replace={})
|
||||
replace(options_for_replace.merge({ :partial => @id.to_s.sub(/^#/,'') }))
|
||||
end
|
||||
|
||||
def value()
|
||||
call 'val()'
|
||||
end
|
||||
|
||||
options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]
|
||||
[:activeClass, :hoverClass, :tolerance].each do |option|
|
||||
options[option] = "'#{options[option]}'" if options[option]
|
||||
end
|
||||
|
||||
%(#{JQUERY_VAR}('#{jquery_id(element_id)}').droppable(#{options_for_javascript(options)});)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
def value=(value)
|
||||
call 'val', value
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = PrototypeHelper::JQUERY_VAR
|
||||
end
|
||||
|
||||
def initialize(generator, pattern)
|
||||
super(generator, "#{JQUERY_VAR}(#{pattern.to_json})")
|
||||
end
|
||||
end
|
||||
|
||||
module ScriptaculousHelper
|
||||
|
||||
unless const_defined? :JQUERY_VAR
|
||||
JQUERY_VAR = PrototypeHelper::JQUERY_VAR
|
||||
end
|
||||
|
||||
unless const_defined? :SCRIPTACULOUS_EFFECTS
|
||||
SCRIPTACULOUS_EFFECTS = {
|
||||
:appear => {:method => 'fadeIn'},
|
||||
:blind_down => {:method => 'blind', :mode => 'show', :options => {:direction => 'vertical'}},
|
||||
:blind_up => {:method => 'blind', :mode => 'hide', :options => {:direction => 'vertical'}},
|
||||
:blind_right => {:method => 'blind', :mode => 'show', :options => {:direction => 'horizontal'}},
|
||||
:blind_left => {:method => 'blind', :mode => 'hide', :options => {:direction => 'horizontal'}},
|
||||
:bounce_in => {:method => 'bounce', :mode => 'show', :options => {:direction => 'up'}},
|
||||
:bounce_out => {:method => 'bounce', :mode => 'hide', :options => {:direction => 'up'}},
|
||||
:drop_in => {:method => 'drop', :mode => 'show', :options => {:direction => 'up'}},
|
||||
:drop_out => {:method => 'drop', :mode => 'hide', :options => {:direction => 'down'}},
|
||||
:fade => {:method => 'fadeOut'},
|
||||
:fold_in => {:method => 'fold', :mode => 'hide'},
|
||||
:fold_out => {:method => 'fold', :mode => 'show'},
|
||||
:grow => {:method => 'scale', :mode => 'show'},
|
||||
:shrink => {:method => 'scale', :mode => 'hide'},
|
||||
:slide_down => {:method => 'slide', :mode => 'show', :options => {:direction => 'up'}},
|
||||
:slide_up => {:method => 'slide', :mode => 'hide', :options => {:direction => 'up'}},
|
||||
:slide_right => {:method => 'slide', :mode => 'show', :options => {:direction => 'left'}},
|
||||
:slide_left => {:method => 'slide', :mode => 'hide', :options => {:direction => 'left'}},
|
||||
:squish => {:method => 'scale', :mode => 'hide', :options => {:origin => "['top','left']"}},
|
||||
:switch_on => {:method => 'clip', :mode => 'show', :options => {:direction => 'vertical'}},
|
||||
:switch_off => {:method => 'clip', :mode => 'hide', :options => {:direction => 'vertical'}},
|
||||
:toggle_appear => {:method => 'fadeToggle'},
|
||||
:toggle_slide => {:method => 'slide', :mode => 'toggle', :options => {:direction => 'up'}},
|
||||
:toggle_blind => {:method => 'blind', :mode => 'toggle', :options => {:direction => 'vertical'}},
|
||||
}
|
||||
end
|
||||
|
||||
def visual_effect(name, element_id = false, js_options = {})
|
||||
element = element_id ? element_id : "this"
|
||||
|
||||
if SCRIPTACULOUS_EFFECTS.has_key? name.to_sym
|
||||
effect = SCRIPTACULOUS_EFFECTS[name.to_sym]
|
||||
name = effect[:method]
|
||||
mode = effect[:mode]
|
||||
js_options = js_options.merge(effect[:options]) if effect[:options]
|
||||
end
|
||||
|
||||
[:color, :direction, :startcolor, :endcolor].each do |option|
|
||||
js_options[option] = "'#{js_options[option]}'" if js_options[option]
|
||||
end
|
||||
|
||||
if js_options.has_key? :duration
|
||||
speed = js_options.delete :duration
|
||||
speed = (speed * 1000).to_i unless speed.nil?
|
||||
else
|
||||
speed = js_options.delete :speed
|
||||
end
|
||||
|
||||
if ['fadeIn','fadeOut','fadeToggle'].include?(name)
|
||||
# 090905 - Jake - changed ' to \" so it passes assert_select_rjs with an id
|
||||
javascript = "#{JQUERY_VAR}(\"#{jquery_id(element_id)}\").#{name}("
|
||||
javascript << "#{speed}" unless speed.nil?
|
||||
javascript << ");"
|
||||
else
|
||||
# 090905 - Jake - changed ' to \" so it passes "assert_select_rjs :effect, ID"
|
||||
javascript = "#{JQUERY_VAR}(\"#{jquery_id(element_id)}\").#{mode || 'effect'}('#{name}'"
|
||||
javascript << ",#{options_for_javascript(js_options)}" unless speed.nil? && js_options.empty?
|
||||
javascript << ",#{speed}" unless speed.nil?
|
||||
javascript << ");"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def sortable_element_js(element_id, options = {}) #:nodoc:
|
||||
#convert similar attributes
|
||||
options[:handle] = ".#{options[:handle]}" if options[:handle]
|
||||
if options[:tag] || options[:only]
|
||||
options[:items] = "> "
|
||||
options[:items] << options.delete(:tag) if options[:tag]
|
||||
options[:items] << ".#{options.delete(:only)}" if options[:only]
|
||||
end
|
||||
options[:connectWith] = options.delete(:containment).map {|x| "##{x}"} if options[:containment]
|
||||
options[:containment] = options.delete(:container) if options[:container]
|
||||
options[:dropOnEmpty] = false unless options[:dropOnEmpty]
|
||||
options[:helper] = "'clone'" if options[:ghosting] == true
|
||||
options[:axis] = case options.delete(:constraint)
|
||||
when "vertical", :vertical
|
||||
"y"
|
||||
when "horizontal", :horizontal
|
||||
"x"
|
||||
when false
|
||||
nil
|
||||
when nil
|
||||
"y"
|
||||
end
|
||||
options.delete(:axis) if options[:axis].nil?
|
||||
options.delete(:overlap)
|
||||
options.delete(:ghosting)
|
||||
|
||||
if options[:onUpdate] || options[:url]
|
||||
if options[:format]
|
||||
options[:with] ||= "#{JQUERY_VAR}(this).sortable('serialize',{key:'#{element_id}[]', expression:#{options[:format]}})"
|
||||
options.delete(:format)
|
||||
else
|
||||
options[:with] ||= "#{JQUERY_VAR}(this).sortable('serialize',{key:'#{element_id}[]'})"
|
||||
end
|
||||
|
||||
options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
|
||||
end
|
||||
|
||||
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
|
||||
options[:update] = options.delete(:onUpdate) if options[:onUpdate]
|
||||
|
||||
[:axis, :cancel, :containment, :cursor, :handle, :tolerance, :items, :placeholder].each do |option|
|
||||
options[option] = "'#{options[option]}'" if options[option]
|
||||
end
|
||||
|
||||
options[:connectWith] = array_or_string_for_javascript(options[:connectWith]) if options[:connectWith]
|
||||
|
||||
%(#{JQUERY_VAR}('#{jquery_id(element_id)}').sortable(#{options_for_javascript(options)});)
|
||||
end
|
||||
|
||||
def draggable_element_js(element_id, options = {})
|
||||
%(#{JQUERY_VAR}("#{jquery_id(element_id)}").draggable(#{options_for_javascript(options)});)
|
||||
end
|
||||
|
||||
def drop_receiving_element_js(element_id, options = {})
|
||||
#convert similar options
|
||||
options[:hoverClass] = options.delete(:hoverclass) if options[:hoverclass]
|
||||
options[:drop] = options.delete(:onDrop) if options[:onDrop]
|
||||
|
||||
if options[:drop] || options[:url]
|
||||
options[:with] ||= "'id=' + encodeURIComponent(#{JQUERY_VAR}(ui.draggable).attr('id'))"
|
||||
options[:drop] ||= "function(ev, ui){" + remote_function(options) + "}"
|
||||
end
|
||||
|
||||
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
|
||||
|
||||
options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]
|
||||
[:activeClass, :hoverClass, :tolerance].each do |option|
|
||||
options[option] = "'#{options[option]}'" if options[option]
|
||||
end
|
||||
|
||||
%(#{JQUERY_VAR}('#{jquery_id(element_id)}').droppable(#{options_for_javascript(options)});)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# The following options can be changed by creating an initializer in config/initializers/jrails.rb
|
||||
|
||||
# jRails uses jQuery.noConflict() by default
|
||||
# to use the default jQuery varibale, use:
|
||||
# ActionView::Helpers::PrototypeHelper::JQUERY_VAR = '$'
|
||||
|
||||
# ActionView::Helpers::PrototypeHelper:: DISABLE_JQUERY_FORGERY_PROTECTION
|
||||
# Set this to disable forgery protection in ajax calls
|
||||
# This is handy if you want to use caching with ajax by injecting the forgery token via another means
|
||||
# for an example, see http://henrik.nyh.se/2008/05/rails-authenticity-token-with-jquery
|
||||
# ActionView::Helpers::PrototypeHelper::DISABLE_JQUERY_FORGERY_PROTECTION = true
|
||||
|
||||
ActionView::Helpers::AssetTagHelper::JAVASCRIPT_DEFAULT_SOURCES = ['jquery','jquery-ui','jrails']
|
||||
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
|
||||
require 'jrails'
|
||||
require 'jquery_selector_assertions' if RAILS_ENV == 'test'
|
|
@ -1,19 +1,25 @@
|
|||
namespace :jrails do
|
||||
namespace :update do
|
||||
|
||||
namespace :js do
|
||||
desc "Copies the jQuery and jRails javascripts to public/javascripts"
|
||||
task :javascripts do
|
||||
task :install do
|
||||
puts "Copying files..."
|
||||
project_dir = RAILS_ROOT + '/public/javascripts/'
|
||||
scripts = Dir[File.join(File.dirname(__FILE__), '..') + '/javascripts/*.js']
|
||||
scripts = Dir[File.join(File.dirname(__FILE__), '..', '/javascripts/', '*.js')]
|
||||
FileUtils.cp(scripts, project_dir)
|
||||
puts "files copied successfully."
|
||||
end
|
||||
end
|
||||
|
||||
namespace :install do
|
||||
desc "Installs the jQuery and jRails javascripts to public/javascripts"
|
||||
task :javascripts do
|
||||
Rake::Task['jrails:update:javascripts'].invoke
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Remove the prototype / script.aculo.us javascript files'
|
||||
task :scrub do
|
||||
puts "Removing files..."
|
||||
files = %W[controls.js dragdrop.js effects.js prototype.js]
|
||||
project_dir = File.join(RAILS_ROOT, 'public', 'javascripts')
|
||||
files.each do |fname|
|
||||
FileUtils.rm(File.join(project_dir, fname)) if File.exists?(File.join(project_dir, fname))
|
||||
end
|
||||
puts "files removed successfully."
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue