backlog 0.35.5 → 0.36.2

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.
Files changed (150) hide show
  1. data/Gemfile +19 -0
  2. data/Gemfile~ +4 -0
  3. data/History.txt +25 -0
  4. data/Rakefile +3 -3
  5. data/app/controllers/{application.rb → application_controller.rb} +1 -2
  6. data/app/controllers/backlogs_controller.rb +0 -16
  7. data/app/controllers/search_controller.rb +0 -2
  8. data/app/controllers/user_controller.rb +7 -7
  9. data/app/controllers/work_locks_controller.rb +2 -2
  10. data/app/controllers/works_controller.rb +23 -23
  11. data/app/helpers/application_helper.rb +9 -6
  12. data/app/helpers/backlogs_helper.rb +1 -1
  13. data/app/helpers/periods_helper.rb +1 -1
  14. data/app/models/backlog.rb +13 -10
  15. data/app/models/period.rb +0 -5
  16. data/app/models/sidebar.rb +1 -0
  17. data/app/models/task.rb +4 -10
  18. data/app/models/user.rb +5 -6
  19. data/app/models/user_notify.rb +0 -1
  20. data/app/models/work.rb +20 -25
  21. data/app/models/works_report_filter.rb +4 -4
  22. data/app/views/backlogs/_buttons.rhtml +1 -1
  23. data/app/views/backlogs/_form.rhtml +5 -9
  24. data/app/views/layouts/_left_top.rhtml +0 -1
  25. data/app/views/periods/_form.rhtml +1 -1
  26. data/app/views/search/results.rhtml +1 -12
  27. data/app/views/task_notify/{invite_en.rhtml → invite.en.html.erb} +0 -0
  28. data/app/views/task_notify/{invite_no.rhtml → invite.no.html.erb} +0 -0
  29. data/app/views/tasks/_task.rhtml +49 -50
  30. data/app/views/tasks/edit.rhtml +4 -4
  31. data/app/views/tasks/start_work.rjs +1 -1
  32. data/app/views/user/_edit.rhtml +1 -1
  33. data/app/views/user/change_password.rhtml +1 -1
  34. data/app/views/user/edit.rhtml +4 -4
  35. data/app/views/user/signup.rhtml +2 -2
  36. data/app/views/user_notify/{change_password_en.rhtml → change_password.en.html.erb} +0 -0
  37. data/app/views/user_notify/{change_password_no.rhtml → change_password.no.html.erb} +0 -0
  38. data/app/views/user_notify/{forgot_password_en.rhtml → forgot_password.en.html.erb} +0 -0
  39. data/app/views/user_notify/{forgot_password_no.rhtml → forgot_password.no.html.erb} +0 -0
  40. data/app/views/user_notify/{monitoring_en.rhtml → monitoring.en.html.erb} +0 -0
  41. data/app/views/user_notify/{monitoring_no.rhtml → monitoring.no.html.erb} +0 -0
  42. data/app/views/user_notify/{monitoring_invitation_en.rhtml → monitoring_invitation.en.html.erb} +0 -0
  43. data/app/views/user_notify/{monitoring_invitation_no.rhtml → monitoring_invitation.no.html.erb} +0 -0
  44. data/app/views/user_notify/{signup_en.rhtml → signup.en.html.erb} +0 -0
  45. data/app/views/user_notify/{signup_no.rhtml → signup.no.html.erb} +0 -0
  46. data/app/views/work_lock_notify/{lock_en.rhtml → lock.en.html.erb} +0 -0
  47. data/app/views/work_lock_notify/{lock_no.rhtml → lock.no.html.erb} +0 -0
  48. data/app/views/work_lock_notify/{nag_en.rhtml → nag.en.html.erb} +0 -0
  49. data/app/views/work_lock_notify/{nag_no.rhtml → nag.no.html.erb} +0 -0
  50. data/app/views/works/_form.rhtml +6 -6
  51. data/app/views/works/_new_row.rhtml +6 -6
  52. data/app/views/works/_row.rhtml +2 -2
  53. data/app/views/works/daily_work_sheet.rhtml +1 -1
  54. data/app/views/works/list.rhtml +6 -6
  55. data/app/views/works/list_excel.rhtml +8 -4
  56. data/app/views/works/timeliste.rhtml +14 -14
  57. data/app/views/works/update_row.rjs +1 -1
  58. data/app/views/works/weekly_work_sheet.rhtml +5 -5
  59. data/app/views/works/weekly_work_sheet_details.rhtml +5 -5
  60. data/config/boot.rb +108 -27
  61. data/config/database.yml +3 -26
  62. data/config/environment.rb +4 -12
  63. data/config/environments/development.rb +0 -1
  64. data/config/initializers/jdbc.rb +7 -0
  65. data/config/initializers/mongrel.rb +83 -0
  66. data/config/locales/en.yml +189 -0
  67. data/config/locales/no.yml +192 -0
  68. data/config/preinitializer.rb +20 -0
  69. data/cruise_build.sh +10 -0
  70. data/cruise_config.rb +1 -1
  71. data/db/migrate/20100720124707_merge_work_account_into_backlog.rb +74 -0
  72. data/db/schema.rb +93 -127
  73. data/lib/class_table_inheritance.rb +53 -11
  74. data/lib/tasks/jdbc.rake +8 -0
  75. data/lib/user_system.rb +5 -1
  76. data/public/javascripts/controls.js +76 -79
  77. data/public/javascripts/dragdrop.js +166 -167
  78. data/public/javascripts/effects.js +174 -168
  79. data/public/javascripts/prototype.js +470 -334
  80. data/public/stylesheets/mwrt002.css +6 -6
  81. data/script/dbconsole +3 -0
  82. data/test/fixtures/backlogs.yml +2 -2
  83. data/test/fixtures/work_lock_subscriptions.yml +2 -2
  84. data/test/fixtures/works.yml +6 -6
  85. data/test/functional/absences_controller_test.rb +1 -1
  86. data/test/functional/backlogs_controller_test.rb +4 -4
  87. data/test/functional/customers_controller_test.rb +1 -1
  88. data/test/functional/dashboard_controller_test.rb +1 -1
  89. data/test/functional/estimates_controller_test.rb +1 -1
  90. data/test/functional/groups_controller_test.rb +1 -1
  91. data/test/functional/parties_controller_test.rb +1 -1
  92. data/test/functional/periods_controller_test.rb +1 -1
  93. data/test/functional/public_holidays_controller_test.rb +1 -1
  94. data/test/functional/search_controller_test.rb +1 -1
  95. data/test/functional/task_files_controller_test.rb +1 -1
  96. data/test/functional/tasks_controller_test.rb +6 -6
  97. data/test/functional/user_controller_test.rb +3 -2
  98. data/test/functional/welcome_controller_test.rb +1 -1
  99. data/test/functional/work_locks_controller_test.rb +1 -1
  100. data/test/functional/works_controller_test.rb +11 -11
  101. data/test/test_helper.rb +2 -2
  102. data/test/unit/absence_test.rb +1 -1
  103. data/test/unit/configuration_test.rb +1 -1
  104. data/test/unit/customer_test.rb +1 -1
  105. data/test/unit/estimate_test.rb +1 -1
  106. data/test/unit/group_test.rb +1 -1
  107. data/test/unit/party_test.rb +1 -1
  108. data/test/unit/period_test.rb +1 -1
  109. data/test/unit/public_holiday_test.rb +1 -1
  110. data/test/unit/task_file_test.rb +1 -1
  111. data/test/unit/task_test.rb +1 -1
  112. data/test/unit/user_test.rb +1 -1
  113. data/test/unit/work_lock_subscription_test.rb +1 -1
  114. data/test/unit/work_lock_test.rb +1 -1
  115. data/test/unit/work_test.rb +8 -8
  116. data/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb +3 -3
  117. data/vendor/plugins/assert_cookie/lib/assert_cookie.rb +2 -2
  118. data/vendor/plugins/auto_complete/README +23 -0
  119. data/vendor/plugins/auto_complete/Rakefile +22 -0
  120. data/vendor/plugins/auto_complete/init.rb +2 -0
  121. data/vendor/plugins/auto_complete/lib/auto_complete.rb +47 -0
  122. data/vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb +143 -0
  123. data/vendor/plugins/auto_complete/test/auto_complete_test.rb +67 -0
  124. data/vendor/plugins/backlog_jira/init.rb +4 -0
  125. data/vendor/plugins/backlog_jira/{tasks → lib/tasks}/backlog_jira_tasks.rake +0 -0
  126. data/vendor/plugins/has_history/{tasks → lib/tasks}/has_history_tasks.rake +0 -0
  127. metadata +745 -817
  128. data/#SearchRequest.xml# +0 -3443
  129. data/app/controllers/application.rb~ +0 -207
  130. data/app/controllers/work_accounts_controller.rb +0 -58
  131. data/app/helpers/work_accounts_helper.rb +0 -2
  132. data/app/models/work_account.rb +0 -18
  133. data/app/models/work_lock_subscription.rb +0 -3
  134. data/app/views/work_accounts/_form.rhtml +0 -16
  135. data/app/views/work_accounts/_name_list.rhtml +0 -5
  136. data/app/views/work_accounts/_title.rhtml +0 -5
  137. data/app/views/work_accounts/edit.rhtml +0 -12
  138. data/app/views/work_accounts/list.rhtml +0 -31
  139. data/app/views/work_accounts/new.rhtml +0 -10
  140. data/app/views/work_accounts/show.rhtml +0 -50
  141. data/config/environments/localization_environment.rb +0 -10
  142. data/jira.log +0 -98246
  143. data/lang/en.yaml +0 -147
  144. data/lang/localizations.yaml +0 -2
  145. data/lang/no.yaml +0 -146
  146. data/lib/localization.rb +0 -88
  147. data/test/fixtures/work_accounts.yml +0 -7
  148. data/test/functional/work_accounts_controller_test.rb +0 -94
  149. data/test/unit/localization_test.rb +0 -47
  150. data/test/unit/work_account_test.rb +0 -10
@@ -1,10 +1,46 @@
1
+ require 'active_record'
2
+ require 'active_record/fixtures'
3
+
1
4
  # This library makes an ActiveRecord subclass model use one table per subclass level.
2
5
  # Instances are instances of the _super class_, with a proxy instance handling the subclass attributes
3
6
  # and method calls.
4
7
 
8
+ # I did get this file from someone else before modyfying it, but I cannot remember who.
9
+ # Credits go to whomever feels they deserve it :)
10
+
5
11
  class ActiveRecord::Base
6
12
  class_inheritable_array :default_eager_loading
7
13
 
14
+ # FIXME(uwe): Patch ActiveRecord::Base to accept an array of mixed symbols and strings
15
+ # FIXME(uwe): Works with ActiveRecord 2.3.8
16
+ def self.add_joins!(sql, joins, scope = :auto)
17
+ scope = scope(:find) if :auto == scope
18
+ merged_joins = scope && scope[:joins] && joins ? merge_joins(scope[:joins], joins) : (joins || scope && scope[:joins])
19
+ case merged_joins
20
+ when Symbol, Hash, Array
21
+
22
+ # BEGIN Original code
23
+ # if array_of_strings?(merged_joins)
24
+ # sql << merged_joins.join(' ') + " "
25
+ # else
26
+ # join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
27
+ # sql << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
28
+ # end
29
+ # END Original code
30
+
31
+ # BEGIN New code
32
+ if merged_joins.is_a?(Array)
33
+ merged_joins.delete_if { |join| sql << " #{join} " if join.is_a?(String) }
34
+ end
35
+ join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
36
+ sql << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
37
+ # END New code
38
+
39
+ when String
40
+ sql << " #{merged_joins} "
41
+ end
42
+ end
43
+
8
44
  class << self
