admin_assistant 1.0.4 → 2.0.0.pre1
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/Rakefile +21 -2
- data/VERSION +1 -1
- data/admin_assistant.gemspec +13 -11
- data/install.rb +8 -13
- data/lib/admin_assistant.rb +7 -11
- data/lib/admin_assistant/active_record_column.rb +5 -6
- data/lib/admin_assistant/belongs_to_column.rb +2 -2
- data/lib/admin_assistant/column.rb +6 -4
- data/lib/admin_assistant/helper.rb +9 -2
- data/lib/admin_assistant/index.rb +6 -6
- data/lib/admin_assistant/request/autocomplete.rb +12 -15
- data/lib/javascripts/admin_assistant.js +148 -220
- data/lib/javascripts/jquery.tokeninput.js +695 -0
- data/lib/stylesheets/token-input.css +113 -0
- data/lib/views/_polymorphic_field_search.html.erb +44 -57
- data/lib/views/_token_input.html.erb +26 -0
- data/lib/views/index.html.erb +8 -2
- metadata +60 -40
- data/lib/views/_restricted_autocompleter.html.erb +0 -53
- data/lib/views/autocomplete.html.erb +0 -11
data/Rakefile
CHANGED
@@ -1,10 +1,29 @@
|
|
1
1
|
require 'grancher/task'
|
2
2
|
require 'rake'
|
3
3
|
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'spec/rake/spectask'
|
4
6
|
|
5
7
|
desc 'Default: run all specs across all supported Rails gem versions.'
|
6
8
|
task :default => :spec
|
7
9
|
|
10
|
+
# run with rake publish
|
11
|
+
Grancher::Task.new do |g|
|
12
|
+
g.branch = 'gh-pages'
|
13
|
+
g.push_to = 'origin' # automatically push too
|
14
|
+
|
15
|
+
g.directory 'website'
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Generate documentation for the admin_assistant plugin.'
|
19
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
20
|
+
rdoc.rdoc_dir = 'rdoc'
|
21
|
+
rdoc.title = 'AdminAssistant'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
26
|
+
|
8
27
|
desc 'Run all specs across all supported Rails gem versions.'
|
9
28
|
task :spec do
|
10
29
|
supported_versions = %w(2.1.0 2.1.2 2.2.2 2.3.2 2.3.3 2.3.4)
|
@@ -16,7 +35,7 @@ task :spec do
|
|
16
35
|
if !missing.empty?
|
17
36
|
puts "Missing Rails versions #{missing.join(',')}; please install and then re-run tests"
|
18
37
|
else
|
19
|
-
cmd = "cd
|
38
|
+
cmd = "cd rails_2_test && " + (
|
20
39
|
supported_versions.map { |version|
|
21
40
|
"echo '===== Testing #{version} =====' && RAILS_GEM_VERSION=#{version} rake"
|
22
41
|
}.join(" && ")
|
@@ -36,7 +55,7 @@ begin
|
|
36
55
|
gem.homepage = "http://github.com/fhwang/admin_assistant"
|
37
56
|
gem.authors = ["Francis Hwang"]
|
38
57
|
gem.add_dependency "will_paginate"
|
39
|
-
gem.files.exclude "
|
58
|
+
gem.files.exclude "rails_2_test"
|
40
59
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
41
60
|
end
|
42
61
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0.pre1
|
data/admin_assistant.gemspec
CHANGED
@@ -4,14 +4,14 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "
|
7
|
+
s.name = %q{admin_assistant}
|
8
|
+
s.version = "2.0.0.pre1"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Francis Hwang"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = %q{2011-05-08}
|
13
|
+
s.description = %q{admin_assistant is a Rails plugin that automates a lot of features typically needed in admin interfaces.}
|
14
|
+
s.email = %q{sera@fhwang.net}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README"
|
17
17
|
]
|
@@ -54,11 +54,12 @@ Gem::Specification.new do |s|
|
|
54
54
|
"lib/images/sort-asc.png",
|
55
55
|
"lib/images/sort-desc.png",
|
56
56
|
"lib/javascripts/admin_assistant.js",
|
57
|
+
"lib/javascripts/jquery.tokeninput.js",
|
57
58
|
"lib/stylesheets/activescaffold.css",
|
58
59
|
"lib/stylesheets/default.css",
|
60
|
+
"lib/stylesheets/token-input.css",
|
59
61
|
"lib/views/_polymorphic_field_search.html.erb",
|
60
|
-
"lib/views/
|
61
|
-
"lib/views/autocomplete.html.erb",
|
62
|
+
"lib/views/_token_input.html.erb",
|
62
63
|
"lib/views/form.html.erb",
|
63
64
|
"lib/views/index.html.erb",
|
64
65
|
"lib/views/multi_form.html.erb",
|
@@ -133,12 +134,13 @@ Gem::Specification.new do |s|
|
|
133
134
|
"website/screenshots.markdown",
|
134
135
|
"website/tutorial.markdown"
|
135
136
|
]
|
136
|
-
s.homepage =
|
137
|
+
s.homepage = %q{http://github.com/fhwang/admin_assistant}
|
137
138
|
s.require_paths = ["lib"]
|
138
|
-
s.rubygems_version =
|
139
|
-
s.summary =
|
139
|
+
s.rubygems_version = %q{1.3.7}
|
140
|
+
s.summary = %q{admin_assistant is a Rails plugin that automates a lot of features typically needed in admin interfaces.}
|
140
141
|
|
141
142
|
if s.respond_to? :specification_version then
|
143
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
142
144
|
s.specification_version = 3
|
143
145
|
|
144
146
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/install.rb
CHANGED
@@ -3,24 +3,19 @@ require 'pathname'
|
|
3
3
|
|
4
4
|
outer = File.dirname(__FILE__)
|
5
5
|
|
6
|
-
# Delete
|
6
|
+
# Delete rails_2_test and various doc directories, unless you're actually
|
7
7
|
# developing admin_assistant itself
|
8
|
-
test_rails_app = Pathname.new("#{outer}/
|
8
|
+
test_rails_app = Pathname.new("#{outer}/rails_2_test").realpath.to_s
|
9
9
|
unless RAILS_ROOT == test_rails_app
|
10
|
-
%w(doc
|
10
|
+
%w(doc rails_2_test website).each do |dir|
|
11
11
|
FileUtils.rm_rf "#{outer}/#{dir}"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
# Copy over static assets
|
16
|
-
|
17
|
-
|
18
|
-
FileUtils.
|
19
|
-
FileUtils.
|
20
|
-
|
21
|
-
"#{RAILS_ROOT}/public/javascripts/admin_assistant.js"
|
22
|
-
)
|
23
|
-
images_dir = "#{RAILS_ROOT}/public/images/admin_assistant"
|
24
|
-
FileUtils.mkdir(images_dir) unless File.exist?(images_dir)
|
25
|
-
FileUtils.cp_r(Dir.glob("#{outer}/lib/images/*"), images_dir)
|
16
|
+
%w(stylesheets javascripts images).each do |asset_type|
|
17
|
+
asset_dir = "#{Rails.root}/public/#{asset_type}/admin_assistant"
|
18
|
+
FileUtils.mkdir(asset_dir) unless File.exist?(asset_dir)
|
19
|
+
FileUtils.cp_r(Dir.glob("#{outer}/lib/#{asset_type}/*"), asset_dir)
|
20
|
+
end
|
26
21
|
|
data/lib/admin_assistant.rb
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
$: << File.join(File.dirname(__FILE__), '../vendor/ar_query/lib')
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
)
|
10
|
-
files.each do |file|
|
11
|
-
require "#{File.dirname(__FILE__)}/admin_assistant/#{file}"
|
2
|
+
require 'find'
|
3
|
+
require 'admin_assistant/column'
|
4
|
+
Find.find(File.dirname(__FILE__)) do |path|
|
5
|
+
if path =~ %r|\.rb$| && path !~ %r|admin_assistant\.rb$| &&
|
6
|
+
path !~ %r|admin_assistant/column\.rb$|
|
7
|
+
require path
|
8
|
+
end
|
12
9
|
end
|
13
|
-
|
14
10
|
require 'will_paginate'
|
15
11
|
|
16
12
|
class AdminAssistant
|
@@ -166,8 +166,8 @@ class AdminAssistant
|
|
166
166
|
js_name = "#{form.object.class.name.underscore}_#{name}"
|
167
167
|
name = @clear_link || "Clear"
|
168
168
|
h << @action_view.send(
|
169
|
-
:
|
170
|
-
|
169
|
+
:link_to, name, '#',
|
170
|
+
'data-prefix' => js_name, :class => 'clear_datetime_select'
|
171
171
|
)
|
172
172
|
end
|
173
173
|
h
|
@@ -270,16 +270,15 @@ class AdminAssistant
|
|
270
270
|
|
271
271
|
def ajax_toggle_inner_html(record)
|
272
272
|
div_id = ajax_toggle_div_id record
|
273
|
-
@action_view.
|
273
|
+
@action_view.link_to(
|
274
274
|
string(record),
|
275
|
-
|
276
|
-
:url => {
|
275
|
+
{
|
277
276
|
:action => 'update', :id => record.id, :from => div_id,
|
278
277
|
record.class.name.underscore.to_sym => {
|
279
278
|
name => (!value(record) ? '1' : '0')
|
280
279
|
}
|
281
280
|
},
|
282
|
-
:
|
281
|
+
{:class => 'toggle', :rel => 'nofollow', 'data-method' => 'put'}
|
283
282
|
)
|
284
283
|
end
|
285
284
|
|
@@ -142,7 +142,7 @@ class AdminAssistant
|
|
142
142
|
def render_autocompleter(form)
|
143
143
|
@action_view.send(
|
144
144
|
:render,
|
145
|
-
:file => AdminAssistant.template_file('
|
145
|
+
:file => AdminAssistant.template_file('_token_input'),
|
146
146
|
:use_full_path => false,
|
147
147
|
:locals => {
|
148
148
|
:form => form, :column => @column,
|
@@ -176,7 +176,7 @@ class AdminAssistant
|
|
176
176
|
def render_autocompleter(form)
|
177
177
|
@action_view.send(
|
178
178
|
:render,
|
179
|
-
:file => AdminAssistant.template_file('
|
179
|
+
:file => AdminAssistant.template_file('_token_input'),
|
180
180
|
:use_full_path => false,
|
181
181
|
:locals => {
|
182
182
|
:form => form, :column => @column,
|
@@ -238,8 +238,9 @@ class AdminAssistant
|
|
238
238
|
input << comparator_html(form.object) << ' ' if @comparators == :all
|
239
239
|
input << form.datetime_select(name, :include_blank => true)
|
240
240
|
input << @action_view.send(
|
241
|
-
:
|
242
|
-
"
|
241
|
+
:link_to, 'Clear', '#',
|
242
|
+
'data-prefix' => "search_#{name.underscore}",
|
243
|
+
:class => 'clear_datetime_select'
|
243
244
|
)
|
244
245
|
end
|
245
246
|
input
|
@@ -254,8 +255,9 @@ class AdminAssistant
|
|
254
255
|
:datetime_separator => ' — ', :time_separator => ' : '
|
255
256
|
).select_datetime
|
256
257
|
input << @action_view.send(
|
257
|
-
:
|
258
|
-
"
|
258
|
+
:link_to, 'Clear', '#',
|
259
|
+
'data-prefix' => "search_#{name.underscore}_#{comparator}",
|
260
|
+
:class => 'clear_datetime_select'
|
259
261
|
)
|
260
262
|
input
|
261
263
|
end
|
@@ -2,8 +2,15 @@ class AdminAssistant
|
|
2
2
|
module Helper
|
3
3
|
def admin_assistant_includes(opts = {})
|
4
4
|
theme = opts[:theme] || 'default'
|
5
|
-
stylesheet_link_tag("admin_assistant/#{theme}")
|
6
|
-
|
5
|
+
tags = stylesheet_link_tag("admin_assistant/#{theme}")
|
6
|
+
tags << stylesheet_link_tag("admin_assistant/token-input")
|
7
|
+
js_dir = Pathname.new(Rails.root) + "public/javascripts/admin_assistant"
|
8
|
+
Dir.entries(js_dir).each do |entry|
|
9
|
+
if entry =~ /\.js$/
|
10
|
+
tags << javascript_include_tag("admin_assistant/#{entry}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
tags
|
7
14
|
end
|
8
15
|
end
|
9
16
|
end
|
@@ -216,13 +216,13 @@ class AdminAssistant
|
|
216
216
|
end
|
217
217
|
|
218
218
|
def delete_link(record)
|
219
|
-
@action_view.
|
219
|
+
@action_view.link_to(
|
220
220
|
'Delete',
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
221
|
+
{:action => 'destroy', :id => record.id},
|
222
|
+
{
|
223
|
+
'data-confirm' => 'Are you sure?', :rel => 'nofollow',
|
224
|
+
'data-method' => 'delete', :class => 'destroy'
|
225
|
+
}
|
226
226
|
)
|
227
227
|
end
|
228
228
|
|
@@ -8,34 +8,31 @@ class AdminAssistant
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
results = records.map { |record|
|
12
|
+
{:id => record.id.to_s, :name => record.send(record_name_field)}
|
13
|
+
}
|
14
|
+
@controller.send(:render, :json => results.to_json)
|
15
|
+
end
|
16
|
+
|
17
|
+
def record_name_field
|
18
|
+
AssociationTarget.new(associated_class).default_name_method
|
18
19
|
end
|
19
20
|
|
20
21
|
def records
|
21
22
|
action =~ /autocomplete_(.*)/
|
22
|
-
associated_class = Module.const_get $1.camelize
|
23
|
-
target = AssociationTarget.new associated_class
|
24
|
-
field = target.default_name_method
|
25
23
|
associated_class.find(
|
26
24
|
:all,
|
27
25
|
:conditions => [
|
28
|
-
"LOWER(#{
|
26
|
+
"LOWER(#{record_name_field}) like ?",
|
29
27
|
"%#{search_string.downcase unless search_string.nil?}%"
|
30
28
|
],
|
31
|
-
:limit => 10,
|
29
|
+
:limit => 10,
|
30
|
+
:order => "length(#{record_name_field}), lower(#{record_name_field})"
|
32
31
|
)
|
33
32
|
end
|
34
33
|
|
35
34
|
def search_string
|
36
|
-
@controller.params[
|
37
|
-
"#{underscored_assoc_class_name}_autocomplete_input"
|
38
|
-
]
|
35
|
+
@controller.params['q']
|
39
36
|
end
|
40
37
|
|
41
38
|
def underscored_assoc_class_name
|
@@ -3,251 +3,179 @@ Don't edit this file: It gets re-copied every time the server starts.
|
|
3
3
|
******************************************************************************/
|
4
4
|
|
5
5
|
var AdminAssistant = {};
|
6
|
-
AdminAssistant.clear_datetime_select = function(name) {
|
7
|
-
$R(1,5).each(function(index) {
|
8
|
-
$(name + '_' + index + 'i').value = '';
|
9
|
-
});
|
10
|
-
};
|
11
6
|
|
12
|
-
|
13
|
-
|
7
|
+
$(document).ready(function() {
|
8
|
+
$('.clear_datetime_select').click(function(event) {
|
9
|
+
name = $(event.target).attr('data-prefix');
|
10
|
+
$.each([1,2,3,4,5], function(i, val) {
|
11
|
+
$('#' + name + '_' + val + 'i').attr('value', '');
|
12
|
+
});
|
13
|
+
return false;
|
14
|
+
});
|
15
|
+
|
16
|
+
$('.index #show_search_form').click(function() {
|
17
|
+
$('#search_form').show();
|
18
|
+
return false;
|
19
|
+
});
|
20
|
+
|
21
|
+
$('.index a.destroy').click(function(event) {
|
22
|
+
jqElt = $(event.target);
|
23
|
+
if (confirm(jqElt.attr('data-confirm'))) {
|
24
|
+
url = jqElt.attr('href');
|
25
|
+
jqTr = jqElt.closest('tr')
|
26
|
+
$.post(
|
27
|
+
url,
|
28
|
+
{"_method": jqElt.attr('data-method')},
|
29
|
+
function() {
|
30
|
+
jqTr.fadeOut();
|
31
|
+
}
|
32
|
+
);
|
33
|
+
}
|
34
|
+
return false;
|
35
|
+
});
|
36
|
+
|
37
|
+
$('.index a.toggle').live('click', function(event) {
|
38
|
+
url = $(event.target).attr('href');
|
39
|
+
container = '#' + $(event.target).parent().attr('id');
|
40
|
+
$.post(
|
41
|
+
url,
|
42
|
+
{},
|
43
|
+
function(data) {
|
44
|
+
$(container).fadeOut(50, function() {
|
45
|
+
$(container).html(data);
|
46
|
+
$(container).fadeIn()
|
47
|
+
});
|
48
|
+
}
|
49
|
+
);
|
50
|
+
return false;
|
51
|
+
});
|
52
|
+
});
|
53
|
+
|
54
|
+
AdminAssistant.PolymorphicFieldSearch = function(name) {
|
55
|
+
this.name = name;
|
56
|
+
this.initialize();
|
14
57
|
};
|
15
58
|
|
16
|
-
AdminAssistant.PolymorphicFieldSearch = Class.create();
|
17
59
|
AdminAssistant.PolymorphicFieldSearch.prototype = {
|
18
|
-
initialize: function(
|
19
|
-
this.
|
20
|
-
this.
|
21
|
-
this.
|
22
|
-
this.autocompleteTypes = types.autocompleteTypes;
|
23
|
-
this.autocompleters = {};
|
24
|
-
this.autocompleteTypes.each(function(autocompleteType) {
|
25
|
-
autocompleter = this.newAutocompleter(autocompleteType);
|
26
|
-
this.autocompleters[autocompleteType.name] = autocompleter;
|
27
|
-
}, this);
|
28
|
-
this.idTypes = types.idTypes;
|
29
|
-
this.idTypes.each(function(idType) {
|
30
|
-
Event.observe(
|
31
|
-
this.name + '_' + idType.name + "_id", 'keyup',
|
32
|
-
this.setHiddenFieldsFromIdField.bind(this)
|
33
|
-
);
|
34
|
-
}, this);
|
35
|
-
this.selectTypes = types.selectTypes;
|
36
|
-
this.selectTypes.each(function(selectType) {
|
37
|
-
Event.observe(
|
38
|
-
this.name + '_' + selectType.name + "_id", 'change',
|
39
|
-
this.setHiddenFieldsFromSelectField.bind(this)
|
40
|
-
);
|
41
|
-
}, this);
|
60
|
+
initialize: function() {
|
61
|
+
this.initAutocompleters();
|
62
|
+
this.initSelectors();
|
63
|
+
this.initTextFields();
|
42
64
|
},
|
43
65
|
|
44
|
-
|
45
|
-
|
46
|
-
this.
|
66
|
+
initAutocompleters: function() {
|
67
|
+
var fieldSearch = this;
|
68
|
+
$.each(this.autocompleterElts(), function(i, elt) {
|
69
|
+
var valueType = $(elt).attr('data-value-type')
|
70
|
+
var opts = {
|
71
|
+
'crossDomain': false, 'tokenLimit': 1,
|
72
|
+
'onAdd': function(item) {
|
73
|
+
fieldSearch.tokenInputOnAdd(item, valueType, elt);
|
74
|
+
},
|
75
|
+
'onDelete': function(item) {
|
76
|
+
fieldSearch.tokenInputOnDelete(item, valueType);
|
77
|
+
}
|
78
|
+
};
|
79
|
+
var initialId = $(elt).attr('data-initial-id');
|
80
|
+
var initialName = $(elt).attr('data-initial-name');
|
81
|
+
if (initialId && initialName) {
|
82
|
+
opts['prePopulate'] = [{'id': initialId, 'name': initialName}];
|
83
|
+
}
|
84
|
+
$(elt).tokenInput($(elt).attr('data-autocomplete-url'), opts)
|
85
|
+
});
|
47
86
|
},
|
48
87
|
|
49
|
-
|
50
|
-
this
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if (idType.name != name_to_not_clear) {
|
59
|
-
$(this.name + '_' + idType.name + '_id').value = '';
|
60
|
-
}
|
61
|
-
}, this);
|
62
|
-
this.selectTypes.each(function(selectType) {
|
63
|
-
if (selectType.name != name_to_not_clear) {
|
64
|
-
$(this.name + '_' + selectType.name + '_id').value = '';
|
65
|
-
}
|
66
|
-
}, this);
|
88
|
+
initSelectors: function() {
|
89
|
+
var fieldSearch = this;
|
90
|
+
$.each(this.selectorElts(), function(i, elt) {
|
91
|
+
$(elt).bind('change', function(evt) {
|
92
|
+
fieldSearch.update(
|
93
|
+
$(this).val(), $(this).attr('data-value-type'), this
|
94
|
+
);
|
95
|
+
});
|
96
|
+
});
|
67
97
|
},
|
68
98
|
|
69
|
-
|
70
|
-
|
99
|
+
initTextFields: function() {
|
100
|
+
var fieldSearch = this;
|
101
|
+
$.each(this.textFieldElts(), function(i, elt) {
|
102
|
+
$(elt).bind('keyup', function(evt) {
|
103
|
+
fieldSearch.update(
|
104
|
+
$(this).val(), $(this).attr('data-value-type'), this
|
105
|
+
);
|
106
|
+
});
|
107
|
+
});
|
71
108
|
},
|
72
109
|
|
73
|
-
|
74
|
-
|
110
|
+
autocompleterElts: function() {
|
111
|
+
var acElts = [];
|
112
|
+
$("#" + this.rootId() + " input").each(function(i, elt) {
|
113
|
+
if ($(elt).attr('data-behavior') == 'autocomplete') {
|
114
|
+
acElts.push(elt);
|
115
|
+
}
|
116
|
+
});
|
117
|
+
return acElts;
|
75
118
|
},
|
76
119
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
parameters: autocompleteType.parameters,
|
85
|
-
paramName: autocompleteType.name + '_autocomplete_input',
|
86
|
-
textField: autocompleteType.textField
|
87
|
-
};
|
88
|
-
options.afterAutocomplete = function(value) {
|
89
|
-
this.hiddenTypeField().value = autocompleteType.type;
|
90
|
-
this.clearInputsExceptFor(autocompleteType.name);
|
91
|
-
}.bind(this);
|
92
|
-
options.afterClearSelected = function(value) {
|
93
|
-
this.hiddenTypeField().value = '';
|
94
|
-
}.bind(this);
|
95
|
-
return new AdminAssistant.RestrictedAutocompleter(
|
96
|
-
autocompleteType.name, this.hiddenFieldId, autocompleteType.url,
|
97
|
-
options
|
98
|
-
);
|
120
|
+
clearAutocompleterView: function(elt) {
|
121
|
+
containerDiv =
|
122
|
+
"#polymorphic_search_" + $(elt).attr('id').replace(/_id/, '');
|
123
|
+
// 1. remove the div containing the selected token
|
124
|
+
$(containerDiv + " .token-input-token").remove();
|
125
|
+
// 2. show the autocompleter input with a blank value
|
126
|
+
$(containerDiv + " input[autocomplete=off]").show().val("");
|
99
127
|
},
|
100
128
|
|
101
|
-
|
102
|
-
|
103
|
-
idType = this.idTypes.detect(function(idt) {
|
104
|
-
return (this.name + '_' + idt.name + '_id' == input.id);
|
105
|
-
}, this);
|
106
|
-
if (input.value == '') {
|
107
|
-
if (this.hiddenTypeField().value == idType.type) {
|
108
|
-
this.clearHiddenFields();
|
109
|
-
}
|
110
|
-
} else {
|
111
|
-
this.hiddenField().value = input.value;
|
112
|
-
this.hiddenTypeField().value = idType.type;
|
113
|
-
this.clearInputsExceptFor(idType.name);
|
114
|
-
}
|
129
|
+
rootId: function() {
|
130
|
+
return "polymorphic_search_" + this.name;
|
115
131
|
},
|
116
132
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
}
|
126
|
-
} else {
|
127
|
-
this.hiddenField().value = select.value;
|
128
|
-
this.hiddenTypeField().value = selectType.type;
|
129
|
-
this.clearInputsExceptFor(selectType.name);
|
130
|
-
}
|
131
|
-
}
|
132
|
-
}
|
133
|
-
|
134
|
-
/*
|
135
|
-
This autocompleter restricts based on a list of names and matching IDs; the IDs
|
136
|
-
are set in a hidden field. Arguments
|
137
|
-
*/
|
138
|
-
AdminAssistant.RestrictedAutocompleter = Class.create();
|
139
|
-
AdminAssistant.RestrictedAutocompleter.prototype = {
|
140
|
-
initialize: function(name, hiddenField, url, options) {
|
141
|
-
this.name = name;
|
142
|
-
this.textField = options.textField || (this.name + '_autocomplete_input');
|
143
|
-
this.palette = options.palette || (this.name + '_autocomplete_palette');
|
144
|
-
this.selectedTextFieldValue = $(this.textField).value;
|
145
|
-
this.hiddenField = hiddenField;
|
146
|
-
this.includeBlank = options.includeBlank;
|
147
|
-
this.modelName = options.modelName || this.name;
|
148
|
-
this.clearLink = options.clearLink || ('clear_' + this.name + '_link');
|
149
|
-
ajaxAutocompleterOptions = {
|
150
|
-
afterUpdateElement: this.autocompleteAfterUpdateElement.bind(this),
|
151
|
-
fullSearch: true,
|
152
|
-
onHide: this.autocompleteOnHide,
|
153
|
-
parameters: options.parameters,
|
154
|
-
paramName: options.paramName,
|
155
|
-
partialChars: 1
|
156
|
-
};
|
157
|
-
if (!options.paletteClonesInputWidth) {
|
158
|
-
ajaxAutocompleterOptions.onShow = this.onShowWithoutCloningInputWidth;
|
159
|
-
}
|
160
|
-
var ac = new Ajax.Autocompleter(
|
161
|
-
this.textField, this.palette, url, ajaxAutocompleterOptions
|
162
|
-
);
|
163
|
-
this.changeArrowBehavior(ac);
|
164
|
-
this.setClearLinkVisibility();
|
165
|
-
Event.observe(this.clearLink, 'click', function(event) {
|
166
|
-
this.clearSelected();
|
167
|
-
}.bind(this));
|
168
|
-
this.afterAutocomplete = options.afterAutocomplete;
|
169
|
-
this.afterClearSelected = options.afterClearSelected;
|
133
|
+
selectorElts: function() {
|
134
|
+
sElts = [];
|
135
|
+
$("#" + this.rootId() + " select").each(function(i, elt) {
|
136
|
+
if ($(elt).attr('data-behavior') == 'select') {
|
137
|
+
sElts.push(elt);
|
138
|
+
}
|
139
|
+
});
|
140
|
+
return sElts;
|
170
141
|
},
|
171
142
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
element.
|
181
|
-
*/
|
182
|
-
autocompleteAfterUpdateElement: function(element, selectedElement) {
|
183
|
-
var id_name = element.id;
|
184
|
-
var input_id = id_name.substr(id_name.length - 1)
|
185
|
-
var selected_value = selectedElement.id.substr(this.modelName.length)
|
186
|
-
|
187
|
-
// If they have more complex markup inside the selection, get the "title" element
|
188
|
-
var title_element = selectedElement.down(".title")
|
189
|
-
if (title_element) selectedElement = title_element
|
190
|
-
|
191
|
-
$(this.hiddenField).value = selected_value
|
192
|
-
this.selectedTextFieldValue =
|
193
|
-
selectedElement.innerHTML.unescapeHTML().strip();
|
194
|
-
this.setClearLinkVisibility();
|
195
|
-
if (this.afterAutocomplete) { this.afterAutocomplete(selected_value); }
|
196
|
-
},
|
197
|
-
|
198
|
-
/*
|
199
|
-
Refresh the text fill-in field to the value reflected in the underlying
|
200
|
-
hidden input fields
|
201
|
-
*/
|
202
|
-
autocompleteOnHide: function( element, update ) {
|
203
|
-
if (this.selectedTextFieldValue) {
|
204
|
-
element.value = this.selectedTextFieldValue;
|
205
|
-
}
|
206
|
-
new Effect.Fade(update,{duration:0.15});
|
207
|
-
},
|
208
|
-
|
209
|
-
/*
|
210
|
-
Overriding totally wierd arrow-up and arrow-down scrolling behavior built
|
211
|
-
into the autocompleter in scriptaculous 1.7.0
|
212
|
-
*/
|
213
|
-
changeArrowBehavior: function(ac) {
|
214
|
-
ac.markPrevious = function() {
|
215
|
-
if(this.index > 0) this.index--
|
216
|
-
else this.index = this.entryCount-1;
|
217
|
-
};
|
218
|
-
ac.markNext = function() {
|
219
|
-
if(this.index < this.entryCount-1) this.index++
|
220
|
-
else this.index = 0;
|
221
|
-
};
|
143
|
+
textFieldElts: function() {
|
144
|
+
var tfElts = []
|
145
|
+
$("#" + this.rootId() + " input[type!=hidden]").each(function(i, elt) {
|
146
|
+
if ($(elt).attr('data-behavior') == 'id') {
|
147
|
+
tfElts.push(elt);
|
148
|
+
}
|
149
|
+
});
|
150
|
+
return tfElts;
|
222
151
|
},
|
223
152
|
|
224
|
-
|
225
|
-
|
226
|
-
this.clearTextField();
|
227
|
-
this.setClearLinkVisibility();
|
228
|
-
if (this.afterClearSelected) { this.afterClearSelected(); }
|
153
|
+
tokenInputOnAdd: function(item, valueType, updatedElt) {
|
154
|
+
this.update(item.id, valueType, updatedElt);
|
229
155
|
},
|
230
156
|
|
231
|
-
|
232
|
-
|
233
|
-
update.style.position = 'absolute';
|
234
|
-
Position.clone(element, update, {
|
235
|
-
setHeight: false, setWidth: false, offsetTop: element.offsetHeight
|
236
|
-
});
|
237
|
-
}
|
238
|
-
Effect.Appear(update,{duration:0.15});
|
157
|
+
tokenInputOnDelete: function(item, valueType) {
|
158
|
+
this.update(null, null, null);
|
239
159
|
},
|
240
160
|
|
241
|
-
|
242
|
-
$(this.
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
161
|
+
update: function(id, type, updatedElt) {
|
162
|
+
$('#search_' + this.name + "_id").val(id);
|
163
|
+
$('#search_' + this.name + "_type").val(type);
|
164
|
+
var fieldSearch = this;
|
165
|
+
$.each(this.autocompleterElts(), function(i, elt) {
|
166
|
+
idFromUpdatedElt = $(updatedElt).attr('id');
|
167
|
+
idFromThisAutocompleter = $(elt).attr('id');
|
168
|
+
if (idFromUpdatedElt != idFromThisAutocompleter) {
|
169
|
+
fieldSearch.clearAutocompleterView(elt);
|
170
|
+
}
|
171
|
+
});
|
172
|
+
$.each(this.selectorElts(), function(i, elt) {
|
173
|
+
if (elt != updatedElt) { $(elt).val(''); }
|
174
|
+
});
|
175
|
+
$.each(this.textFieldElts(), function(i, elt) {
|
176
|
+
if (elt != updatedElt) { $(elt).val(''); }
|
177
|
+
});
|
251
178
|
}
|
252
|
-
}
|
179
|
+
};
|
180
|
+
|
253
181
|
|