radiant 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of radiant might be problematic. Click here for more details.

Files changed (197) hide show
  1. data/CHANGELOG +61 -7
  2. data/CONTRIBUTORS +15 -0
  3. data/app/controllers/admin/export_controller.rb +1 -1
  4. data/app/controllers/admin/page_controller.rb +1 -0
  5. data/app/controllers/admin/user_controller.rb +2 -1
  6. data/app/controllers/application.rb +7 -8
  7. data/app/helpers/admin/node_helper.rb +84 -0
  8. data/app/helpers/admin/page_helper.rb +1 -19
  9. data/app/helpers/application_helper.rb +15 -9
  10. data/app/models/file_not_found_page.rb +2 -2
  11. data/app/models/page.rb +22 -18
  12. data/app/models/page_context.rb +9 -0
  13. data/app/models/radiant/config.rb +4 -2
  14. data/app/models/response_cache.rb +18 -12
  15. data/app/models/standard_tags.rb +111 -50
  16. data/app/views/admin/extension/index.rhtml +2 -2
  17. data/app/views/admin/layout/edit.rhtml +2 -2
  18. data/app/views/admin/layout/remove.rhtml +2 -2
  19. data/app/views/admin/page/_node.rhtml +4 -26
  20. data/app/views/admin/page/_part.rhtml +9 -14
  21. data/app/views/admin/page/edit.rhtml +38 -121
  22. data/app/views/admin/page/index.rhtml +2 -6
  23. data/app/views/admin/page/remove.rhtml +2 -2
  24. data/app/views/admin/snippet/edit.rhtml +3 -3
  25. data/app/views/admin/snippet/index.rhtml +2 -2
  26. data/app/views/admin/snippet/remove.rhtml +2 -2
  27. data/app/views/admin/user/edit.rhtml +4 -4
  28. data/app/views/admin/user/preferences.rhtml +2 -2
  29. data/app/views/admin/welcome/login.rhtml +1 -1
  30. data/config/environment.rb +79 -78
  31. data/db/schema.rb +2 -0
  32. data/lib/local_time.rb +12 -0
  33. data/lib/plugins/extension_patches/lib/fixture_loading_extension.rb +1 -1
  34. data/lib/plugins/extension_patches/lib/mailer_view_paths_extension.rb +3 -3
  35. data/lib/radiant.rb +1 -1
  36. data/lib/radiant/extension.rb +9 -3
  37. data/lib/radiant/extension_loader.rb +2 -2
  38. data/lib/tasks/extensions.rake +23 -8
  39. data/public/javascripts/admin.js +89 -0
  40. data/public/javascripts/controls.js +486 -354
  41. data/public/javascripts/dragdrop.js +90 -58
  42. data/public/javascripts/effects.js +398 -364
  43. data/public/javascripts/pngfix.js +37 -37
  44. data/public/javascripts/prototype.js +2764 -1095
  45. data/public/javascripts/ruledtable.js +10 -25
  46. data/public/javascripts/sitemap.js +74 -112
  47. data/public/javascripts/string.js +1 -7
  48. data/public/javascripts/tabcontrol.js +71 -86
  49. data/public/javascripts/tag_reference_search.js +19 -26
  50. data/public/stylesheets/admin/main.css +11 -5
  51. data/test/fixtures/extensions/01_basic/lib/new_module.rb +2 -0
  52. data/test/fixtures/page_parts.yml +16 -1
  53. data/test/fixtures/pages.yml +47 -84
  54. data/test/functional/extension_initialization_test.rb +11 -0
  55. data/test/helpers/login_test_helper.rb +12 -1
  56. data/test/helpers/page_test_helper.rb +6 -0
  57. data/test/helpers/render_test_helper.rb +11 -8
  58. data/test/test_helper.rb +1 -12
  59. data/test/unit/file_not_found_page_test.rb +5 -1
  60. data/test/unit/local_time_test.rb +45 -0
  61. data/test/unit/page_context_test.rb +32 -1
  62. data/test/unit/page_test.rb +45 -11
  63. data/test/unit/radiant/config_test.rb +1 -1
  64. data/test/unit/response_cache_test.rb +27 -2
  65. data/test/unit/standard_tags_test.rb +60 -15
  66. data/vendor/extensions/archive/README +29 -0
  67. data/vendor/extensions/archive/Rakefile +25 -0
  68. data/{app → vendor/extensions/archive/app}/models/archive_day_index_page.rb +0 -0
  69. data/{app → vendor/extensions/archive/app}/models/archive_finder.rb +8 -6
  70. data/{app → vendor/extensions/archive/app}/models/archive_month_index_page.rb +0 -0
  71. data/{app → vendor/extensions/archive/app}/models/archive_page.rb +0 -0
  72. data/{app → vendor/extensions/archive/app}/models/archive_year_index_page.rb +0 -0
  73. data/vendor/extensions/archive/archive_extension.rb +19 -0
  74. data/{lib → vendor/extensions/archive/lib}/archive_index_tags_and_methods.rb +0 -0
  75. data/vendor/extensions/archive/lib/tasks/archive_extension_tasks.rake +28 -0
  76. data/vendor/extensions/archive/test/fixtures/pages.yml +397 -0
  77. data/vendor/extensions/archive/test/functional/archive_extension_test.rb +16 -0
  78. data/{test → vendor/extensions/archive/test}/helpers/archive_index_test_helper.rb +0 -0
  79. data/vendor/extensions/archive/test/test_helper.rb +19 -0
  80. data/{test → vendor/extensions/archive/test}/unit/archive_day_index_page_test.rb +0 -0
  81. data/{test → vendor/extensions/archive/test}/unit/archive_month_index_page_test.rb +0 -0
  82. data/{test → vendor/extensions/archive/test}/unit/archive_page_test.rb +7 -1
  83. data/{test → vendor/extensions/archive/test}/unit/archive_year_index_page_test.rb +0 -0
  84. data/vendor/rails/actionmailer/CHANGELOG +10 -0
  85. data/vendor/rails/actionmailer/Rakefile +1 -1
  86. data/vendor/rails/actionmailer/lib/action_mailer/version.rb +1 -1
  87. data/vendor/rails/actionpack/CHANGELOG +51 -2
  88. data/vendor/rails/actionpack/Rakefile +1 -1
  89. data/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb +2 -2
  90. data/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb +1 -1
  91. data/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb +3 -0
  92. data/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb +1 -0
  93. data/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb +2 -0
  94. data/vendor/rails/actionpack/lib/action_controller/base.rb +7 -1
  95. data/vendor/rails/actionpack/lib/action_controller/caching.rb +39 -38
  96. data/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb +30 -0
  97. data/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb +1 -1
  98. data/vendor/rails/actionpack/lib/action_controller/cgi_process.rb +13 -4
  99. data/vendor/rails/actionpack/lib/action_controller/cookies.rb +5 -3
  100. data/vendor/rails/actionpack/lib/action_controller/filters.rb +176 -77
  101. data/vendor/rails/actionpack/lib/action_controller/integration.rb +31 -21
  102. data/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb +1 -1
  103. data/vendor/rails/actionpack/lib/action_controller/pagination.rb +7 -1
  104. data/vendor/rails/actionpack/lib/action_controller/resources.rb +117 -32
  105. data/vendor/rails/actionpack/lib/action_controller/routing.rb +56 -23
  106. data/vendor/rails/actionpack/lib/action_controller/test_process.rb +5 -2
  107. data/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb +4 -1
  108. data/vendor/rails/actionpack/lib/action_controller/verification.rb +1 -0
  109. data/vendor/rails/actionpack/lib/action_pack/version.rb +1 -1
  110. data/vendor/rails/actionpack/lib/action_view/base.rb +25 -19
  111. data/vendor/rails/actionpack/lib/action_view/compiled_templates.rb +2 -2
  112. data/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb +18 -18
  113. data/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb +10 -0
  114. data/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb +3 -0
  115. data/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb +33 -17
  116. data/vendor/rails/actionpack/test/activerecord/pagination_test.rb +9 -0
  117. data/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb +13 -0
  118. data/vendor/rails/actionpack/test/controller/addresses_render_test.rb +4 -1
  119. data/vendor/rails/actionpack/test/controller/base_test.rb +1 -1
  120. data/vendor/rails/actionpack/test/controller/caching_test.rb +3 -2
  121. data/vendor/rails/actionpack/test/controller/cookie_test.rb +11 -0
  122. data/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb +18 -0
  123. data/vendor/rails/actionpack/test/controller/filter_params_test.rb +1 -0
  124. data/vendor/rails/actionpack/test/controller/filters_test.rb +149 -26
  125. data/vendor/rails/actionpack/test/controller/integration_test.rb +93 -8
  126. data/vendor/rails/actionpack/test/controller/resources_test.rb +215 -36
  127. data/vendor/rails/actionpack/test/controller/routing_test.rb +2 -2
  128. data/vendor/rails/actionpack/test/controller/test_test.rb +16 -0
  129. data/vendor/rails/actionpack/test/controller/url_rewriter_test.rb +66 -10
  130. data/vendor/rails/actionpack/test/controller/verification_test.rb +15 -0
  131. data/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml +2 -1
  132. data/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb +5 -0
  133. data/vendor/rails/actionpack/test/template/compiled_templates_test.rb +29 -17
  134. data/vendor/rails/actionpack/test/template/javascript_helper_test.rb +4 -4
  135. data/vendor/rails/actionpack/test/template/number_helper_test.rb +1 -1
  136. data/vendor/rails/actionpack/test/template/prototype_helper_test.rb +13 -13
  137. data/vendor/rails/actionwebservice/CHANGELOG +14 -0
  138. data/vendor/rails/actionwebservice/Rakefile +2 -2
  139. data/vendor/rails/actionwebservice/lib/action_web_service/version.rb +1 -1
  140. data/vendor/rails/activerecord/CHANGELOG +34 -0
  141. data/vendor/rails/activerecord/Rakefile +1 -1
  142. data/vendor/rails/activerecord/lib/active_record/acts/list.rb +14 -2
  143. data/vendor/rails/activerecord/lib/active_record/acts/tree.rb +7 -0
  144. data/vendor/rails/activerecord/lib/active_record/associations.rb +29 -14
  145. data/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb +5 -1
  146. data/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb +2 -2
  147. data/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb +10 -0
  148. data/vendor/rails/activerecord/lib/active_record/base.rb +12 -3
  149. data/vendor/rails/activerecord/lib/active_record/calculations.rb +2 -2
  150. data/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  151. data/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  152. data/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
  153. data/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb +54 -38
  154. data/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb +3 -3
  155. data/vendor/rails/activerecord/lib/active_record/fixtures.rb +1 -1
  156. data/vendor/rails/activerecord/lib/active_record/timestamp.rb +0 -9
  157. data/vendor/rails/activerecord/lib/active_record/version.rb +1 -1
  158. data/vendor/rails/activerecord/test/associations/eager_test.rb +13 -0
  159. data/vendor/rails/activerecord/test/associations/join_model_test.rb +10 -1
  160. data/vendor/rails/activerecord/test/associations_test.rb +36 -3
  161. data/vendor/rails/activerecord/test/base_test.rb +17 -4
  162. data/vendor/rails/activerecord/test/defaults_test.rb +15 -0
  163. data/vendor/rails/activerecord/test/fixtures/author.rb +1 -0
  164. data/vendor/rails/activerecord/test/fixtures/binaries.yml +437 -0
  165. data/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb +13 -0
  166. data/vendor/rails/activerecord/test/fixtures/developer.rb +10 -0
  167. data/vendor/rails/activerecord/test/fixtures_test.rb +9 -5
  168. data/vendor/rails/activerecord/test/migration_test.rb +9 -10
  169. data/vendor/rails/activerecord/test/mixin_test.rb +47 -0
  170. data/vendor/rails/activerecord/test/validations_test.rb +2 -2
  171. data/vendor/rails/activesupport/CHANGELOG +16 -0
  172. data/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb +9 -3
  173. data/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb +48 -3
  174. data/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb +14 -0
  175. data/vendor/rails/activesupport/lib/active_support/dependencies.rb +3 -3
  176. data/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb +5 -3
  177. data/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb +6 -6
  178. data/vendor/rails/activesupport/lib/active_support/version.rb +1 -1
  179. data/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb +37 -0
  180. data/vendor/rails/activesupport/test/core_ext/module_test.rb +8 -0
  181. data/vendor/rails/activesupport/test/dependencies_test.rb +11 -0
  182. data/vendor/rails/activesupport/test/{json.rb → json_test.rb} +15 -5
  183. data/vendor/rails/railties/CHANGELOG +25 -1
  184. data/vendor/rails/railties/README +32 -3
  185. data/vendor/rails/railties/Rakefile +5 -5
  186. data/vendor/rails/railties/environments/boot.rb +12 -18
  187. data/vendor/rails/railties/environments/environment.rb +15 -15
  188. data/vendor/rails/railties/lib/dispatcher.rb +1 -2
  189. data/vendor/rails/railties/lib/initializer.rb +33 -9
  190. data/vendor/rails/railties/lib/rails/version.rb +1 -1
  191. data/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +1 -1
  192. data/vendor/rails/railties/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb +1 -0
  193. data/vendor/rails/railties/lib/railties_path.rb +1 -1
  194. data/vendor/rails/railties/lib/tasks/framework.rake +4 -4
  195. data/vendor/rails/railties/lib/tasks/routes.rake +17 -0
  196. data/vendor/rails/release.rb +2 -2
  197. metadata +1877 -1848