9
45
  alias_method :has_one_without_cti, :has_one
10
46
 
@@ -16,9 +52,10 @@ class ActiveRecord::Base
16
52
  opts = {}
17
53
  params.push(opts)
18
54
  end
19
- opts[:include] ||= []
20
- opts[:include] = [opts[:include]] unless opts[:include].is_a?(Array)
21
- opts[:include] += default_eager_loading
55
+ opts[:joins] ||= []
56
+ opts[:joins] = [opts[:joins]] unless opts[:joins].is_a?(Array)
57
+ opts[:joins] += default_eager_loading
58
+ opts[:readonly] = false if opts[:readonly].nil?
22
59
  end
23
60
  find_without_default_eager_loading(*params)
24
61
  end
@@ -63,11 +100,10 @@ class ActiveRecord::Base
63
100
  if options[:save_before_superclass_callbacks] || true
64
101
  # We need the after_save filter for this association to run /before/ any other after_save's already registered on a superclass,
65
102
  # and before any after_creates or after_updates. This calls for some hackery:
66
- proxy_save_callback = @inheritable_attributes[:after_save].pop
67
- @inheritable_attributes[:after_create] ||= []
68
- @inheritable_attributes[:after_create].unshift(proxy_save_callback)
69
- @inheritable_attributes[:after_update] ||= []
70
- @inheritable_attributes[:after_update].unshift(proxy_save_callback)
103
+
104
+ proxy_save_callback = after_save_callback_chain.pop
105
+ after_create_callback_chain.unshift(proxy_save_callback)
106
+ after_update_callback_chain.unshift(proxy_save_callback)
71
107
  end
