allgems 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +0 -0
- data/README.rdoc +16 -0
- data/allgems.gemspec +24 -0
- data/bin/allgems +215 -0
- data/config.ru +11 -0
- data/lib/allgems.rb +69 -0
- data/lib/allgems/App.rb +92 -0
- data/lib/allgems/Configurator.rb +0 -0
- data/lib/allgems/GemWorker.rb +229 -0
- data/lib/allgems/IndexBuilder.rb +17 -0
- data/lib/allgems/Indexer.rb +23 -0
- data/lib/allgems/Runner.rb +59 -0
- data/lib/allgems/Specer.rb +12 -0
- data/lib/allgems/ViewHelpers.rb +48 -0
- data/lib/allgems/hanna_hack.rb +82 -0
- data/lib/allgems/migrations/001_initialize.rb +39 -0
- data/public/images/edit.png +0 -0
- data/public/images/folder.png +0 -0
- data/public/images/git.gif +0 -0
- data/public/images/page.png +0 -0
- data/public/images/page_white_text.png +0 -0
- data/public/images/rubygems-125x125t.png +0 -0
- data/public/javascripts/base.js +212 -0
- data/public/javascripts/gembox.js +77 -0
- data/public/javascripts/jquery.form.js +632 -0
- data/public/javascripts/jquery.js +4241 -0
- data/public/javascripts/jquery.metadata.js +121 -0
- data/public/javascripts/jquery.ui.js +273 -0
- data/public/swf/clippy.swf +0 -0
- data/views/doc.haml +17 -0
- data/views/file_tree.haml +9 -0
- data/views/gem.haml +45 -0
- data/views/gembox.sass +188 -0
- data/views/gems_columns.haml +24 -0
- data/views/gems_header.haml +15 -0
- data/views/gems_table.haml +28 -0
- data/views/index.haml +1 -0
- data/views/layout.haml +59 -0
- data/views/load.haml +16 -0
- data/views/no_results.haml +3 -0
- metadata +185 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
module AllGems
|
2
|
+
class IndexBuilder
|
3
|
+
def initialize(args={})
|
4
|
+
raise ArgumentError.new('Expecting a Sequel::Database to be passed') unless args[:database] && args[:database].is_a?(Sequel::Database)
|
5
|
+
@db = args[:database]
|
6
|
+
end
|
7
|
+
def build_array(filter=[])
|
8
|
+
b = []
|
9
|
+
Gem::SpecFetcher.fetcher.list(AllGems.allgems).each_pair{|uri, x| b = b | x.reject{|a|filter.include?(a)}.map{|c|{:name => c[0], :version => c[1]}}}
|
10
|
+
b
|
11
|
+
end
|
12
|
+
def local_array
|
13
|
+
la = @db[:versions].join(:gems, :id => :gem_id).join(:platforms, :id => :versions__platform_id).select(:name, :version, :platform).all.collect{|x|x.values}
|
14
|
+
la.map{|a| [a[0], Gem::Version.new(a[1]), a[2]]}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AllGems
|
2
|
+
class Indexer
|
3
|
+
class << self
|
4
|
+
def index_gem(spec, format)
|
5
|
+
case format
|
6
|
+
when :hanna
|
7
|
+
self.index_hanna(spec)
|
8
|
+
when :rdoc
|
9
|
+
self.index_rdoc(spec)
|
10
|
+
when :sdoc
|
11
|
+
self.index_sdoc(spec)
|
12
|
+
end
|
13
|
+
AllGems.logger.info "Gem index is complete for #{spec.full_name}"
|
14
|
+
end
|
15
|
+
def index_hanna(spec)
|
16
|
+
end
|
17
|
+
def index_rdoc(spec)
|
18
|
+
end
|
19
|
+
def index_sdoc(spec)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'actionpool'
|
2
|
+
require 'actiontimer'
|
3
|
+
require 'allgems/IndexBuilder'
|
4
|
+
require 'allgems/GemWorker'
|
5
|
+
|
6
|
+
module AllGems
|
7
|
+
class Runner
|
8
|
+
# :db_path:: path to sqlite database
|
9
|
+
# :runners:: maximum number of threads to use
|
10
|
+
# :interval:: how often to update documents (useless if using cron)
|
11
|
+
def initialize(args={})
|
12
|
+
raise ArgumentError.new('Expecting path to database') unless args[:db_path]
|
13
|
+
@db = Sequel.connect("sqlite://#{args[:db_path]}")
|
14
|
+
AllGems.initialize_db(@db)
|
15
|
+
@pool = ActionPool::Pool.new(:max_threads => args[:runners] ? args[:runners] : 10)
|
16
|
+
GemWorker.setup
|
17
|
+
@index = IndexBuilder.new(:database => @db)
|
18
|
+
@interval = args[:interval] ? args[:interval] : nil
|
19
|
+
@timer = nil
|
20
|
+
@lock = Mutex.new
|
21
|
+
@guard = ConditionVariable.new
|
22
|
+
@stop = false
|
23
|
+
end
|
24
|
+
|
25
|
+
def do_sync
|
26
|
+
if(@interval)
|
27
|
+
@timer = ActionTimer::Timer.new(:pool => @pool)
|
28
|
+
sync
|
29
|
+
@timer.add(@interval){ sync }
|
30
|
+
else
|
31
|
+
sync
|
32
|
+
end
|
33
|
+
end
|
34
|
+
# Get the list of gems we need and load up the pool. Then take a nap
|
35
|
+
# until the pool gets bored and wakes us up
|
36
|
+
def sync
|
37
|
+
Gem.refresh
|
38
|
+
Thread.new do
|
39
|
+
@pool.add_jobs(@index.build_array(@index.local_array).collect{|x| lambda{GemWorker.process({:database => @db}.merge(x))}})
|
40
|
+
end
|
41
|
+
begin
|
42
|
+
@pool << lambda{@lock.synchronize{@guard.signal}}
|
43
|
+
@lock.synchronize{@guard.wait(@lock)}
|
44
|
+
rescue StandardError => boom
|
45
|
+
AllGems.logger.error boom.to_s
|
46
|
+
retry unless @stop
|
47
|
+
end
|
48
|
+
end
|
49
|
+
# Stop the runner
|
50
|
+
def stop(now=false)
|
51
|
+
@timer.clear if @timer
|
52
|
+
@stop = true
|
53
|
+
@lock.synchronize{@guard.broadcast}
|
54
|
+
@pool.shutdown(now)
|
55
|
+
GemWorker.pool.shutdown(now)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module AllGems
|
2
|
+
class Specer
|
3
|
+
class << self
|
4
|
+
def get_spec(gem, version=nil)
|
5
|
+
spec = AllGems.db[:specs].join(:versions, :id => :version_id).join(:gems, :id => :gem_id).filter(:name => gem)
|
6
|
+
spec = spec.filter(:version => version) if version
|
7
|
+
spec = spec.order(:version.desc).limit(1).first
|
8
|
+
return spec ? Marshal.load(spec[:spec].unpack('m')[0]) : nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rdoc/markup/to_html'
|
2
|
+
|
3
|
+
module AllGems
|
4
|
+
module ViewHelpers
|
5
|
+
|
6
|
+
def tag_options(options, escape = true)
|
7
|
+
option_string = options.collect {|k,v| %{#{k}="#{v}"}}.join(' ')
|
8
|
+
option_string = " " + option_string unless option_string.blank?
|
9
|
+
end
|
10
|
+
|
11
|
+
def content_tag(name, content, options, escape = true)
|
12
|
+
tag_options = tag_options(options, escape) if options
|
13
|
+
"<#{name}#{tag_options}>#{content}</#{name}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
def link_to(text, link = nil, options = {})
|
17
|
+
link ||= text
|
18
|
+
link = url_for(link)
|
19
|
+
"<a href=\"#{link}\">#{text}</a>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def link_to_gem(gem, options = {})
|
23
|
+
version = options[:version] ? options[:version] : ''
|
24
|
+
text = options[:text] ? options[:text] : gem
|
25
|
+
link_to(text, "/gems/#{gem}/#{version}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def url_for(link_options)
|
29
|
+
case link_options
|
30
|
+
when Hash
|
31
|
+
path = link_options.delete(:path) || request.path_info
|
32
|
+
params.delete('captures')
|
33
|
+
path + '?' + build_query(params.merge(link_options))
|
34
|
+
else
|
35
|
+
link_options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def ts(time)
|
40
|
+
time.strftime('%b %d, %Y') if time
|
41
|
+
end
|
42
|
+
|
43
|
+
def rdocify(text)
|
44
|
+
@_rdoc ||= RDoc::Markup::ToHtml.new
|
45
|
+
@_rdoc.convert(text)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# This file is a simple hack to force hanna to use
|
2
|
+
# the 2.3.0 version of rdoc
|
3
|
+
|
4
|
+
if ARGV.size == 1 and ARGV.first == '-h'
|
5
|
+
puts <<-HELP
|
6
|
+
Hanna -- a better RDoc template
|
7
|
+
Synopsis:
|
8
|
+
hanna [options] [file names...]
|
9
|
+
[sudo] hanna --gems [gem names...]
|
10
|
+
|
11
|
+
Example usage:
|
12
|
+
|
13
|
+
hanna lib/**/*.rb
|
14
|
+
|
15
|
+
Hanna passes all arguments to RDoc. To find more about RDoc options, see
|
16
|
+
"rdoc -h". Default options are:
|
17
|
+
|
18
|
+
-o doc --inline-source --charset=UTF-8
|
19
|
+
|
20
|
+
The second form, with the "--gems" argument, serves the same purpose as
|
21
|
+
the "gem rdoc" command: it generates documentation for installed gems.
|
22
|
+
When no gem names are given, "hanna --gems" will install docs for EACH of
|
23
|
+
the gems, which can, uh, take a little while.
|
24
|
+
|
25
|
+
HELP
|
26
|
+
exit 0
|
27
|
+
end
|
28
|
+
|
29
|
+
unless RUBY_PLATFORM =~ /(:?mswin|mingw)/
|
30
|
+
require 'pathname'
|
31
|
+
hanna_dir = Pathname.new(__FILE__).realpath.dirname + '../lib'
|
32
|
+
else
|
33
|
+
# windows
|
34
|
+
hanna_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
35
|
+
end
|
36
|
+
|
37
|
+
$:.unshift(hanna_dir) unless $:.include?(hanna_dir)
|
38
|
+
|
39
|
+
require 'rubygems'
|
40
|
+
gem 'rdoc', '2.3.0'
|
41
|
+
require 'rdoc/rdoc'
|
42
|
+
|
43
|
+
options = []
|
44
|
+
|
45
|
+
options << '-f' << 'html' << '-T' << 'hanna'
|
46
|
+
options << '--inline-source' << '--charset=UTF-8'
|
47
|
+
|
48
|
+
if ARGV.first == '--gems'
|
49
|
+
require 'rubygems/doc_manager'
|
50
|
+
Gem::DocManager.configured_args = options
|
51
|
+
|
52
|
+
gem_names = ARGV.dup
|
53
|
+
gem_names.shift
|
54
|
+
|
55
|
+
unless gem_names.empty?
|
56
|
+
specs = gem_names.inject([]) do |arr, name|
|
57
|
+
found = Gem::SourceIndex.from_installed_gems.find_name(name)
|
58
|
+
spec = found.sort_by {|s| s.version }.last
|
59
|
+
arr << spec if spec
|
60
|
+
arr
|
61
|
+
end
|
62
|
+
else
|
63
|
+
specs = Gem::SourceIndex.from_installed_gems.inject({}) do |all, pair|
|
64
|
+
full_name, spec = pair
|
65
|
+
if spec.has_rdoc? and (!all[spec.name] or spec.version > all[spec.name].version)
|
66
|
+
all[spec.name] = spec
|
67
|
+
end
|
68
|
+
all
|
69
|
+
end
|
70
|
+
specs = specs.values
|
71
|
+
puts "Hanna is installing documentation for #{specs.size} gem#{specs.size > 1 ? 's' : ''} ..."
|
72
|
+
end
|
73
|
+
|
74
|
+
specs.each do |spec|
|
75
|
+
Gem::DocManager.new(spec).generate_rdoc
|
76
|
+
end
|
77
|
+
else
|
78
|
+
options << '-o' << 'doc' unless ARGV.include?('-o') or ARGV.include?('--op')
|
79
|
+
options.concat ARGV
|
80
|
+
|
81
|
+
RDoc::RDoc.new.document(options)
|
82
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Class.new(Sequel::Migration) do
|
2
|
+
def up
|
3
|
+
AllGems.db << "CREATE TABLE gems (
|
4
|
+
name VARCHAR NOT NULL UNIQUE COLLATE NOCASE,
|
5
|
+
summary TEXT,
|
6
|
+
description TEXT,
|
7
|
+
id INTEGER NOT NULL PRIMARY KEY)"
|
8
|
+
# create_table(:gems) do
|
9
|
+
# String :name, :null => false, :unique => true
|
10
|
+
# String :summary
|
11
|
+
# String :description
|
12
|
+
# primary_key :id, :null => false
|
13
|
+
# end
|
14
|
+
AllGems.db.create_table(:platforms) do
|
15
|
+
String :platform, :null => false, :unique => true
|
16
|
+
primary_key :id, :null => false
|
17
|
+
end
|
18
|
+
AllGems.db.create_table(:versions) do
|
19
|
+
String :version, :null => false
|
20
|
+
Time :release, :null => false
|
21
|
+
foreign_key :gem_id, :table => :gems, :null => false
|
22
|
+
foreign_key :platform_id, :table => :platforms, :null => false
|
23
|
+
index [:gem_id, :version, :platform_id], :unique => true
|
24
|
+
primary_key :id, :null => false
|
25
|
+
end
|
26
|
+
AllGems.db.create_table(:specs) do
|
27
|
+
String :spec, :null => false
|
28
|
+
foreign_key :version_id, :table => :versions, :null => false
|
29
|
+
index [:spec, :version_id], :unique => true
|
30
|
+
primary_key :id, :null => false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def down
|
34
|
+
AllGems.db.drop_table(:specs)
|
35
|
+
AllGems.db.drop_table(:versions)
|
36
|
+
AllGems.db.drop_table(:platforms)
|
37
|
+
AllGems.db.drop_table(:gems)
|
38
|
+
end
|
39
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,212 @@
|
|
1
|
+
(function(){
|
2
|
+
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
|
3
|
+
|
4
|
+
// The base Class implementation (does nothing)
|
5
|
+
this.Class = function(){};
|
6
|
+
|
7
|
+
// Create a new Class that inherits from this class
|
8
|
+
Class.extend = function(prop) {
|
9
|
+
var _super = this.prototype;
|
10
|
+
|
11
|
+
// Instantiate a base class (but only create the instance,
|
12
|
+
// don't run the init constructor)
|
13
|
+
initializing = true;
|
14
|
+
var prototype = new this();
|
15
|
+
initializing = false;
|
16
|
+
|
17
|
+
// Copy the properties over onto the new prototype
|
18
|
+
for (var name in prop) {
|
19
|
+
// Check if we're overwriting an existing function
|
20
|
+
prototype[name] = typeof prop[name] == "function" &&
|
21
|
+
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
22
|
+
(function(name, fn){
|
23
|
+
return function() {
|
24
|
+
var tmp = this._super;
|
25
|
+
|
26
|
+
// Add a new ._super() method that is the same method
|
27
|
+
// but on the super-class
|
28
|
+
this._super = _super[name];
|
29
|
+
|
30
|
+
// The method only need to be bound temporarily, so we
|
31
|
+
// remove it when we're done executing
|
32
|
+
var ret = fn.apply(this, arguments);
|
33
|
+
this._super = tmp;
|
34
|
+
|
35
|
+
return ret;
|
36
|
+
};
|
37
|
+
})(name, prop[name]) :
|
38
|
+
prop[name];
|
39
|
+
}
|
40
|
+
|
41
|
+
// The dummy class constructor
|
42
|
+
function Class() {
|
43
|
+
// All construction is actually done in the init method
|
44
|
+
if ( !initializing && this.init )
|
45
|
+
this.init.apply(this, arguments);
|
46
|
+
}
|
47
|
+
|
48
|
+
// Populate our constructed prototype object
|
49
|
+
Class.prototype = prototype;
|
50
|
+
|
51
|
+
// Enforce the constructor to be what we expect
|
52
|
+
Class.constructor = Class;
|
53
|
+
|
54
|
+
// And make this class extendable
|
55
|
+
Class.extend = arguments.callee;
|
56
|
+
|
57
|
+
return Class;
|
58
|
+
};
|
59
|
+
})();
|
60
|
+
|
61
|
+
|
62
|
+
$.fn.extend({
|
63
|
+
getId: function() {
|
64
|
+
var match = $(this).attr("id").match(/\d+/)
|
65
|
+
return match ? parseInt(match[0]) : null;
|
66
|
+
},
|
67
|
+
setInputHint: function() {
|
68
|
+
el = $(this);
|
69
|
+
el.data('default', el.val());
|
70
|
+
|
71
|
+
el.focus(function() {
|
72
|
+
if(el.data('default') != el.val()) return;
|
73
|
+
el.removeClass('hint').val('');
|
74
|
+
})
|
75
|
+
.blur(function() {
|
76
|
+
if($.trim(el.val()) != '') return;
|
77
|
+
el.addClass('hint').val(el.data('default'));
|
78
|
+
})
|
79
|
+
.addClass('hint');
|
80
|
+
},
|
81
|
+
fadeUp: function(speed) {
|
82
|
+
$(this).css({'position':'relative'}).animate({top:"-150px", opacity: 0}, speed, function() { $(this).remove(); })
|
83
|
+
return $(this);
|
84
|
+
}
|
85
|
+
});
|
86
|
+
|
87
|
+
$.extend({
|
88
|
+
log: function() {
|
89
|
+
if (typeof console == 'undefined') {
|
90
|
+
// do nothing
|
91
|
+
} else {
|
92
|
+
console.log(arguments);
|
93
|
+
}
|
94
|
+
},
|
95
|
+
timestamp: function() {
|
96
|
+
return Math.floor(new Date().getTime()/1000);
|
97
|
+
}
|
98
|
+
});
|
99
|
+
|
100
|
+
// authenticity tokens
|
101
|
+
// http://www.viget.com/extend/ie-jquery-rails-and-http-oh-my
|
102
|
+
$(function() {
|
103
|
+
$(document).ajaxSend(function(event, request, settings) {
|
104
|
+
if (settings.type == 'GET' || settings.type == 'get' || typeof(AUTH_TOKEN) == "undefined") return;
|
105
|
+
// settings.data is a serialized string like "foo=bar&baz=boink" (or null)
|
106
|
+
settings.data = settings.data || "";
|
107
|
+
settings.data += (settings.data ? "&" : "") + "authenticity_token=" + encodeURIComponent(AUTH_TOKEN);
|
108
|
+
});
|
109
|
+
});
|
110
|
+
|
111
|
+
var Base = {
|
112
|
+
popup: function (link,title,width,height) {
|
113
|
+
return window.open(link,title,"height="+height+",width="+width+",status=no,toolbar=no,menubar=no,location=no");
|
114
|
+
},
|
115
|
+
urlify: function(title) {
|
116
|
+
// self.downcase.gsub(/(_|-|\/|\\|\&|,| )/,'_')[0..40]
|
117
|
+
return title.toString().strip().toLowerCase().gsub(/ /, '_').gsub(/[^a-z0-9\-_]/,'').truncate(40,'');
|
118
|
+
},
|
119
|
+
copyTextToClipboard: function(text) {
|
120
|
+
// create form element
|
121
|
+
var form_element = $('clipboard_holder') ? $('clipboard_holder') : new Element('input',{'type':'hidden','id':'clipboard_holder','name':'clipboard_holder','value':text});
|
122
|
+
if (form_element.createTextRange) {
|
123
|
+
var range = form_element.createTextRange();
|
124
|
+
if (range && BodyLoaded==1)
|
125
|
+
range.execCommand('Copy');
|
126
|
+
} else {
|
127
|
+
var flashcopier = $('flashcopier') ? $('flashcopier') : new Element('div',{id: 'flashcopier'});
|
128
|
+
$(flashcopier).innerHTML = '<embed src="/swf/_clipboard.swf" FlashVars="clipboard='+escape(form_element.value)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
|
129
|
+
document.body.appendChild(flashcopier);
|
130
|
+
}
|
131
|
+
},
|
132
|
+
images: {
|
133
|
+
hover_suffix: '_on',
|
134
|
+
active_suffix: '_on',
|
135
|
+
deactive_suffix: '_off',
|
136
|
+
swap: function(for_el,to) {
|
137
|
+
$(for_el).attr('src', to);
|
138
|
+
},
|
139
|
+
activate: function (for_el) {
|
140
|
+
return this.swap(for_el,this.activateSrc(for_el));
|
141
|
+
},
|
142
|
+
deactivate: function (for_el) {
|
143
|
+
return this.swap(for_el,this.deactivateSrc(for_el));
|
144
|
+
},
|
145
|
+
hover: function (for_el) {
|
146
|
+
return this.swap(for_el,this.hoverSrc(for_el));
|
147
|
+
},
|
148
|
+
replaceSrc: function (for_el,search,replace_with) {
|
149
|
+
return $(for_el).attr('src').replace(search,replace_with);
|
150
|
+
},
|
151
|
+
activateSrc: function (for_el) {
|
152
|
+
return this.replaceSrc(for_el,this.deactive_suffix,this.active_suffix);
|
153
|
+
},
|
154
|
+
deactivateSrc: function (for_el) {
|
155
|
+
return this.replaceSrc(for_el,this.active_suffix,this.deactive_suffix);
|
156
|
+
},
|
157
|
+
hoverSrc: function (for_el) {
|
158
|
+
return this.replaceSrc(for_el,this.deactive_suffix,this.hover_suffix);
|
159
|
+
},
|
160
|
+
restore: function (for_el) {
|
161
|
+
MM_swapImgRestore();
|
162
|
+
}
|
163
|
+
}
|
164
|
+
};
|
165
|
+
|
166
|
+
$.extend({
|
167
|
+
param: function( a, nest_in ) {
|
168
|
+
var s = [ ];
|
169
|
+
// check for nest
|
170
|
+
if (typeof nest_in == 'undefined') nest_in = false;
|
171
|
+
|
172
|
+
function nested(key) {
|
173
|
+
if (nest_in)
|
174
|
+
return nest_in + '[' + key + ']';
|
175
|
+
else
|
176
|
+
return key;
|
177
|
+
}
|
178
|
+
function add( key, value ){
|
179
|
+
key = nested(key)
|
180
|
+
s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
181
|
+
};
|
182
|
+
// If an array was passed in, assume that it is an array
|
183
|
+
// of form elements
|
184
|
+
if ( jQuery.isArray(a) || a.jquery )
|
185
|
+
// Serialize the form elements
|
186
|
+
jQuery.each( a, function(){
|
187
|
+
add( this.name, this.value );
|
188
|
+
});
|
189
|
+
|
190
|
+
// Otherwise, assume that it's an object of key/value pairs
|
191
|
+
else
|
192
|
+
// Serialize the key/values
|
193
|
+
for ( var j in a )
|
194
|
+
// If the value is an array then the key names need to be repeated
|
195
|
+
if ( jQuery.isArray(a[j]) )
|
196
|
+
jQuery.each( a[j], function(){
|
197
|
+
add( j, this );
|
198
|
+
});
|
199
|
+
else if (a[j].constructor == Object)
|
200
|
+
s.push($.param(a[j], nested(j)));
|
201
|
+
else
|
202
|
+
add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
|
203
|
+
|
204
|
+
// Return the resulting serialization
|
205
|
+
return s.join("&").replace(/%20/g, "+");
|
206
|
+
},
|
207
|
+
shove: function(fn, object) {
|
208
|
+
return function() {
|
209
|
+
return fn.apply(object, arguments);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
});
|