@@ -1,10 +1,12 @@
1
- // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
- // (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
1
+ // script.aculo.us dragdrop.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 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
3
5
  //
4
6
  // script.aculo.us is freely distributable under the terms of an MIT-style license.
5
7
  // For details, see the script.aculo.us web site: http://script.aculo.us/
6
8
 
7
- if(typeof Effect == 'undefined')
9
+ if(Object.isUndefined(Effect))
8
10
  throw("dragdrop.js requires including script.aculo.us' effects.js library");
9
11
 
10
12
  var Droppables = {
@@ -20,14 +22,13 @@ var Droppables = {
20
22
  greedy: true,
21
23
  hoverclass: null,
22
24
  tree: false
23
- }, arguments[1] || {});
25
+ }, arguments[1] || { });
24
26
 
25
27
  // cache containers
26
28
  if(options.containment) {
27
29
  options._containers = [];
28
30
  var containment = options.containment;
29
- if((typeof containment == 'object') &&
30
- (containment.constructor == Array)) {
31
+ if(Object.isArray(containment)) {
31
32
  containment.each( function(c) { options._containers.push($(c)) });
32
33
  } else {
33
34
  options._containers.push($(containment));
@@ -87,21 +88,23 @@ var Droppables = {
87
88
 
88
89
  show: function(point, element) {
89
90
  if(!this.drops.length) return;
90
- var affected = [];
91
+ var drop, affected = [];
91
92
 
92
- if(this.last_active) this.deactivate(this.last_active);
93
93
  this.drops.each( function(drop) {
94
94
  if(Droppables.isAffected(point, element, drop))
95
95
  affected.push(drop);
96
96
  });
97
97
 
98
- if(affected.length>0) {
98
+ if(affected.length>0)
99
99
  drop = Droppables.findDeepestChild(affected);
100
+
101
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
102
+ if (drop) {
100
103
  Position.within(drop.element, point[0], point[1]);
101
104
  if(drop.onHover)
102
105
  drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
103
106
 
104
- Droppables.activate(drop);
107
+ if (drop != this.last_active) Droppables.activate(drop);
105
108
  }
106
109
  },
107
110
 
@@ -110,8 +113,10 @@ var Droppables = {
110
113
  Position.prepare();
111
114
 
112
115
  if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
113
- if (this.last_active.onDrop)
114
- this.last_active.onDrop(element, this.last_active.element, event);
116
+ if (this.last_active.onDrop) {
117
+ this.last_active.onDrop(element, this.last_active.element, event);
118
+ return true;
119
+ }
115
120
  },
116
121
 
117
122
  reset: function() {
@@ -219,10 +224,7 @@ var Draggables = {
219
224
 
220
225
  /*--------------------------------------------------------------------------*/
221
226
 
222
- var Draggable = Class.create();
223
- Draggable._dragging = {};
224
-
225
- Draggable.prototype = {
227
+ var Draggable = Class.create({
226
228
  initialize: function(element) {
227
229
  var defaults = {
228
230
  handle: false,
@@ -233,7 +235,7 @@ Draggable.prototype = {
233
235
  });
234
236
  },
235
237
  endeffect: function(element) {
236
- var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
238
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
237
239
  new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
238
240
  queue: {scope:'_draggable', position:'end'},
239
241
  afterFinish: function(){
@@ -243,6 +245,7 @@ Draggable.prototype = {
243
245
  },
244
246
  zindex: 1000,
245
247
  revert: false,
248
+ quiet: false,
246
249
  scroll: false,
247
250
  scrollSensitivity: 20,
248
251
  scrollSpeed: 15,
@@ -250,7 +253,7 @@ Draggable.prototype = {
250
253
  delay: 0
251
254
  };
252
255
 
253
- if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
256
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
254
257
  Object.extend(defaults, {
255
258
  starteffect: function(element) {
256
259
  element._opacity = Element.getOpacity(element);
@@ -259,11 +262,11 @@ Draggable.prototype = {
259
262
  }
260
263
  });
261
264
 
262
- var options = Object.extend(defaults, arguments[1] || {});
265
+ var options = Object.extend(defaults, arguments[1] || { });
263
266
 
264
267
  this.element = $(element);
265
268
 
266
- if(options.handle && (typeof options.handle == 'string'))
269
+ if(options.handle && Object.isString(options.handle))
267
270
  this.handle = this.element.down('.'+options.handle, 0);
268
271
 
269
272
  if(!this.handle) this.handle = $(options.handle);
@@ -276,7 +279,6 @@ Draggable.prototype = {
276
279
 
277
280
  Element.makePositioned(this.element); // fix IE
278
281
 
279
- this.delta = this.currentDelta();
280
282
  this.options = options;
281
283
  this.dragging = false;
282
284
 
@@ -298,17 +300,17 @@ Draggable.prototype = {
298
300
  },
299
301
 
300
302
  initDrag: function(event) {
301
- if(typeof Draggable._dragging[this.element] != 'undefined' &&
303
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
302
304
  Draggable._dragging[this.element]) return;
303
305
  if(Event.isLeftClick(event)) {
304
306
  // abort on form elements, fixes a Firefox issue
305
307
  var src = Event.element(event);
306
- if(src.tagName && (
307
- src.tagName=='INPUT' ||
308
- src.tagName=='SELECT' ||
309
- src.tagName=='OPTION' ||
310
- src.tagName=='BUTTON' ||
311
- src.tagName=='TEXTAREA')) return;
308
+ if((tag_name = src.tagName.toUpperCase()) && (
309
+ tag_name=='INPUT' ||
310
+ tag_name=='SELECT' ||
311
+ tag_name=='OPTION' ||
312
+ tag_name=='BUTTON' ||
313
+ tag_name=='TEXTAREA')) return;
312
314
 
313
315
  var pointer = [Event.pointerX(event), Event.pointerY(event)];
314
316
  var pos = Position.cumulativeOffset(this.element);
@@ -321,6 +323,8 @@ Draggable.prototype = {
321
323
 
322
324
  startDrag: function(event) {
323
325
  this.dragging = true;
326
+ if(!this.delta)
327
+ this.delta = this.currentDelta();
324
328
 
325
329
  if(this.options.zindex) {
326
330
  this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
@@ -329,7 +333,9 @@ Draggable.prototype = {
329
333
 
330
334
  if(this.options.ghosting) {
331
335
  this._clone = this.element.cloneNode(true);
332
- Position.absolutize(this.element);
336
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
337
+ if (!this.element._originallyAbsolute)
338
+ Position.absolutize(this.element);
333
339
  this.element.parentNode.insertBefore(this._clone, this.element);
334
340
  }
335
341
 
@@ -351,8 +357,12 @@ Draggable.prototype = {
351
357
 
352
358
  updateDrag: function(event, pointer) {
353
359
  if(!this.dragging) this.startDrag(event);
354
- Position.prepare();
355
- Droppables.show(pointer, this.element);
360
+
361
+ if(!this.options.quiet){
362
+ Position.prepare();
363
+ Droppables.show(pointer, this.element);
364
+ }
365
+
356
366
  Draggables.notify('onDrag', this, event);
357
367
 
358
368
  this.draw(pointer);
@@ -380,30 +390,44 @@ Draggable.prototype = {
380
390
  }
381
391
 
382
392
  // fix AppleWebKit rendering
383
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
393
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
384
394
 
385
395
  Event.stop(event);
386
396
  },
387
397
 
388
398
  finishDrag: function(event, success) {
389
399
  this.dragging = false;
400
+
401
+ if(this.options.quiet){
402
+ Position.prepare();
403
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
404
+ Droppables.show(pointer, this.element);
405
+ }
390
406
 
391
407
  if(this.options.ghosting) {
392
- Position.relativize(this.element);
408
+ if (!this.element._originallyAbsolute)
409
+ Position.relativize(this.element);
410
+ delete this.element._originallyAbsolute;
393
411
  Element.remove(this._clone);
394
412
  this._clone = null;
395
413
  }
396
414
 
397
- if(success) Droppables.fire(event, this.element);
415
+ var dropped = false;
416
+ if(success) {
417
+ dropped = Droppables.fire(event, this.element);
418
+ if (!dropped) dropped = false;
419
+ }
420
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
398
421
  Draggables.notify('onEnd', this, event);
399
422
 
400
423
  var revert = this.options.revert;
401
- if(revert && typeof revert == 'function') revert = revert(this.element);
424
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
402
425
 
403
426
  var d = this.currentDelta();
404
427
  if(revert && this.options.reverteffect) {
405
- this.options.reverteffect(this.element,
406
- d[1]-this.delta[1], d[0]-this.delta[0]);
428
+ if (dropped == 0 || revert != 'failure')
429
+ this.options.reverteffect(this.element,
430
+ d[1]-this.delta[1], d[0]-this.delta[0]);
407
431
  } else {
408
432
  this.delta = d;
409
433
  }
@@ -451,15 +475,15 @@ Draggable.prototype = {
451
475
  }.bind(this));
452
476
 
453
477
  if(this.options.snap) {
454
- if(typeof this.options.snap == 'function') {
478
+ if(Object.isFunction(this.options.snap)) {
455
479
  p = this.options.snap(p[0],p[1],this);
456
480
  } else {
457
- if(this.options.snap instanceof Array) {
481
+ if(Object.isArray(this.options.snap)) {
458
482
  p = p.map( function(v, i) {
459
- return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
483
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
460
484
  } else {
461
485
  p = p.map( function(v) {
462
- return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
486
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
463
487
  }
464
488
  }}
465
489
 
@@ -543,12 +567,13 @@ Draggable.prototype = {
543
567
  }
544
568
  return { top: T, left: L, width: W, height: H };
545
569
  }
546
- }
570
+ });
571
+
572
+ Draggable._dragging = { };
547
573
 
548
574
  /*--------------------------------------------------------------------------*/
549
575
 
550
- var SortableObserver = Class.create();
551
- SortableObserver.prototype = {
576
+ var SortableObserver = Class.create({
552
577
  initialize: function(element, observer) {
553
578
  this.element = $(element);
554
579
  this.observer = observer;
@@ -564,15 +589,15 @@ SortableObserver.prototype = {
564
589
  if(this.lastValue != Sortable.serialize(this.element))
565
590
  this.observer(this.element)
566
591
  }
567
- }
592
+ });
568
593
 
569
594
  var Sortable = {
570
595
  SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
571
596
 
572
- sortables: {},
597
+ sortables: { },
573
598
 
574
599
  _findRootElement: function(element) {
575
- while (element.tagName != "BODY") {
600
+ while (element.tagName.toUpperCase() != "BODY") {
576
601
  if(element.id && Sortable.sortables[element.id]) return element;
577
602
  element = element.parentNode;
578
603
  }
@@ -612,13 +637,20 @@ var Sortable = {
612
637
  delay: 0,
613
638
  hoverclass: null,
614
639
  ghosting: false,
640
+ quiet: false,
615
641
  scroll: false,
616
642
  scrollSensitivity: 20,
617
643
  scrollSpeed: 15,
618
644
  format: this.SERIALIZE_RULE,
645
+
646
+ // these take arrays of elements or ids and can be
647
+ // used for better initialization performance
648
+ elements: false,
649
+ handles: false,
650
+
619
651
  onChange: Prototype.emptyFunction,
620
652
  onUpdate: Prototype.emptyFunction
621
- }, arguments[1] || {});
653
+ }, arguments[1] || { });
622
654
 
623
655
  // clear any old sortable with same element
624
656
  this.destroy(element);
@@ -626,6 +658,7 @@ var Sortable = {
626
658
  // build options for the draggables
627
659
  var options_for_draggable = {
628
660
  revert: true,
661
+ quiet: options.quiet,
629
662
  scroll: options.scroll,
630
663
  scrollSpeed: options.scrollSpeed,
631
664
  scrollSensitivity: options.scrollSensitivity,
@@ -679,10 +712,9 @@ var Sortable = {
679
712
  options.droppables.push(element);
680
713
  }
681
714
 
682
- (this.findElements(element, options) || []).each( function(e) {
683
- // handles are per-draggable
684
- var handle = options.handle ?
685
- $(e).down('.'+options.handle,0) : e;
715
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
716
+ var handle = options.handles ? $(options.handles[i]) :
717
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
686
718
  options.draggables.push(
687
719
  new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
688
720
  Droppables.add(e, options_for_droppable);
@@ -842,7 +874,7 @@ var Sortable = {
842
874
  only: sortableOptions.only,
843
875
  name: element.id,
844
876
  format: sortableOptions.format
845
- }, arguments[1] || {});
877
+ }, arguments[1] || { });
846
878
 
847
879
  var root = {
848
880
  id: null,
@@ -866,7 +898,7 @@ var Sortable = {
866
898
 
867
899
  sequence: function(element) {
868
900
  element = $(element);
869
- var options = Object.extend(this.options(element), arguments[1] || {});
901
+ var options = Object.extend(this.options(element), arguments[1] || { });
870
902
 
871
903
  return $(this.findElements(element, options) || []).map( function(item) {
872
904
  return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
@@ -875,9 +907,9 @@ var Sortable = {
875
907
 
876
908
  setSequence: function(element, new_sequence) {
877
909
  element = $(element);
878
- var options = Object.extend(this.options(element), arguments[2] || {});
910
+ var options = Object.extend(this.options(element), arguments[2] || { });
879
911
 
880
- var nodeMap = {};
912
+ var nodeMap = { };
881
913
  this.findElements(element, options).each( function(n) {
882
914
  if (n.id.match(options.format))
883
915
  nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
@@ -895,7 +927,7 @@ var Sortable = {
895
927
 
896
928
  serialize: function(element) {
897
929
  element = $(element);
898
- var options = Object.extend(Sortable.options(element), arguments[1] || {});
930
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
899
931
  var name = encodeURIComponent(
900
932
  (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
901
933
 
@@ -919,7 +951,7 @@ Element.isParent = function(child, element) {
919
951
  return Element.isParent(child.parentNode, element);
920
952
  }
921
953
 
922
- Element.findChildren = function(element, only, recursive, tagName) {
954
+ Element.findChildren = function(element, only, recursive, tagName) {
923
955
  if(!element.hasChildNodes()) return null;
924
956
  tagName = tagName.toUpperCase();
925
957
  if(only) only = [only].flatten();
@@ -1,4 +1,6 @@
1
- // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
1
+ // script.aculo.us effects.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)
2
4
  // Contributors:
3
5
  // Justin Palmer (http://encytemedia.com/)
4
6
  // Mark Pilgrim (http://diveintomark.org/)
@@ -11,17 +13,17 @@
11
13
  // returns self (or first argument) if not convertable
12
14
  String.prototype.parseColor = function() {
13
15
  var color = '#';
14
- if(this.slice(0,4) == 'rgb(') {
16
+ if (this.slice(0,4) == 'rgb(') {
15
17
  var cols = this.slice(4,this.length-1).split(',');
16
18
  var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
17
19
  } else {
18
- if(this.slice(0,1) == '#') {
19
- if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
20
- if(this.length==7) color = this.toLowerCase();
20
+ if (this.slice(0,1) == '#') {
21
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
22
+ if (this.length==7) color = this.toLowerCase();
21
23
  }
22
24
  }
23
- return(color.length==7 ? color : (arguments[0] || this));
24
- }
25
+ return (color.length==7 ? color : (arguments[0] || this));
26
+ };
25
27
 
26
28
  /*--------------------------------------------------------------------------*/
27
29
 
@@ -30,7 +32,7 @@ Element.collectTextNodes = function(element) {
30
32
  return (node.nodeType==3 ? node.nodeValue :
31
33
  (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
32
34
  }).flatten().join('');
33
- }
35
+ };
34
36
 
35
37
  Element.collectTextNodesIgnoreClass = function(element, className) {
36
38
  return $A($(element).childNodes).collect( function(node) {
@@ -38,47 +40,18 @@ Element.collectTextNodesIgnoreClass = function(element, className) {
38
40
  ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
39
41
  Element.collectTextNodesIgnoreClass(node, className) : ''));
40
42
  }).flatten().join('');
41
- }
43
+ };
42
44
 
43
45
  Element.setContentZoom = function(element, percent) {
44
46
  element = $(element);
45
47
  element.setStyle({fontSize: (percent/100) + 'em'});
46
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
48
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
47
49
  return element;
48
- }
49
-
50
- Element.getOpacity = function(element){
51
- element = $(element);
52
- var opacity;
53
- if (opacity = element.getStyle('opacity'))
54
- return parseFloat(opacity);
55
- if (opacity = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
56
- if(opacity[1]) return parseFloat(opacity[1]) / 100;
57
- return 1.0;
58
- }
50
+ };
59
51
 
60
- Element.setOpacity = function(element, value){
61
- element= $(element);
62
- if (value == 1){
63
- element.setStyle({ opacity:
64
- (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ?
65
- 0.999999 : 1.0 });
66
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
67
- element.setStyle({filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});
68
- } else {
69
- if(value < 0.00001) value = 0;
70
- element.setStyle({opacity: value});
71
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
72
- element.setStyle(
73
- { filter: element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
74
- 'alpha(opacity='+value*100+')' });
75
- }
76
- return element;
77
- }
78
-
79
- Element.getInlineOpacity = function(element){
52
+ Element.getInlineOpacity = function(element){
80
53
  return $(element).style.opacity || '';
81
- }
54
+ };
82
55
 
83
56
  Element.forceRerendering = function(element) {
84
57
  try {
@@ -91,31 +64,63 @@ Element.forceRerendering = function(element) {
91
64
 
92
65
  /*--------------------------------------------------------------------------*/
93
66
 
94
- Array.prototype.call = function() {
95
- var args = arguments;
96
- this.each(function(f){ f.apply(this, args) });
97
- }
98
-
99
- /*--------------------------------------------------------------------------*/
100
-
101
67
  var Effect = {
102
68
  _elementDoesNotExistError: {
103
69
  name: 'ElementDoesNotExistError',
104
70
  message: 'The specified DOM element does not exist, but is required for this effect to operate'
105
71
  },
72
+ Transitions: {
73
+ linear: Prototype.K,
74
+ sinoidal: function(pos) {
75
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
76
+ },
77
+ reverse: function(pos) {
78
+ return 1-pos;
79
+ },
80
+ flicker: function(pos) {
81
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
82
+ return pos > 1 ? 1 : pos;
83
+ },
84
+ wobble: function(pos) {
85
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
86
+ },
87
+ pulse: function(pos, pulses) {
88
+ pulses = pulses || 5;
89
+ return (
90
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
91
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
92
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
93
+ );
94
+ },
95
+ spring: function(pos) {
96
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
97
+ },
98
+ none: function(pos) {
99
+ return 0;
100
+ },
101
+ full: function(pos) {
102
+ return 1;
103
+ }
104
+ },
105
+ DefaultOptions: {
106
+ duration: 1.0, // seconds
107
+ fps: 100, // 100= assume 66fps max.
108
+ sync: false, // true for combining
109
+ from: 0.0,
110
+ to: 1.0,
111
+ delay: 0.0,
112
+ queue: 'parallel'
113
+ },
106
114
  tagifyText: function(element) {
107
- if(typeof Builder == 'undefined')
108
- throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
109
-
110
115
  var tagifyStyle = 'position:relative';
111
- if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
116
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
112
117
 
113
118
  element = $(element);
114
119
  $A(element.childNodes).each( function(child) {
115
- if(child.nodeType==3) {
120
+ if (child.nodeType==3) {
116
121
  child.nodeValue.toArray().each( function(character) {
117
122
  element.insertBefore(
118
- Builder.node('span',{style: tagifyStyle},
123
+ new Element('span', {style: tagifyStyle}).update(
119
124
  character == ' ' ? String.fromCharCode(160) : character),
120
125
  child);
121
126
  });
@@ -125,8 +130,8 @@ var Effect = {
125
130
  },
126
131
  multiple: function(element, effect) {
127
132
  var elements;
128
- if(((typeof element == 'object') ||
129
- (typeof element == 'function')) &&
133
+ if (((typeof element == 'object') ||
134
+ Object.isFunction(element)) &&
130
135
  (element.length))
131
136
  elements = element;
132
137
  else
@@ -135,7 +140,7 @@ var Effect = {
135
140
  var options = Object.extend({
136
141
  speed: 0.1,
137
142
  delay: 0.0
138
- }, arguments[2] || {});
143
+ }, arguments[2] || { });
139
144
  var masterDelay = options.delay;
140
145
 
141
146
  $A(elements).each( function(element, index) {
@@ -152,53 +157,20 @@ var Effect = {
152
157
  effect = (effect || 'appear').toLowerCase();
153
158
  var options = Object.extend({
154
159
  queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
155
- }, arguments[2] || {});
160
+ }, arguments[2] || { });
156
161
  Effect[element.visible() ?
157
162
  Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
158
163
  }
159
164
  };
160
165
 
161
- var Effect2 = Effect; // deprecated
162
-
163
- /* ------------- transitions ------------- */
164
-
165
- Effect.Transitions = {
166
- linear: Prototype.K,
167
- sinoidal: function(pos) {
168
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
169
- },
170
- reverse: function(pos) {
171
- return 1-pos;
172
- },
173
- flicker: function(pos) {
174
- return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
175
- },
176
- wobble: function(pos) {
177
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
178
- },
179
- pulse: function(pos, pulses) {
180
- pulses = pulses || 5;
181
- return (
182
- Math.round((pos % (1/pulses)) * pulses) == 0 ?
183
- ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
184
- 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
185
- );
186
- },
187
- none: function(pos) {
188
- return 0;
189
- },
190
- full: function(pos) {
191
- return 1;
192
- }
193
- };
166
+ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
194
167
 
195
168
  /* ------------- core effects ------------- */
196
169
 
197
- Effect.ScopedQueue = Class.create();
198
- Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
170
+ Effect.ScopedQueue = Class.create(Enumerable, {
199
171
  initialize: function() {
200
172
  this.effects = [];
201
- this.interval = null;
173
+ this.interval = null;
202
174
  },
203
175
  _each: function(iterator) {
204
176
  this.effects._each(iterator);
@@ -206,7 +178,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
206
178
  add: function(effect) {
207
179
  var timestamp = new Date().getTime();
208
180
 
209
- var position = (typeof effect.options.queue == 'string') ?
181
+ var position = Object.isString(effect.options.queue) ?
210
182
  effect.options.queue : effect.options.queue.position;
211
183
 
212
184
  switch(position) {
@@ -229,115 +201,111 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
229
201
  effect.startOn += timestamp;
230
202
  effect.finishOn += timestamp;
231
203
 
232
- if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
204
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
233
205
  this.effects.push(effect);
234
206
 
235
- if(!this.interval)
236
- this.interval = setInterval(this.loop.bind(this), 40);
207
+ if (!this.interval)
208
+ this.interval = setInterval(this.loop.bind(this), 15);
237
209
  },
238
210
  remove: function(effect) {
239
211
  this.effects = this.effects.reject(function(e) { return e==effect });
240
- if(this.effects.length == 0) {
212
+ if (this.effects.length == 0) {
241
213
  clearInterval(this.interval);
242
214
  this.interval = null;
243
215
  }
244
216
  },
245
217
  loop: function() {
246
218
  var timePos = new Date().getTime();
247
- this.effects.invoke('loop', timePos);
219
+ for(var i=0, len=this.effects.length;i<len;i++)
220
+ this.effects[i] && this.effects[i].loop(timePos);
248
221
  }
249
222
  });
250
223
 
251
224
  Effect.Queues = {
252
225
  instances: $H(),
253
226
  get: function(queueName) {
254
- if(typeof queueName != 'string') return queueName;
227
+ if (!Object.isString(queueName)) return queueName;
255
228
 
256
- if(!this.instances[queueName])
257
- this.instances[queueName] = new Effect.ScopedQueue();
258
-
259
- return this.instances[queueName];
229
+ return this.instances.get(queueName) ||
230
+ this.instances.set(queueName, new Effect.ScopedQueue());
260
231
  }
261
- }
232
+ };
262
233
  Effect.Queue = Effect.Queues.get('global');
263
234
 
264
- Effect.DefaultOptions = {
265
- transition: Effect.Transitions.sinoidal,
266
- duration: 1.0, // seconds
267
- fps: 25.0, // max. 25fps due to Effect.Queue implementation
268
- sync: false, // true for combining
269
- from: 0.0,
270
- to: 1.0,
271
- delay: 0.0,
272
- queue: 'parallel'
273
- }
274
-
275
- Effect.Base = function() {};
276
- Effect.Base.prototype = {
235
+ Effect.Base = Class.create({
277
236
  position: null,
278
237
  start: function(options) {
279
- this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
238
+ function codeForEvent(options,eventName){
239
+ return (
240
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
241
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
242
+ );
243
+ }
244
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
245
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
280
246
  this.currentFrame = 0;
281
247
  this.state = 'idle';
282
248
  this.startOn = this.options.delay*1000;
283
- this.finishOn = this.startOn + (this.options.duration*1000);
249
+ this.finishOn = this.startOn+(this.options.duration*1000);
250
+ this.fromToDelta = this.options.to-this.options.from;
251
+ this.totalTime = this.finishOn-this.startOn;
252
+ this.totalFrames = this.options.fps*this.options.duration;
253
+
254
+ eval('this.render = function(pos){ '+
255
+ 'if (this.state=="idle"){this.state="running";'+
256
+ codeForEvent(this.options,'beforeSetup')+
257
+ (this.setup ? 'this.setup();':'')+
258
+ codeForEvent(this.options,'afterSetup')+
259
+ '};if (this.state=="running"){'+
260
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
261
+ 'this.position=pos;'+
262
+ codeForEvent(this.options,'beforeUpdate')+
263
+ (this.update ? 'this.update(pos);':'')+
264
+ codeForEvent(this.options,'afterUpdate')+
265
+ '}}');
266
+
284
267
  this.event('beforeStart');
285
- if(!this.options.sync)
286
- Effect.Queues.get(typeof this.options.queue == 'string' ?
268
+ if (!this.options.sync)
269
+ Effect.Queues.get(Object.isString(this.options.queue) ?
287
270
  'global' : this.options.queue.scope).add(this);
288
271
  },
289
272
  loop: function(timePos) {
290
- if(timePos >= this.startOn) {
291
- if(timePos >= this.finishOn) {
273
+ if (timePos >= this.startOn) {
274
+ if (timePos >= this.finishOn) {
292
275
  this.render(1.0);
293
276
  this.cancel();
294
277
  this.event('beforeFinish');
295
- if(this.finish) this.finish();
278
+ if (this.finish) this.finish();
296
279
  this.event('afterFinish');
297
280
  return;
298
281
  }
299
- var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
300
- var frame = Math.round(pos * this.options.fps * this.options.duration);
301
- if(frame > this.currentFrame) {
282
+ var pos = (timePos - this.startOn) / this.totalTime,
283
+ frame = (pos * this.totalFrames).round();
284
+ if (frame > this.currentFrame) {
302
285
  this.render(pos);
303
286
  this.currentFrame = frame;
304
287
  }
305
288
  }
306
289
  },
307
- render: function(pos) {
308
- if(this.state == 'idle') {
309
- this.state = 'running';
310
- this.event('beforeSetup');
311
- if(this.setup) this.setup();
312
- this.event('afterSetup');
313
- }
314
- if(this.state == 'running') {
315
- if(this.options.transition) pos = this.options.transition(pos);
316
- pos *= (this.options.to-this.options.from);
317
- pos += this.options.from;
318
- this.position = pos;
319
- this.event('beforeUpdate');
320
- if(this.update) this.update(pos);
321
- this.event('afterUpdate');
322
- }
323
- },
324
290
  cancel: function() {
325
- if(!this.options.sync)
326
- Effect.Queues.get(typeof this.options.queue == 'string' ?
291
+ if (!this.options.sync)
292
+ Effect.Queues.get(Object.isString(this.options.queue) ?
327
293
  'global' : this.options.queue.scope).remove(this);
328
294
  this.state = 'finished';
329
295
  },
330
296
  event: function(eventName) {
331
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
332
- if(this.options[eventName]) this.options[eventName](this);
297
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
298
+ if (this.options[eventName]) this.options[eventName](this);
333
299
  },
334
300
  inspect: function() {
335
- return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
301
+ var data = $H();
302
+ for(property in this)
303
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
304
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
336
305
  }
337
- }
306
+ });
338
307
 
339
- Effect.Parallel = Class.create();
340
- Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
308
+ Effect.Parallel = Class.create(Effect.Base, {
341
309
  initialize: function(effects) {
342
310
  this.effects = effects || [];
343
311
  this.start(arguments[1]);
@@ -350,35 +318,45 @@ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
350
318
  effect.render(1.0);
351
319
  effect.cancel();
352
320
  effect.event('beforeFinish');
353
- if(effect.finish) effect.finish(position);
321
+ if (effect.finish) effect.finish(position);
354
322
  effect.event('afterFinish');
355
323
  });
356
324
  }
357
325
  });
358
326
 
359
- Effect.Event = Class.create();
360
- Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
327
+ Effect.Tween = Class.create(Effect.Base, {
328
+ initialize: function(object, from, to) {
329
+ object = Object.isString(object) ? $(object) : object;
330
+ var args = $A(arguments), method = args.last(),
331
+ options = args.length == 5 ? args[3] : null;
332
+ this.method = Object.isFunction(method) ? method.bind(object) :
333
+ Object.isFunction(object[method]) ? object[method].bind(object) :
334
+ function(value) { object[method] = value };
335
+ this.start(Object.extend({ from: from, to: to }, options || { }));
336
+ },
337
+ update: function(position) {
338
+ this.method(position);
339
+ }
340
+ });
341
+
342
+ Effect.Event = Class.create(Effect.Base, {
361
343
  initialize: function() {
362
- var options = Object.extend({
363
- duration: 0
364
- }, arguments[0] || {});
365
- this.start(options);
344
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
366
345
  },
367
346
  update: Prototype.emptyFunction
368
347
  });
369
348
 
370
- Effect.Opacity = Class.create();
371
- Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
349
+ Effect.Opacity = Class.create(Effect.Base, {
372
350
  initialize: function(element) {
373
351
  this.element = $(element);
374
- if(!this.element) throw(Effect._elementDoesNotExistError);
352
+ if (!this.element) throw(Effect._elementDoesNotExistError);
375
353
  // make this work on IE on elements without 'layout'
376
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
354
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
377
355
  this.element.setStyle({zoom: 1});
378
356
  var options = Object.extend({
379
357
  from: this.element.getOpacity() || 0.0,
380
358
  to: 1.0
381
- }, arguments[1] || {});
359
+ }, arguments[1] || { });
382
360
  this.start(options);
383
361
  },
384
362
  update: function(position) {
@@ -386,36 +364,30 @@ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
386
364
  }
387
365
  });
388
366
 
389
- Effect.Move = Class.create();
390
- Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
367
+ Effect.Move = Class.create(Effect.Base, {
391
368
  initialize: function(element) {
392
369
  this.element = $(element);
393
- if(!this.element) throw(Effect._elementDoesNotExistError);
370
+ if (!this.element) throw(Effect._elementDoesNotExistError);
394
371
  var options = Object.extend({
395
372
  x: 0,
396
373
  y: 0,
397
374
  mode: 'relative'
398
- }, arguments[1] || {});
375
+ }, arguments[1] || { });
399
376
  this.start(options);
400
377
  },
401
378
  setup: function() {
402
- // Bug in Opera: Opera returns the "real" position of a static element or
403
- // relative element that does not have top/left explicitly set.
404
- // ==> Always set top and left for position relative elements in your stylesheets
405
- // (to 0 if you do not need them)
406
379
  this.element.makePositioned();
407
380
  this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
408
381
  this.originalTop = parseFloat(this.element.getStyle('top') || '0');
409
- if(this.options.mode == 'absolute') {
410
- // absolute movement, so we need to calc deltaX and deltaY
382
+ if (this.options.mode == 'absolute') {
411
383
  this.options.x = this.options.x - this.originalLeft;
412
384
  this.options.y = this.options.y - this.originalTop;
413
385
  }
414
386
  },
415
387
  update: function(position) {
416
388
  this.element.setStyle({
417
- left: Math.round(this.options.x * position + this.originalLeft) + 'px',
418
- top: Math.round(this.options.y * position + this.originalTop) + 'px'
389
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
390
+ top: (this.options.y * position + this.originalTop).round() + 'px'
419
391
  });
420
392
  }
421
393
  });
@@ -423,30 +395,29 @@ Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
423
395
  // for backwards compatibility
424
396
  Effect.MoveBy = function(element, toTop, toLeft) {
425
397
  return new Effect.Move(element,
426
- Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
398
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
427
399
  };
428
400
 
429
- Effect.Scale = Class.create();
430
- Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
401
+ Effect.Scale = Class.create(Effect.Base, {
431
402
  initialize: function(element, percent) {
432
403
  this.element = $(element);
433
- if(!this.element) throw(Effect._elementDoesNotExistError);
404
+ if (!this.element) throw(Effect._elementDoesNotExistError);
434
405
  var options = Object.extend({
435
406
  scaleX: true,
436
407
  scaleY: true,
437
408
  scaleContent: true,
438
409
  scaleFromCenter: false,
439
- scaleMode: 'box', // 'box' or 'contents' or {} with provided values
410
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
440
411
  scaleFrom: 100.0,
441
412
  scaleTo: percent
442
- }, arguments[2] || {});
413
+ }, arguments[2] || { });
443
414
  this.start(options);
444
415
  },
445
416
  setup: function() {
446
417
  this.restoreAfterFinish = this.options.restoreAfterFinish || false;
447
418
  this.elementPositioning = this.element.getStyle('position');
448
419
 
449
- this.originalStyle = {};
420
+ this.originalStyle = { };
450
421
  ['top','left','width','height','fontSize'].each( function(k) {
451
422
  this.originalStyle[k] = this.element.style[k];
452
423
  }.bind(this));
@@ -456,7 +427,7 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
456
427
 
457
428
  var fontSize = this.element.getStyle('font-size') || '100%';
458
429
  ['em','px','%','pt'].each( function(fontSizeType) {
459
- if(fontSize.indexOf(fontSizeType)>0) {
430
+ if (fontSize.indexOf(fontSizeType)>0) {
460
431
  this.fontSize = parseFloat(fontSize);
461
432
  this.fontSizeType = fontSizeType;
462
433
  }
@@ -465,60 +436,61 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
465
436
  this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
466
437
 
467
438
  this.dims = null;
468
- if(this.options.scaleMode=='box')
439
+ if (this.options.scaleMode=='box')
469
440
  this.dims = [this.element.offsetHeight, this.element.offsetWidth];
470
- if(/^content/.test(this.options.scaleMode))
441
+ if (/^content/.test(this.options.scaleMode))
471
442
  this.dims = [this.element.scrollHeight, this.element.scrollWidth];
472
- if(!this.dims)
443
+ if (!this.dims)
473
444
  this.dims = [this.options.scaleMode.originalHeight,
474
445
  this.options.scaleMode.originalWidth];
475
446
  },
476
447
  update: function(position) {
477
448
  var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
478
- if(this.options.scaleContent && this.fontSize)
449
+ if (this.options.scaleContent && this.fontSize)
479
450
  this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
480
451
  this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
481
452
  },
482
453
  finish: function(position) {
483
- if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
454
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
484
455
  },
485
456
  setDimensions: function(height, width) {
486
- var d = {};
487
- if(this.options.scaleX) d.width = Math.round(width) + 'px';
488
- if(this.options.scaleY) d.height = Math.round(height) + 'px';
489
- if(this.options.scaleFromCenter) {
457
+ var d = { };
458
+ if (this.options.scaleX) d.width = width.round() + 'px';
459
+ if (this.options.scaleY) d.height = height.round() + 'px';
460
+ if (this.options.scaleFromCenter) {
490
461
  var topd = (height - this.dims[0])/2;
491
462
  var leftd = (width - this.dims[1])/2;
492
- if(this.elementPositioning == 'absolute') {
493
- if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
494
- if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
463
+ if (this.elementPositioning == 'absolute') {
464
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
465
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
495
466
  } else {
496
- if(this.options.scaleY) d.top = -topd + 'px';
497
- if(this.options.scaleX) d.left = -leftd + 'px';
467
+ if (this.options.scaleY) d.top = -topd + 'px';
468
+ if (this.options.scaleX) d.left = -leftd + 'px';
498
469
  }
499
470
  }
500
471
  this.element.setStyle(d);
501
472
  }
502
473
  });
503
474
 
504
- Effect.Highlight = Class.create();
505
- Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
475
+ Effect.Highlight = Class.create(Effect.Base, {
506
476
  initialize: function(element) {
507
477
  this.element = $(element);
508
- if(!this.element) throw(Effect._elementDoesNotExistError);
509
- var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
478
+ if (!this.element) throw(Effect._elementDoesNotExistError);
479
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
510
480
  this.start(options);
511
481
  },
512
482
  setup: function() {
513
483
  // Prevent executing on elements not in the layout flow
514
- if(this.element.getStyle('display')=='none') { this.cancel(); return; }
484
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
515
485
  // Disable background image during the effect
516
- this.oldStyle = {
517
- backgroundImage: this.element.getStyle('background-image') };
518
- this.element.setStyle({backgroundImage: 'none'});
519
- if(!this.options.endcolor)
486
+ this.oldStyle = { };
487
+ if (!this.options.keepBackgroundImage) {
488
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
489
+ this.element.setStyle({backgroundImage: 'none'});
490
+ }
491
+ if (!this.options.endcolor)
520
492
  this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
521
- if(!this.options.restorecolor)
493
+ if (!this.options.restorecolor)
522
494
  this.options.restorecolor = this.element.getStyle('background-color');
523
495
  // init color calculations
524
496
  this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
@@ -526,7 +498,7 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype),
526
498
  },
527
499
  update: function(position) {
528
500
  this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
529
- return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
501
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
530
502
  },
531
503
  finish: function() {
532
504
  this.element.setStyle(Object.extend(this.oldStyle, {
@@ -535,30 +507,21 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype),
535
507
  }
536
508
  });
537
509
 
538
- Effect.ScrollTo = Class.create();
539
- Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
540
- initialize: function(element) {
541
- this.element = $(element);
542
- this.start(arguments[1] || {});
543
- },
544
- setup: function() {
545
- Position.prepare();
546
- var offsets = Position.cumulativeOffset(this.element);
547
- if(this.options.offset) offsets[1] += this.options.offset;
548
- var max = window.innerHeight ?
549
- window.height - window.innerHeight :
550
- document.body.scrollHeight -
551
- (document.documentElement.clientHeight ?
552
- document.documentElement.clientHeight : document.body.clientHeight);
553
- this.scrollStart = Position.deltaY;
554
- this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
555
- },
556
- update: function(position) {
557
- Position.prepare();
558
- window.scrollTo(Position.deltaX,
559
- this.scrollStart + (position*this.delta));
560
- }
561
- });
510
+ Effect.ScrollTo = function(element) {
511
+ var options = arguments[1] || { },
512
+ scrollOffsets = document.viewport.getScrollOffsets(),
513
+ elementOffsets = $(element).cumulativeOffset(),
514
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
515
+
516
+ if (options.offset) elementOffsets[1] += options.offset;
517
+
518
+ return new Effect.Tween(null,
519
+ scrollOffsets.top,
520
+ elementOffsets[1] > max ? max : elementOffsets[1],
521
+ options,
522
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
523
+ );
524
+ };
562
525
 
563
526
  /* ------------- combination effects ------------- */
564
527
 
@@ -566,14 +529,15 @@ Effect.Fade = function(element) {
566
529
  element = $(element);
567
530
  var oldOpacity = element.getInlineOpacity();
568
531
  var options = Object.extend({
569
- from: element.getOpacity() || 1.0,
570
- to: 0.0,
571
- afterFinishInternal: function(effect) {
572
- if(effect.options.to!=0) return;
573
- effect.element.hide().setStyle({opacity: oldOpacity});
574
- }}, arguments[1] || {});
532
+ from: element.getOpacity() || 1.0,
533
+ to: 0.0,
534
+ afterFinishInternal: function(effect) {
535
+ if (effect.options.to!=0) return;
536
+ effect.element.hide().setStyle({opacity: oldOpacity});
537
+ }
538
+ }, arguments[1] || { });
575
539
  return new Effect.Opacity(element,options);
576
- }
540
+ };
577
541
 
578
542
  Effect.Appear = function(element) {
579
543
  element = $(element);
@@ -586,9 +550,9 @@ Effect.Appear = function(element) {
586
550
  },
587
551
  beforeSetup: function(effect) {
588
552
  effect.element.setOpacity(effect.options.from).show();
589
- }}, arguments[1] || {});
553
+ }}, arguments[1] || { });
590
554
  return new Effect.Opacity(element,options);
591
- }
555
+ };
592
556
 
593
557
  Effect.Puff = function(element) {
594
558
  element = $(element);
@@ -610,9 +574,9 @@ Effect.Puff = function(element) {
610
574
  },
611
575
  afterFinishInternal: function(effect) {
612
576
  effect.effects[0].element.hide().setStyle(oldStyle); }
613
- }, arguments[1] || {})
577
+ }, arguments[1] || { })
614
578
  );
615
- }
579
+ };
616
580
 
617
581
  Effect.BlindUp = function(element) {
618
582
  element = $(element);
@@ -624,9 +588,9 @@ Effect.BlindUp = function(element) {
624
588
  afterFinishInternal: function(effect) {
625
589
  effect.element.hide().undoClipping();
626
590
  }
627
- }, arguments[1] || {})
591
+ }, arguments[1] || { })
628
592
  );
629
- }
593
+ };
630
594
 
631
595
  Effect.BlindDown = function(element) {
632
596
  element = $(element);
@@ -643,8 +607,8 @@ Effect.BlindDown = function(element) {
643
607
  afterFinishInternal: function(effect) {
644
608
  effect.element.undoClipping();
645
609
  }
646
- }, arguments[1] || {}));
647
- }
610
+ }, arguments[1] || { }));
611
+ };
648
612
 
649
613
  Effect.SwitchOff = function(element) {
650
614
  element = $(element);
@@ -665,8 +629,8 @@ Effect.SwitchOff = function(element) {
665
629
  }
666
630
  })
667
631
  }
668
- }, arguments[1] || {}));
669
- }
632
+ }, arguments[1] || { }));
633
+ };
670
634
 
671
635
  Effect.DropOut = function(element) {
672
636
  element = $(element);
@@ -685,29 +649,35 @@ Effect.DropOut = function(element) {
685
649
  afterFinishInternal: function(effect) {
686
650
  effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
687
651
  }
688
- }, arguments[1] || {}));
689
- }
652
+ }, arguments[1] || { }));
653
+ };
690
654
 
691
655
  Effect.Shake = function(element) {
692
656
  element = $(element);
657
+ var options = Object.extend({
658
+ distance: 20,
659
+ duration: 0.5
660
+ }, arguments[1] || {});
661
+ var distance = parseFloat(options.distance);
662
+ var split = parseFloat(options.duration) / 10.0;
693
663
  var oldStyle = {
694
664
  top: element.getStyle('top'),
695
665
  left: element.getStyle('left') };
696
- return new Effect.Move(element,
697
- { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
666
+ return new Effect.Move(element,
667
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
698
668
  new Effect.Move(effect.element,
699
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
669
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
700
670
  new Effect.Move(effect.element,
701
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
671
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
702
672
  new Effect.Move(effect.element,
703
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
673
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
704
674
  new Effect.Move(effect.element,
705
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
675
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
706
676
  new Effect.Move(effect.element,
707
- { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
677
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
708
678
  effect.element.undoPositioned().setStyle(oldStyle);
709
679
  }}) }}) }}) }}) }}) }});
710
- }
680
+ };
711
681
 
712
682
  Effect.SlideDown = function(element) {
713
683
  element = $(element).cleanWhitespace();
@@ -723,7 +693,7 @@ Effect.SlideDown = function(element) {
723
693
  afterSetup: function(effect) {
724
694
  effect.element.makePositioned();
725
695
  effect.element.down().makePositioned();
726
- if(window.opera) effect.element.setStyle({top: ''});
696
+ if (window.opera) effect.element.setStyle({top: ''});
727
697
  effect.element.makeClipping().setStyle({height: '0px'}).show();
728
698
  },
729
699
  afterUpdateInternal: function(effect) {
@@ -733,23 +703,25 @@ Effect.SlideDown = function(element) {
733
703
  afterFinishInternal: function(effect) {
734
704
  effect.element.undoClipping().undoPositioned();
735
705
  effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
736
- }, arguments[1] || {})
706
+ }, arguments[1] || { })
737
707
  );
738
- }
708
+ };
739
709
 
740
710
  Effect.SlideUp = function(element) {
741
711
  element = $(element).cleanWhitespace();
742
712
  var oldInnerBottom = element.down().getStyle('bottom');
713
+ var elementDimensions = element.getDimensions();
743
714
  return new Effect.Scale(element, window.opera ? 0 : 1,
744
715
  Object.extend({ scaleContent: false,
745
716
  scaleX: false,
746
717
  scaleMode: 'box',
747
718
  scaleFrom: 100,
719
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
748
720
  restoreAfterFinish: true,
749
- beforeStartInternal: function(effect) {
721
+ afterSetup: function(effect) {
750
722
  effect.element.makePositioned();
751
723
  effect.element.down().makePositioned();
752
- if(window.opera) effect.element.setStyle({top: ''});
724
+ if (window.opera) effect.element.setStyle({top: ''});
753
725
  effect.element.makeClipping().show();
754
726
  },
755
727
  afterUpdateInternal: function(effect) {
@@ -757,12 +729,12 @@ Effect.SlideUp = function(element) {
757
729
  (effect.dims[0] - effect.element.clientHeight) + 'px' });
758
730
  },
759
731
  afterFinishInternal: function(effect) {
760
- effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
761
- effect.element.down().undoPositioned();
732
+ effect.element.hide().undoClipping().undoPositioned();
733
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
762
734
  }
763
- }, arguments[1] || {})
735
+ }, arguments[1] || { })
764
736
  );
765
- }
737
+ };
766
738
 