72
108
 
73
109
  # adds this to the class-inheritable array of default eager loads:
@@ -106,7 +142,7 @@ class ActiveRecord::Base
106
142
  def method_missing(method_symbol, *parameters)
107
143
  if method_symbol.to_s =~ /^find_by_(.+)/
108
144
  attributes = $1.split('_and_')
109
- super_attributes = attributes & columns.map {|c| c.name}
145
+ super_attributes = attributes & columns.map{|c| c.name}
110
146
  sub_attributes = attributes - super_attributes
111
147
  if super_attributes.size > 0
112
148
  # TODO (uwe): Only use super attributes first
@@ -128,7 +164,7 @@ class ActiveRecord::Base
128
164
  method_missing_super(method_symbol, *parameters)
129
165
  end
130
166
  end
131
- # TODO (uwe): validates_uniqueness_of should only be delegated for colimns not in super class???
167
+ # TODO (uwe): validates_uniqueness_of should only be delegated for columns not in super class???
132
168
  delegate :validates_uniqueness_of, {:to => #{proxy_class_name}}
133
169
 
134
170
  delegate :foreign_keys, {:to => #{proxy_class_name}}
@@ -178,4 +214,10 @@ class ActiveRecord::Base
178
214
  end
179
215
  end
180
216
  end
181
- end
217
+ end
218
+
219
+ class Fixtures
220
+ def primary_key_name
221
+ @connection.primary_key(@table_name)
222
+ end
223
+ end
@@ -0,0 +1,8 @@
1
+ # This file was generated by the "jdbc" generator, which is provided
2
+ # by the activerecord-jdbc-adapter gem.
3
+ #
4
+ # This file allows you to use Rails' various db:* tasks with JDBC.
5
+ if defined?(JRUBY_VERSION)
6
+ require 'jdbc_adapter'
7
+ require 'jdbc_adapter/rake_tasks'
8
+ end
@@ -49,6 +49,8 @@ module UserSystem
49
49
  cookies[:autologin]
50
50
  when Hash:
51
51
  cookies[:autologin][:value].first
52
+ when CGI::Cookie
53
+ cookies[:autologin].first[:value].first
52
54
  else
53
55
  raise "Unknown cookie class: #{cookie.class}"
54
56
  end
@@ -57,6 +59,8 @@ module UserSystem
57
59
  cookies[:token]
58
60
  when Hash:
59
61
  cookies[:token][:value].first
62
+ when CGI::Cookie
63
+ cookies[:token].first[:value].first
60
64
  else
61
65
  raise "Unknown cookie class: #{cookie.class}"
62
66
  end
@@ -87,7 +91,7 @@ module UserSystem
87
91
  end
88
92
 
89
93
  def current_user= user
90
- session[:user_id] = user && user.id if @session
94
+ session[:user_id] = user && user.id if self.respond_to?(:session)
91
95
  Thread.current[:user] = user
92
96
  end
93
97
 
@@ -1,24 +1,22 @@
1
- // script.aculo.us controls.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
2
-
3
- // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
- // (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
5
- // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
1
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
+ // (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
3
+ // (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
6
4
  // Contributors:
7
5
  // Richard Livsey
8
6
  // Rahul Bhargava
9
7
  // Rob Wills
10
- //
8
+ //
11
9
  // script.aculo.us is freely distributable under the terms of an MIT-style license.
12
10
  // For details, see the script.aculo.us web site: http://script.aculo.us/
13
11
 
14
- // Autocompleter.Base handles all the autocompletion functionality
12
+ // Autocompleter.Base handles all the autocompletion functionality
15
13
  // that's independent of the data source for autocompletion. This
16
14
  // includes drawing the autocompletion menu, observing keyboard
17
15
  // and mouse events, and similar.
18
16
  //
19
- // Specific autocompleters need to provide, at the very least,
17
+ // Specific autocompleters need to provide, at the very least,
20
18
  // a getUpdatedChoices function that will be invoked every time
21
- // the text inside the monitored textbox changes. This method
19
+ // the text inside the monitored textbox changes. This method
22
20
  // should get the text for which to provide autocompletion by
23
21
  // invoking this.getToken(), NOT by directly accessing
24
22
  // this.element.value. This is to allow incremental tokenized
@@ -32,23 +30,23 @@
32
30
  // will incrementally autocomplete with a comma as the token.
33
31
  // Additionally, ',' in the above example can be replaced with
34
32
  // a token array, e.g. { tokens: [',', '\n'] } which
35
- // enables autocompletion on multiple tokens. This is most
36
- // useful when one of the tokens is \n (a newline), as it
33
+ // enables autocompletion on multiple tokens. This is most
34
+ // useful when one of the tokens is \n (a newline), as it
37
35
  // allows smart autocompletion after linebreaks.
38
36
 
39
37
  if(typeof Effect == 'undefined')
40
38
  throw("controls.js requires including script.aculo.us' effects.js library");
41
39
 
42
- var Autocompleter = { }
40
+ var Autocompleter = { };
43
41
  Autocompleter.Base = Class.create({
44
42
  baseInitialize: function(element, update, options) {
45
- element = $(element)
46
- this.element = element;
47
- this.update = $(update);
48
- this.hasFocus = false;
49
- this.changed = false;
50
- this.active = false;
51
- this.index = 0;
43
+ element = $(element);
44
+ this.element = element;
45
+ this.update = $(update);
46
+ this.hasFocus = false;
47
+ this.changed = false;
48
+ this.active = false;
49
+ this.index = 0;
52
50
  this.entryCount = 0;
53
51
  this.oldElementValue = this.element.value;
54
52
 
@@ -61,42 +59,42 @@ Autocompleter.Base = Class.create({
61
59
  this.options.tokens = this.options.tokens || [];
62
60
  this.options.frequency = this.options.frequency || 0.4;
63
61
  this.options.minChars = this.options.minChars || 1;
64
- this.options.onShow = this.options.onShow ||
65
- function(element, update){
62
+ this.options.onShow = this.options.onShow ||
63
+ function(element, update){
66
64
  if(!update.style.position || update.style.position=='absolute') {
67
65
  update.style.position = 'absolute';
68
66
  Position.clone(element, update, {
69
- setHeight: false,
67
+ setHeight: false,
70
68
  offsetTop: element.offsetHeight
71
69
  });
72
70
  }
73
71
  Effect.Appear(update,{duration:0.15});
74
72
  };
75
- this.options.onHide = this.options.onHide ||
73
+ this.options.onHide = this.options.onHide ||
76
74
  function(element, update){ new Effect.Fade(update,{duration:0.15}) };
77
75
 
78
- if(typeof(this.options.tokens) == 'string')
76
+ if(typeof(this.options.tokens) == 'string')
79
77
  this.options.tokens = new Array(this.options.tokens);
80
78
  // Force carriage returns as token delimiters anyway
81
79
  if (!this.options.tokens.include('\n'))
82
80
  this.options.tokens.push('\n');
83
81
 
84
82
  this.observer = null;
85
-
83
+
86
84
  this.element.setAttribute('autocomplete','off');
87
85
 
88
86
  Element.hide(this.update);
89
87
 
90
88
  Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
91
- Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));
89
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
92
90
  },
93
91
 
94
92
  show: function() {
95
93
  if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
96
- if(!this.iefix &&
94
+ if(!this.iefix &&
97
95
  (Prototype.Browser.IE) &&
98
96
  (Element.getStyle(this.update, 'position')=='absolute')) {
99
- new Insertion.After(this.update,
97
+ new Insertion.After(this.update,
100
98
  '<iframe id="' + this.update.id + '_iefix" '+
101
99
  'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
102
100
  'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
@@ -104,7 +102,7 @@ Autocompleter.Base = Class.create({
104
102
  }
105
103
  if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
106
104
  },
107
-
105
+
108
106
  fixIEOverlapping: function() {
109
107
  Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
110
108
  this.iefix.style.zIndex = 1;
@@ -130,7 +128,6 @@ Autocompleter.Base = Class.create({
130
128
  if(this.active)
131
129
  switch(event.keyCode) {
132
130
  case Event.KEY_TAB:
133
- return;
134
131
  case Event.KEY_RETURN:
135
132
  this.selectEntry();
136
133
  Event.stop(event);
@@ -145,23 +142,23 @@ Autocompleter.Base = Class.create({
145
142
  case Event.KEY_UP:
146
143
  this.markPrevious();
147
144
  this.render();
148
- if(Prototype.Browser.WebKit) Event.stop(event);
145
+ Event.stop(event);
149
146
  return;
150
147
  case Event.KEY_DOWN:
151
148
  this.markNext();
152
149
  this.render();
153
- if(Prototype.Browser.WebKit) Event.stop(event);
150
+ Event.stop(event);
154
151
  return;
155
152
  }
156
- else
157
- if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
153
+ else
154
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
158
155
  (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
159
156
 
160
157
  this.changed = true;
161
158
  this.hasFocus = true;
162
159
 
163
160
  if(this.observer) clearTimeout(this.observer);
164
- this.observer =
161
+ this.observer =
165
162
  setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
166
163
  },
167
164
 
@@ -173,35 +170,35 @@ Autocompleter.Base = Class.create({
173
170
 
174
171
  onHover: function(event) {
175
172
  var element = Event.findElement(event, 'LI');
176
- if(this.index != element.autocompleteIndex)
173
+ if(this.index != element.autocompleteIndex)
177
174
  {
178
175
  this.index = element.autocompleteIndex;
179
176
  this.render();
180
177
  }
181
178
  Event.stop(event);
182
179
  },
183
-
180
+
184
181
  onClick: function(event) {
185
182
  var element = Event.findElement(event, 'LI');
186
183
  this.index = element.autocompleteIndex;
187
184
  this.selectEntry();
188
185
  this.hide();
189
186
  },
190
-
187
+
191
188
  onBlur: function(event) {
192
189
  // needed to make click events working
193
190
  setTimeout(this.hide.bind(this), 250);
194
191
  this.hasFocus = false;
195
- this.active = false;
196
- },
197
-
192
+ this.active = false;
193
+ },
194
+
198
195
  render: function() {
199
196
  if(this.entryCount > 0) {
200
197
  for (var i = 0; i < this.entryCount; i++)
201
- this.index==i ?
202
- Element.addClassName(this.getEntry(i),"selected") :
198
+ this.index==i ?
199
+ Element.addClassName(this.getEntry(i),"selected") :
203
200
  Element.removeClassName(this.getEntry(i),"selected");
204
- if(this.hasFocus) {
201
+ if(this.hasFocus) {
205
202
  this.show();
206
203
  this.active = true;
207
204
  }
@@ -210,27 +207,27 @@ Autocompleter.Base = Class.create({
210
207
  this.hide();
211
208
  }
212
209
  },
213
-
210
+
214
211
  markPrevious: function() {
215
- if(this.index > 0) this.index--
212
+ if(this.index > 0) this.index--;
216
213
  else this.index = this.entryCount-1;
217
214
  this.getEntry(this.index).scrollIntoView(true);
218
215
  },
219
-
216
+
220
217
  markNext: function() {
221
- if(this.index < this.entryCount-1) this.index++
218
+ if(this.index < this.entryCount-1) this.index++;
222
219
  else this.index = 0;
223
220
  this.getEntry(this.index).scrollIntoView(false);
224
221
  },
225
-
222
+
226
223
  getEntry: function(index) {
227
224
  return this.update.firstChild.childNodes[index];
228
225
  },
229
-
226
+
230
227
  getCurrentEntry: function() {
231
228
  return this.getEntry(this.index);
232
229
  },
233
-
230
+
234
231
  selectEntry: function() {
235
232
  this.active = false;
236
233
  this.updateElement(this.getCurrentEntry());
@@ -247,7 +244,7 @@ Autocompleter.Base = Class.create({
247
244
  if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
248
245
  } else
249
246
  value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
250
-
247
+
251
248
  var bounds = this.getTokenBounds();
252
249
  if (bounds[0] != -1) {
253
250
  var newValue = this.element.value.substr(0, bounds[0]);
@@ -260,7 +257,7 @@ Autocompleter.Base = Class.create({
260
257
  }
261
258
  this.oldElementValue = this.element.value;
262
259
  this.element.focus();
263
-
260
+
264
261
  if (this.options.afterUpdateElement)
265
262
  this.options.afterUpdateElement(this.element, selectedElement);
266
263
  },
@@ -272,20 +269,20 @@ Autocompleter.Base = Class.create({
272
269
  Element.cleanWhitespace(this.update.down());
273
270
 
274
271
  if(this.update.firstChild && this.update.down().childNodes) {
275
- this.entryCount =
272
+ this.entryCount =
276
273
  this.update.down().childNodes.length;
277
274
  for (var i = 0; i < this.entryCount; i++) {
278
275
  var entry = this.getEntry(i);
279
276
  entry.autocompleteIndex = i;
280
277
  this.addObservers(entry);
281
278
  }
282
- } else {
279
+ } else {
283
280
  this.entryCount = 0;
284
281
  }
285
282
 
286
283
  this.stopIndicator();
287
284
  this.index = 0;
288
-
285
+
289
286
  if(this.entryCount==1 && this.options.autoSelect) {
290
287
  this.selectEntry();
291
288
  this.hide();
@@ -301,7 +298,7 @@ Autocompleter.Base = Class.create({
301
298
  },
302
299
 
303
300
  onObserverEvent: function() {
304
- this.changed = false;
301
+ this.changed = false;
305
302
  this.tokenBounds = null;
306
303
  if(this.getToken().length>=this.options.minChars) {
307
304
  this.getUpdatedChoices();
@@ -354,16 +351,16 @@ Ajax.Autocompleter = Class.create(Autocompleter.Base, {
354
351
 
355
352
  getUpdatedChoices: function() {
356
353
  this.startIndicator();
357
-
358
- var entry = encodeURIComponent(this.options.paramName) + '=' +
354
+
355
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
359
356
  encodeURIComponent(this.getToken());
360
357
 
361
358
  this.options.parameters = this.options.callback ?
362
359
  this.options.callback(this.element, entry) : entry;
363
360
 
364
- if(this.options.defaultParams)
361
+ if(this.options.defaultParams)
365
362
  this.options.parameters += '&' + this.options.defaultParams;
366
-
363
+
367
364
  new Ajax.Request(this.url, this.options);
368
365
  },
369
366
 
@@ -385,7 +382,7 @@ Ajax.Autocompleter = Class.create(Autocompleter.Base, {
385
382
  // - choices - How many autocompletion choices to offer
386
383
  //
387
384
  // - partialSearch - If false, the autocompleter will match entered
388
- // text only at the beginning of strings in the
385
+ // text only at the beginning of strings in the
389
386
  // autocomplete array. Defaults to true, which will
390
387
  // match text at the beginning of any *word* in the
391
388
  // strings in the autocomplete array. If you want to
@@ -402,7 +399,7 @@ Ajax.Autocompleter = Class.create(Autocompleter.Base, {
402
399
  // - ignoreCase - Whether to ignore case when autocompleting.
403
400
  // Defaults to true.
404
401
  //
405
- // It's possible to pass in a custom function as the 'selector'
402
+ // It's possible to pass in a custom function as the 'selector'
406
403
  // option, if you prefer to write your own autocompletion logic.
407
404
  // In that case, the other options above will not apply unless
408
405
  // you support them.
@@ -430,20 +427,20 @@ Autocompleter.Local = Class.create(Autocompleter.Base, {
430
427
  var entry = instance.getToken();
431
428
  var count = 0;
432
429
 
433
- for (var i = 0; i < instance.options.array.length &&
434
- ret.length < instance.options.choices ; i++) {
430
+ for (var i = 0; i < instance.options.array.length &&
431
+ ret.length < instance.options.choices ; i++) {
435
432
 
436
433
  var elem = instance.options.array[i];
437
- var foundPos = instance.options.ignoreCase ?
438
- elem.toLowerCase().indexOf(entry.toLowerCase()) :
434
+ var foundPos = instance.options.ignoreCase ?
435
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
439
436
  elem.indexOf(entry);
440
437
 
441
438
  while (foundPos != -1) {
442
- if (foundPos == 0 && elem.length != entry.length) {
443
- ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
439
+ if (foundPos == 0 && elem.length != entry.length) {
440
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
444
441
  elem.substr(entry.length) + "</li>");
445
442
  break;
446
- } else if (entry.length >= instance.options.partialChars &&
443
+ } else if (entry.length >= instance.options.partialChars &&
447
444
  instance.options.partialSearch && foundPos != -1) {
448
445
  if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
449
446
  partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
@@ -453,14 +450,14 @@ Autocompleter.Local = Class.create(Autocompleter.Base, {
453
450
  }
454
451
  }
455
452
 
456
- foundPos = instance.options.ignoreCase ?
457
- elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
453
+ foundPos = instance.options.ignoreCase ?
454
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
458
455
  elem.indexOf(entry, foundPos + 1);
459
456
 
460
457
  }
461
458
  }
462
459
  if (partial.length)
463
- ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
460
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
464
461
  return "<ul>" + ret.join('') + "</ul>";
465
462
  }
466
463
  }, options || { });
@@ -477,7 +474,7 @@ Field.scrollFreeActivate = function(field) {
477
474
  setTimeout(function() {
478
475
  Field.activate(field);
479
476
  }, 1);
480
- }
477
+ };
481
478
 
482
479
  Ajax.InPlaceEditor = Class.create({
483
480
  initialize: function(element, url, options) {
@@ -607,7 +604,7 @@ Ajax.InPlaceEditor = Class.create({
607
604
  this.triggerCallback('onEnterHover');
608
605
  },
609
606
  getText: function() {
610
- return this.element.innerHTML;
607
+ return this.element.innerHTML.unescapeHTML();
611
608
  },
612
609
  handleAJAXFailure: function(transport) {
613
610
  this.triggerCallback('onFailure', transport);
@@ -783,7 +780,7 @@ Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
783
780
  onSuccess: function(transport) {
784
781
  var js = transport.responseText.strip();
785
782
  if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
786
- throw 'Server returned an invalid collection representation.';
783
+ throw('Server returned an invalid collection representation.');
787
784
  this._collection = eval(js);
788
785
  this.checkForExternalText();
789
786
  }.bind(this),
@@ -940,7 +937,7 @@ Ajax.InPlaceCollectionEditor.DefaultOptions = {
940
937
  loadingCollectionText: 'Loading options...'
941
938
  };
942
939
 
943
- // Delayed observer, like Form.Element.Observer,
940
+ // Delayed observer, like Form.Element.Observer,
944
941
  // but waits for delay after last key input
945
942
  // Ideal for live-search fields
946
943
 
@@ -950,7 +947,7 @@ Form.Element.DelayedObserver = Class.create({
950
947
  this.element = $(element);
951
948
  this.callback = callback;
952
949
  this.timer = null;
953
- this.lastValue = $F(this.element);
950
+ this.lastValue = $F(this.element);
954
951
  Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
955
952
  },
956
953
  delayedListener: function(event) {
@@ -963,4 +960,4 @@ Form.Element.DelayedObserver = Class.create({
963
960
  this.timer = null;
964
961
  this.callback(this.element, $F(this.element));
965
962
  }
966
- });
963
+ });