spakit 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +2 -0
- data/Manifest.txt +7 -0
- data/README.txt +142 -0
- data/Rakefile +11 -0
- data/init.rb +2 -0
- data/lib/spakit.rb +27 -0
- data/lib/spakit_helper.rb +70 -0
- metadata +71 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
Author:: Wen-Tien Chang(mailto:ihower@handlino.com), hlb(mailto:hlb@handlino.com)
|
2
|
+
Copyright:: Copyright (c) 2007 Handlino Inc.
|
3
|
+
License:: Distributed under the New BSD License
|
4
|
+
|
5
|
+
== Description ==
|
6
|
+
Spakit is a plugin that makes it very easy to turn your Rails App
|
7
|
+
Into a "single page application" (SPA).
|
8
|
+
|
9
|
+
To enable SPA, simply install the plug-in, create a spakit layout and use Spakit helper.
|
10
|
+
Don't need modify any model/controller code... ;)
|
11
|
+
|
12
|
+
Spakit will send xhr request(i.e. prototype's Ajax.Updater ) with ?layout=spakit,
|
13
|
+
and controller return HTML with spakit layout. Note that spakit_form_for not support file upload submit.
|
14
|
+
|
15
|
+
By the way, Message plugin is another SPA plugin,using different approach.
|
16
|
+
|
17
|
+
== Requirements
|
18
|
+
* Rails 2.0.2
|
19
|
+
|
20
|
+
== Install ==
|
21
|
+
* gem install spakit
|
22
|
+
* cd /your_app/vendor/plugin/
|
23
|
+
* gem unpack spakit
|
24
|
+
|
25
|
+
== Usage ==
|
26
|
+
|
27
|
+
For now, Spakit provide three helper:
|
28
|
+
|
29
|
+
* spakit_link_to, just like remote_link_to
|
30
|
+
* spakit_form_for, just like form_for, but you must specify :url
|
31
|
+
* spakit_form_tag, just like form_tag
|
32
|
+
|
33
|
+
by default spakit will replace HTML element called #content.
|
34
|
+
|
35
|
+
== Layout code example ==
|
36
|
+
You should write flash message here because we often place that in application layout.
|
37
|
+
|
38
|
+
# /view/layouts/spakit.rhtml
|
39
|
+
|
40
|
+
<p><%= flash[:notice] %></p>
|
41
|
+
<%= yield %>
|
42
|
+
|
43
|
+
== History Bookmarks ==
|
44
|
+
|
45
|
+
We recommend Really Simple History(RSH) library to handle browser forward/back.
|
46
|
+
|
47
|
+
Example code:
|
48
|
+
|
49
|
+
# environment.rb
|
50
|
+
|
51
|
+
module SpakitHelper
|
52
|
+
@@spa_options = {
|
53
|
+
:update => 'content-region',
|
54
|
+
:loading => 'SPA.loading',
|
55
|
+
:complete => 'SPA.complete'
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# application.js
|
60
|
+
# We use jquery syntax, you can use prototype to define your function.
|
61
|
+
|
62
|
+
var $j = jQuery.noConflict();
|
63
|
+
|
64
|
+
(function($) {
|
65
|
+
SPA = {
|
66
|
+
currentHash: null,
|
67
|
+
currentLocation: null,
|
68
|
+
init: function() {
|
69
|
+
if ( $('#waiting-message').length == 0 ) {
|
70
|
+
$('<div id="waiting-message"><img src="/images/ajax-loader.gif"></div>').appendTo('#bd');
|
71
|
+
$('#waiting-message').hide();
|
72
|
+
}
|
73
|
+
},
|
74
|
+
loading: function() {
|
75
|
+
this.init();
|
76
|
+
$('#waiting-message').show();
|
77
|
+
},
|
78
|
+
hide: function() {
|
79
|
+
$('#waiting-message').hide();
|
80
|
+
},
|
81
|
+
historyChange: function(newLocation, historyData, isFresh) {
|
82
|
+
if (isFresh == null) {
|
83
|
+
if (historyStorage.hasKey(newLocation)) {
|
84
|
+
if (newLocation == "start") {
|
85
|
+
newLocation = location.pathname;
|
86
|
+
}
|
87
|
+
|
88
|
+
$.ajax({
|
89
|
+
type: "GET",
|
90
|
+
url: newLocation,
|
91
|
+
data: { layout: "spakit" },
|
92
|
+
beforeSend: function(){ SPA.loading(); },
|
93
|
+
complete: function(res, status){
|
94
|
+
if ( status == "success" || status == "notmodified" ) {
|
95
|
+
$('#content-region').html(res.responseText);
|
96
|
+
}
|
97
|
+
SPA.hide();
|
98
|
+
}
|
99
|
+
});
|
100
|
+
}
|
101
|
+
} else {
|
102
|
+
/* new data */
|
103
|
+
dhtmlHistory.add(newLocation, historyData);
|
104
|
+
}
|
105
|
+
},
|
106
|
+
complete: function(newLocation) {
|
107
|
+
this.historyChange(newLocation, "", true);
|
108
|
+
this.hide();
|
109
|
+
}
|
110
|
+
};
|
111
|
+
|
112
|
+
SPA.currentHash = window.location.hash;
|
113
|
+
if (SPA.currentHash.length) {
|
114
|
+
if (SPA.currentHash.charAt(0) == '#' && SPA.currentHash.charAt(1) == '/') {
|
115
|
+
SPA.currentLocation = SPA.currentHash.slice(1);
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
$(document).ready(function(){
|
120
|
+
dhtmlHistory.initialize();
|
121
|
+
if (SPA.currentLocation) {
|
122
|
+
if (SPA.currentLocation != '#start') {
|
123
|
+
window.location.href = SPA.currentLocation;
|
124
|
+
}
|
125
|
+
} else {
|
126
|
+
dhtmlHistory.addListener(SPA.historyChange);
|
127
|
+
if (dhtmlHistory.isFirstLoad()) {
|
128
|
+
dhtmlHistory.add("start", "");
|
129
|
+
}
|
130
|
+
}
|
131
|
+
});
|
132
|
+
|
133
|
+
})(jQuery);
|
134
|
+
|
135
|
+
window.dhtmlHistory.create({
|
136
|
+
toJSON: function(o) {
|
137
|
+
return JSON.stringify(o);
|
138
|
+
},
|
139
|
+
fromJSON: function(s) {
|
140
|
+
return JSON.parse(s);
|
141
|
+
}
|
142
|
+
});
|
data/Rakefile
ADDED
data/init.rb
ADDED
data/lib/spakit.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module ActionController
|
2
|
+
|
3
|
+
class Base
|
4
|
+
alias :rails_redirect_to :redirect_to
|
5
|
+
alias :rails_render :render
|
6
|
+
|
7
|
+
def redirect_to(options = {}, response_status = {})
|
8
|
+
if options.class == Hash
|
9
|
+
options.merge!( :layout => 'spakit' ) if ( self.params[:layout].to_s == 'spakit' && !options.include?(:layout) )
|
10
|
+
elsif options.class == String
|
11
|
+
options = options + '?layout=spakit' if ( self.params[:layout].to_s == 'spakit' && !options.include?('layout=') )
|
12
|
+
end
|
13
|
+
|
14
|
+
rails_redirect_to(options, response_status)
|
15
|
+
end
|
16
|
+
|
17
|
+
# deprecated_status is for rspec compatible
|
18
|
+
# http://rubyforge.org/pipermail/rspec-users/2007-November/004780.html
|
19
|
+
def render(options = nil,deprecated_status=nil, &block) #:doc:
|
20
|
+
options.merge!( :layout => 'spakit' ) if ( options.class == Hash && !options.include?(:layout) && self.params[:layout].to_s == 'spakit' )
|
21
|
+
options = { :layout => 'spakit' } if ( !options && self.params[:layout].to_s == 'spakit' ) #rails default
|
22
|
+
|
23
|
+
rails_render(options, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module SpakitHelper
|
2
|
+
|
3
|
+
@@spa_options = {
|
4
|
+
:update => 'content',
|
5
|
+
:loading => nil,
|
6
|
+
:complete => nil
|
7
|
+
}
|
8
|
+
|
9
|
+
# api is the same as remote_link_to
|
10
|
+
# TODO: omit CSRF auth token if method is get
|
11
|
+
def spakit_link_to(name, options = {}, html_options = nil)
|
12
|
+
#abs path will use non-SPA
|
13
|
+
return link_to(name,options[:url]) if options[:url].class == String && options[:url].include?('http://')
|
14
|
+
|
15
|
+
html_options = { :href => url_for(options[:url]) } unless html_options
|
16
|
+
html_options[:href] = url_for(options[:url]) unless (html_options && html_options[:href] )
|
17
|
+
|
18
|
+
options.merge!( :method => :get ) unless options[:method]
|
19
|
+
options.merge!( :update => @@spa_options[:update] ) if (@@spa_options[:update] && !options[:update])
|
20
|
+
options.merge!( :loading => "#{@@spa_options[:loading]}()" ) if (@@spa_options[:loading] && !options[:loading])
|
21
|
+
options.merge!( :complete => "#{@@spa_options[:complete]}('#{html_options[:href]}');" ) if (@@spa_options[:complete] && !options[:complete])
|
22
|
+
options.merge! ( :with => "'layout=spakit'" ) unless options[:with]
|
23
|
+
|
24
|
+
link_to_remote(name, options, html_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# api is the same as remote_remote_for, but you must provide :url
|
28
|
+
# spakit_remote_for @event, :url => hash_for_events_path, :html => {...} do |f|
|
29
|
+
# is just equal
|
30
|
+
# form_remote_for @event, :url => hash_for_events_path.merge(:layout => 'spakit'), :update => 'content', :loading => "SPA.show()",:complete => "SPA.hide()" do |f|
|
31
|
+
# TODO: can omit :url
|
32
|
+
def spakit_form_for(record_or_name_or_array, *args, &proc)
|
33
|
+
options = args.extract_options!
|
34
|
+
|
35
|
+
target = url_for( options[:url] )
|
36
|
+
options.merge!( :update => @@spa_options[:update] ) if (@@spa_options[:update] && !options[:update])
|
37
|
+
options.merge!( :loading => "#{@@spa_options[:loading]}()" ) if (@@spa_options[:loading] && !options[:loading])
|
38
|
+
options.merge!( :complete => "#{@@spa_options[:complete]}('#{target}');" ) if (@@spa_options[:complete] && !options[:complete])
|
39
|
+
|
40
|
+
#can't use options[:with] here because it will force to use Form.serialize
|
41
|
+
if options[:url].is_a?(Hash)
|
42
|
+
options[:url].merge!( :layout => 'spakit' )
|
43
|
+
elsif options[:url].is_a?(String)
|
44
|
+
options[:url] = options[:url] + '?layout=spakit' #String
|
45
|
+
end
|
46
|
+
|
47
|
+
options[:html] = { :action => target } unless options[:html]
|
48
|
+
options[:html].merge!( :action => target ) if ( options[:html] and !options[:html][:action] )
|
49
|
+
|
50
|
+
form_remote_for(record_or_name_or_array, *(args << options), &proc)
|
51
|
+
end
|
52
|
+
|
53
|
+
def spakit_form_tag( options = {}, &block)
|
54
|
+
target = ( options[:url].is_a?(Hash) ) ? url_for( options[:url] ) : options[:url]
|
55
|
+
options.merge!( :update => @@spa_options[:update] ) if (@@spa_options[:update] && !options[:update])
|
56
|
+
options.merge!( :loading => "#{@@spa_options[:loading]}()" ) if (@@spa_options[:loading] && !options[:loading])
|
57
|
+
options.merge!( :complete => "#{@@spa_options[:complete]}('#{target}');" ) if (@@spa_options[:complete] && !options[:complete])
|
58
|
+
|
59
|
+
if options[:url].is_a?(Hash)
|
60
|
+
options[:url].merge!( :layout => 'spakit' )
|
61
|
+
elsif options[:url].is_a?(String)
|
62
|
+
options[:url] = options[:url] + '?layout=spakit' #String
|
63
|
+
end
|
64
|
+
|
65
|
+
options[:html] = { :action => target } unless options[:html]
|
66
|
+
options[:html].merge!( :action => target ) if ( options[:html] and !options[:html][:action] )
|
67
|
+
|
68
|
+
form_remote_tag(options, &block)
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spakit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wen-Tien Chang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-04-08 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.5.1
|
23
|
+
version:
|
24
|
+
description: ""
|
25
|
+
email:
|
26
|
+
- ihower@handlino.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
files:
|
36
|
+
- History.txt
|
37
|
+
- init.rb
|
38
|
+
- Manifest.txt
|
39
|
+
- Rakefile
|
40
|
+
- lib/spakit.rb
|
41
|
+
- lib/spakit_helper.rb
|
42
|
+
- README.txt
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: Spakit is a plugin that makes it very easy to turn your Rails App
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --main
|
48
|
+
- README.txt
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project: spakit
|
66
|
+
rubygems_version: 1.1.0
|
67
|
+
signing_key:
|
68
|
+
specification_version: 2
|
69
|
+
summary: ""
|
70
|
+
test_files: []
|
71
|
+
|