767
739
  // Bug in opera makes the TD containing this element expand for a instance after finish
768
740
  Effect.Squish = function(element) {
@@ -775,7 +747,7 @@ Effect.Squish = function(element) {
775
747
  effect.element.hide().undoClipping();
776
748
  }
777
749
  });
778
- }
750
+ };
779
751
 
780
752
  Effect.Grow = function(element) {
781
753
  element = $(element);
@@ -784,7 +756,7 @@ Effect.Grow = function(element) {
784
756
  moveTransition: Effect.Transitions.sinoidal,
785
757
  scaleTransition: Effect.Transitions.sinoidal,
786
758
  opacityTransition: Effect.Transitions.full
787
- }, arguments[1] || {});
759
+ }, arguments[1] || { });
788
760
  var oldStyle = {
789
761
  top: element.style.top,
790
762
  left: element.style.left,
@@ -849,7 +821,7 @@ Effect.Grow = function(element) {
849
821
  )
850
822
  }
851
823
  });
852
- }
824
+ };
853
825
 
854
826
  Effect.Shrink = function(element) {
855
827
  element = $(element);
@@ -858,7 +830,7 @@ Effect.Shrink = function(element) {
858
830
  moveTransition: Effect.Transitions.sinoidal,
859
831
  scaleTransition: Effect.Transitions.sinoidal,
860
832
  opacityTransition: Effect.Transitions.none
861
- }, arguments[1] || {});
833
+ }, arguments[1] || { });
862
834
  var oldStyle = {
863
835
  top: element.style.top,
864
836
  left: element.style.left,
@@ -903,11 +875,11 @@ Effect.Shrink = function(element) {
903
875
  effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
904
876
  }, options)
