backlog 0.35.5 → 0.36.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ });