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 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 test_rails_app && " + (
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 "test_rails_app/**/*"
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.0.4
1
+ 2.0.0.pre1
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = "admin_assistant"
8
- s.version = "1.0.4"
7
+ s.name = %q{admin_assistant}
8
+ s.version = "2.0.0.pre1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
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 = "2013-02-07"
13
- s.description = "admin_assistant is a Rails plugin that automates a lot of features typically needed in admin interfaces."
14
- s.email = "sera@fhwang.net"
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/_restricted_autocompleter.html.erb",
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 = "http://github.com/fhwang/admin_assistant"
137
+ s.homepage = %q{http://github.com/fhwang/admin_assistant}
137
138
  s.require_paths = ["lib"]
138
- s.rubygems_version = "1.8.25"
139
- s.summary = "admin_assistant is a Rails plugin that automates a lot of features typically needed in admin interfaces."
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 test_rails_app and various doc directories, unless you're actually
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}/test_rails_app").realpath.to_s
8
+ test_rails_app = Pathname.new("#{outer}/rails_2_test").realpath.to_s
9
9
  unless RAILS_ROOT == test_rails_app
10
- %w(doc test_rails_app website).each do |dir|
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
- css_dir = "#{RAILS_ROOT}/public/stylesheets/admin_assistant"
17
- FileUtils.mkdir(css_dir) unless File.exist?(css_dir)
18
- FileUtils.cp_r(Dir.glob("#{outer}/lib/stylesheets/*"), css_dir)
19
- FileUtils.copy(
20
- "#{outer}/lib/javascripts/admin_assistant.js",
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
 
@@ -1,16 +1,12 @@
1
1
  $: << File.join(File.dirname(__FILE__), '../vendor/ar_query/lib')
2
- files = %w(
3
- column virtual_column active_record_column association_target
4
- belongs_to_column builder date_time_range_end_point_selector
5
- default_search_column file_column_column form_view has_many_column helper
6
- index paperclip_column polymorphic_belongs_to_column request/base
7
- request/autocomplete request/create request/destroy request/edit
8
- request/index request/new request/show request/update search show_view
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
- :link_to_function, name,
170
- "AdminAssistant.clear_datetime_select('#{js_name}')"
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.link_to_remote(
273
+ @action_view.link_to(
274
274
  string(record),
275
- :update => div_id,
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
- :success => "$(#{div_id}).hide(); $(#{div_id}).appear()"
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('_restricted_autocompleter'),
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('_restricted_autocompleter'),
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
- :link_to_function, 'Clear',
242
- "AdminAssistant.clear_datetime_select('search_#{name.underscore}')"
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 => ' &mdash; ', :time_separator => ' : '
255
256
  ).select_datetime
256
257
  input << @action_view.send(
257
- :link_to_function, 'Clear',
258
- "AdminAssistant.clear_datetime_select('search_#{name.underscore}_#{comparator}')"
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
- javascript_include_tag('admin_assistant')
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.link_to_remote(
219
+ @action_view.link_to(
220
220
  'Delete',
221
- :url => {:action => 'destroy', :id => record.id},
222
- :confirm => 'Are you sure?',
223
- :success =>
224
- "Effect.Fade('#{@admin_assistant.model_class.name.underscore}_#{record.id}', {duration: 0.25})",
225
- :method => :delete
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
- render_template_file(
12
- 'autocomplete', :layout => false,
13
- :locals => {
14
- :records => records, :prefix => underscored_assoc_class_name,
15
- :associated_class => associated_class
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(#{field}) like ?",
26
+ "LOWER(#{record_name_field}) like ?",
29
27
  "%#{search_string.downcase unless search_string.nil?}%"
30
28
  ],
31
- :limit => 10, :order => "length(#{field}), lower(#{field})"
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
- AdminAssistant.show_search_form = function() {
13
- $('search_form').show();
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(name, types) {
19
- this.name = name;
20
- this.hiddenFieldId = 'search_' + name + '_id';
21
- this.hiddenTypeFieldId = 'search_' + name + '_type';
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
- clearHiddenFields: function() {
45
- this.hiddenField().value = '';
46
- this.hiddenTypeField().value = '';
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
- clearInputsExceptFor: function(name_to_not_clear) {
50
- this.autocompleteTypes.each(function(autocompleteType) {
51
- if (autocompleteType.name != name_to_not_clear) {
52
- var autocompleter = this.autocompleters[autocompleteType.name]
53
- autocompleter.clearTextField();
54
- autocompleter.setClearLinkVisibility();
55
- }
56
- }, this);
57
- this.idTypes.each(function(idType) {
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
- hiddenField: function() {
70
- return $(this.hiddenFieldId);
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
- hiddenTypeField: function() {
74
- return $(this.hiddenTypeFieldId);
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
- newAutocompleter: function(autocompleteType) {
78
- options = {
79
- clearLink: autocompleteType.clearLink,
80
- includeBlank: true,
81
- modelName: autocompleteType.name,
82
- palette: autocompleteType.palette,
83
- paletteClonesInputWidth: false,
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
- setHiddenFieldsFromIdField: function(event) {
102
- input = event.findElement();
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
- setHiddenFieldsFromSelectField: function(event) {
118
- select = event.findElement();
119
- selectType = this.selectTypes.detect(function(st) {
120
- return (this.name + '_' + st.name + '_id' == select.id);
121
- }, this);
122
- if (select.value == '') {
123
- if (this.hiddenTypeField().value == selectType.type) {
124
- this.clearHiddenFields();
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
- This is the callback that fires after a selection is made from the
174
- autocompleter results.
175
-
176
- In addition to setting hidden id fields, it will place the text label of the
177
- selected item in the search field. It assumes that your selectedElement is
178
- one with simple text contents or some markup structure with an element of
179
- class "title". In the latter case, it will use the text of the "title"
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
- clearSelected: function() {
225
- $(this.hiddenField).value = '';
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
- onShowWithoutCloningInputWidth: function(element, update){
232
- if(!update.style.position || update.style.position=='absolute') {
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
- clearTextField: function() {
242
- $(this.textField).value = '';
243
- },
244
-
245
- setClearLinkVisibility: function() {
246
- if ($(this.textField).value == '') {
247
- $(this.clearLink).hide();
248
- } else {
249
- if (this.includeBlank) { $(this.clearLink).show(); }
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