905
877
  );
906
- }
878
+ };
907
879
 
908
880
  Effect.Pulsate = function(element) {
909
881
  element = $(element);
910
- var options = arguments[1] || {};
882
+ var options = arguments[1] || { };
911
883
  var oldOpacity = element.getInlineOpacity();
912
884
  var transition = options.transition || Effect.Transitions.sinoidal;
913
885
  var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
@@ -916,7 +888,7 @@ Effect.Pulsate = function(element) {
916
888
  Object.extend(Object.extend({ duration: 2.0, from: 0,
917
889
  afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
918
890
  }, options), {transition: reverser}));
919
- }
891
+ };
920
892
 
921
893
  Effect.Fold = function(element) {
922
894
  element = $(element);
@@ -936,37 +908,71 @@ Effect.Fold = function(element) {
936
908
  afterFinishInternal: function(effect) {
937
909
  effect.element.hide().undoClipping().setStyle(oldStyle);
938
910
  } });
939
- }}, arguments[1] || {}));
911
+ }}, arguments[1] || { }));
940
912
  };
941
913
 
942
- Effect.Morph = Class.create();
943
- Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
914
+ Effect.Morph = Class.create(Effect.Base, {
944
915
  initialize: function(element) {
945
916
  this.element = $(element);
946
- if(!this.element) throw(Effect._elementDoesNotExistError);
917
+ if (!this.element) throw(Effect._elementDoesNotExistError);
947
918
  var options = Object.extend({
948
- style: ''
949
- }, arguments[1] || {});
919
+ style: { }
920
+ }, arguments[1] || { });
921
+
922
+ if (!Object.isString(options.style)) this.style = $H(options.style);
923
+ else {
924
+ if (options.style.include(':'))
925
+ this.style = options.style.parseStyle();
926
+ else {
927
+ this.element.addClassName(options.style);
928
+ this.style = $H(this.element.getStyles());
929
+ this.element.removeClassName(options.style);
930
+ var css = this.element.getStyles();
931
+ this.style = this.style.reject(function(style) {
932
+ return style.value == css[style.key];
933
+ });
934
+ options.afterFinishInternal = function(effect) {
935
+ effect.element.addClassName(effect.options.style);
936
+ effect.transforms.each(function(transform) {
937
+ effect.element.style[transform.style] = '';
938
+ });
939
+ }
940
+ }
941
+ }
950
942
  this.start(options);
951
943
  },
944
+
952
945
  setup: function(){
953
946
  function parseColor(color){
954
- if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
947
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
955
948
  color = color.parseColor();
956
949
  return $R(0,2).map(function(i){
957
950
  return parseInt( color.slice(i*2+1,i*2+3), 16 )
958
951
  });
959
952
  }
960
- this.transforms = this.options.style.parseStyle().map(function(property){
961
- var originalValue = this.element.getStyle(property[0]);
962
- return $H({
963
- style: property[0],
964
- originalValue: property[1].unit=='color' ?
965
- parseColor(originalValue) : parseFloat(originalValue || 0),
966
- targetValue: property[1].unit=='color' ?
967
- parseColor(property[1].value) : property[1].value,
968
- unit: property[1].unit
969
- });
953
+ this.transforms = this.style.map(function(pair){
954
+ var property = pair[0], value = pair[1], unit = null;
955
+
956
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
957
+ value = value.parseColor();
958
+ unit = 'color';
959
+ } else if (property == 'opacity') {
960
+ value = parseFloat(value);
961
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
962
+ this.element.setStyle({zoom: 1});
963
+ } else if (Element.CSS_LENGTH.test(value)) {
964
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
965
+ value = parseFloat(components[1]);
966
+ unit = (components.length == 3) ? components[2] : null;
967
+ }
968
+
969
+ var originalValue = this.element.getStyle(property);
970
+ return {
971
+ style: property.camelize(),
972
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
973
+ targetValue: unit=='color' ? parseColor(value) : value,
974
+ unit: unit
975
+ };
970
976
  }.bind(this)).reject(function(transform){
971
977
  return (
972
978
  (transform.originalValue == transform.targetValue) ||
@@ -978,32 +984,35 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
978
984
  });
979
985
  },
980
986
  update: function(position) {
981
- var style = $H(), value = null;
982
- this.transforms.each(function(transform){
983
- value = transform.unit=='color' ?
984
- $R(0,2).inject('#',function(m,v,i){
985
- return m+(Math.round(transform.originalValue[i]+
986
- (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :
987
- transform.originalValue + Math.round(
988
- ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
989
- style[transform.style] = value;
990
- });
991
- this.element.setStyle(style);
987
+ var style = { }, transform, i = this.transforms.length;
988
+ while(i--)
989
+ style[(transform = this.transforms[i]).style] =
990
+ transform.unit=='color' ? '#'+
991
+ (Math.round(transform.originalValue[0]+
992
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
993
+ (Math.round(transform.originalValue[1]+
994
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
995
+ (Math.round(transform.originalValue[2]+
996
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
997
+ (transform.originalValue +
998
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
999
+ (transform.unit === null ? '' : transform.unit);
1000
+ this.element.setStyle(style, true);
992
1001
  }
993
1002
  });
994
1003
 
995
- Effect.Transform = Class.create();
996
- Object.extend(Effect.Transform.prototype, {
1004
+ Effect.Transform = Class.create({
997
1005
  initialize: function(tracks){
998
1006
  this.tracks = [];
999
- this.options = arguments[1] || {};
1007
+ this.options = arguments[1] || { };
1000
1008
  this.addTracks(tracks);
1001
1009
  },
1002
1010
  addTracks: function(tracks){
1003
1011
  tracks.each(function(track){
1004
- var data = $H(track).values().first();
1012
+ track = $H(track);
1013
+ var data = track.values().first();
1005
1014
  this.tracks.push($H({
1006
- ids: $H(track).keys().first(),
1015
+ ids: track.keys().first(),
1007
1016
  effect: Effect.Morph,
1008
1017
  options: { style: data }
1009
1018
  }));
@@ -1013,76 +1022,101 @@ Object.extend(Effect.Transform.prototype, {
1013
1022
  play: function(){
1014
1023
  return new Effect.Parallel(
1015
1024
  this.tracks.map(function(track){
1016
- var elements = [$(track.ids) || $$(track.ids)].flatten();
1017
- return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
1025
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1026
+ var elements = [$(ids) || $$(ids)].flatten();
1027
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
1018
1028
  }).flatten(),
1019
1029
  this.options
1020
1030
  );
1021
1031
  }
1022
1032
  });
1023
1033
 
1024
- Element.CSS_PROPERTIES = ['azimuth', 'backgroundAttachment', 'backgroundColor', 'backgroundImage',
1025
- 'backgroundPosition', 'backgroundRepeat', 'borderBottomColor', 'borderBottomStyle',
1026
- 'borderBottomWidth', 'borderCollapse', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth',
1027
- 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderSpacing', 'borderTopColor',
1028
- 'borderTopStyle', 'borderTopWidth', 'bottom', 'captionSide', 'clear', 'clip', 'color', 'content',
1029
- 'counterIncrement', 'counterReset', 'cssFloat', 'cueAfter', 'cueBefore', 'cursor', 'direction',
1030
- 'display', 'elevation', 'emptyCells', 'fontFamily', 'fontSize', 'fontSizeAdjust', 'fontStretch',
1031
- 'fontStyle', 'fontVariant', 'fontWeight', 'height', 'left', 'letterSpacing', 'lineHeight',
1032
- 'listStyleImage', 'listStylePosition', 'listStyleType', 'marginBottom', 'marginLeft', 'marginRight',
1033
- 'marginTop', 'markerOffset', 'marks', 'maxHeight', 'maxWidth', 'minHeight', 'minWidth', 'opacity',
1034
- 'orphans', 'outlineColor', 'outlineOffset', 'outlineStyle', 'outlineWidth', 'overflowX', 'overflowY',
1035
- 'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'page', 'pageBreakAfter', 'pageBreakBefore',
1036
- 'pageBreakInside', 'pauseAfter', 'pauseBefore', 'pitch', 'pitchRange', 'position', 'quotes',
1037
- 'richness', 'right', 'size', 'speakHeader', 'speakNumeral', 'speakPunctuation', 'speechRate', 'stress',
1038
- 'tableLayout', 'textAlign', 'textDecoration', 'textIndent', 'textShadow', 'textTransform', 'top',
1039
- 'unicodeBidi', 'verticalAlign', 'visibility', 'voiceFamily', 'volume', 'whiteSpace', 'widows',
1040
- 'width', 'wordSpacing', 'zIndex'];
1034
+ Element.CSS_PROPERTIES = $w(
1035
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1036
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1037
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1038
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1039
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
1040
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1041
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1042
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1043
+ 'right textIndent top width wordSpacing zIndex');
1041
1044
 
1042
1045
  Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1043
1046
 
1047
+ String.__parseStyleElement = document.createElement('div');
1044
1048
  String.prototype.parseStyle = function(){
1045
- var element = Element.extend(document.createElement('div'));
1046
- element.innerHTML = '<div style="' + this + '"></div>';
1047
- var style = element.down().style, styleRules = $H();
1049
+ var style, styleRules = $H();
1050
+ if (Prototype.Browser.WebKit)
1051
+ style = new Element('div',{style:this}).style;
1052
+ else {
1053
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1054
+ style = String.__parseStyleElement.childNodes[0].style;
1055
+ }
1048
1056
 
1049
1057
  Element.CSS_PROPERTIES.each(function(property){
1050
- if(style[property]) styleRules[property] = style[property];
1058
+ if (style[property]) styleRules.set(property, style[property]);
1051
1059
  });
1052
1060
 
1053
- var result = $H();
1054
-
1055
- styleRules.each(function(pair){
1056
- var property = pair[0], value = pair[1], unit = null;
1057
-
1058
- if(value.parseColor('#zzzzzz') != '#zzzzzz') {
1059
- value = value.parseColor();
1060
- unit = 'color';
1061
- } else if(Element.CSS_LENGTH.test(value))
1062
- var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),
1063
- value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null;
1064
-
1065
- result[property.underscore().dasherize()] = $H({ value:value, unit:unit });
1066
- }.bind(this));
1067
-
1068
- return result;
1061
+ if (Prototype.Browser.IE && this.include('opacity'))
1062
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1063
+
1064
+ return styleRules;
1069
1065
  };
1070
1066
 
1071
- Element.morph = function(element, style) {
1072
- new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
1073
- return element;
1067
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1068
+ Element.getStyles = function(element) {
1069
+ var css = document.defaultView.getComputedStyle($(element), null);
1070
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1071
+ styles[property] = css[property];
1072
+ return styles;
1073
+ });
1074
+ };
1075
+ } else {
1076
+ Element.getStyles = function(element) {
1077
+ element = $(element);
1078
+ var css = element.currentStyle, styles;
1079
+ styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) {
1080
+ hash.set(property, css[property]);
1081
+ return hash;
1082
+ });
1083
+ if (!styles.opacity) styles.set('opacity', element.getOpacity());
1084
+ return styles;
1085
+ };
1074
1086
  };
1075
1087
 
1076
- ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
1077
- 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
1078
- function(f) { Element.Methods[f] = Element[f]; }
1088
+ Effect.Methods = {
1089
+ morph: function(element, style) {
1090
+ element = $(element);
1091
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1092
+ return element;
1093
+ },
1094
+ visualEffect: function(element, effect, options) {
1095
+ element = $(element)
1096
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1097
+ new Effect[klass](element, options);
1098
+ return element;
1099
+ },
1100
+ highlight: function(element, options) {
1101
+ element = $(element);
1102
+ new Effect.Highlight(element, options);
1103
+ return element;
1104
+ }
1105
+ };
1106
+
1107
+ $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1108
+ 'pulsate shake puff squish switchOff dropOut').each(
1109
+ function(effect) {
1110
+ Effect.Methods[effect] = function(element, options){
1111
+ element = $(element);
1112
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1113
+ return element;
1114
+ }
1115
+ }
1079
1116
  );
1080
1117
 
1081
- Element.Methods.visualEffect = function(element, effect, options) {
1082
- s = effect.gsub(/_/, '-').camelize();
1083
- effect_class = s.charAt(0).toUpperCase() + s.substring(1);
1084
- new Effect[effect_class](element, options);
1085
- return $(element);
1086
- };
1118
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1119
+ function(f) { Effect.Methods[f] = Element[f]; }
1120
+ );
1087
1121
 
1088
- Element.addMethods();
1122
+ Element.addMethods(Effect.Methods);