rails 0.14.2 → 0.14.3

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

Potentially problematic release.


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

Files changed (53) hide show
  1. data/CHANGELOG +83 -0
  2. data/README +16 -53
  3. data/Rakefile +10 -11
  4. data/bin/about +3 -0
  5. data/bin/plugin +3 -0
  6. data/configs/database.yml +65 -3
  7. data/configs/lighttpd.conf +40 -0
  8. data/environments/boot.rb +2 -2
  9. data/environments/environment.rb +3 -3
  10. data/environments/test.rb +1 -7
  11. data/helpers/test_helper.rb +19 -4
  12. data/html/javascripts/controls.js +18 -5
  13. data/html/javascripts/dragdrop.js +6 -3
  14. data/html/javascripts/effects.js +181 -290
  15. data/html/javascripts/prototype.js +13 -11
  16. data/lib/commands/about.rb +2 -0
  17. data/lib/commands/plugin.rb +823 -0
  18. data/lib/commands/process/reaper.rb +3 -3
  19. data/lib/commands/server.rb +23 -54
  20. data/lib/commands/servers/lighttpd.rb +56 -0
  21. data/lib/commands/servers/webrick.rb +59 -0
  22. data/lib/dispatcher.rb +30 -8
  23. data/lib/fcgi_handler.rb +6 -1
  24. data/lib/initializer.rb +107 -42
  25. data/lib/rails_generator/generators/applications/app/app_generator.rb +14 -12
  26. data/lib/rails_generator/generators/components/migration/migration_generator.rb +52 -5
  27. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +2 -2
  28. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +1 -5
  29. data/lib/rails_generator/generators/components/plugin/USAGE +33 -0
  30. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +33 -0
  31. data/lib/rails_generator/generators/components/plugin/templates/README +4 -0
  32. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +22 -0
  33. data/lib/rails_generator/generators/components/plugin/templates/USAGE +8 -0
  34. data/lib/rails_generator/generators/components/plugin/templates/generator.rb +8 -0
  35. data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -0
  36. data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -0
  37. data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +4 -0
  38. data/lib/rails_generator/generators/components/plugin/templates/unit_test.rb +8 -0
  39. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +6 -1
  40. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +1 -1
  41. data/lib/rails_generator/generators/components/scaffold/templates/style.css +1 -1
  42. data/lib/rails_generator/lookup.rb +1 -0
  43. data/lib/rails_info.rb +94 -0
  44. data/lib/rails_version.rb +1 -1
  45. data/lib/tasks/databases.rake +8 -5
  46. data/lib/tasks/documentation.rake +34 -1
  47. data/lib/tasks/framework.rake +50 -12
  48. data/lib/tasks/misc.rake +5 -1
  49. data/lib/tasks/rails.rb +2 -2
  50. data/lib/tasks/testing.rake +14 -1
  51. metadata +28 -9
  52. data/html/javascripts/scriptaculous.js +0 -47
  53. data/html/javascripts/slider.js +0 -258
@@ -3,11 +3,26 @@ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
3
3
  require 'test_help'
4
4
 
5
5
  class Test::Unit::TestCase
6
- # Turn off transactional fixtures if you're working with MyISAM tables in MySQL
6
+ # Transactional fixtures accelerate your tests by wrapping each test method
7
+ # in a transaction that's rolled back on completion. This ensures that the
8
+ # test database remains unchanged so your fixtures don't have to be reloaded
9
+ # between every test method. Fewer database queries means faster tests.
10
+ #
11
+ # Read Mike Clark's excellent walkthrough at
12
+ # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
13
+ #
14
+ # Every Active Record database supports transactions except MyISAM tables
15
+ # in MySQL. Turn off transactional fixtures in this case; however, if you
16
+ # don't care one way or the other, switching from MyISAM to InnoDB tables
17
+ # is recommended.
7
18
  self.use_transactional_fixtures = true
8
-
9
- # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
19
+
20
+ # Instantiated fixtures are slow, but give you @david where otherwise you
21
+ # would need people(:david). If you don't want to migrate your existing
22
+ # test cases which use the @david style and don't mind the speed hit (each
23
+ # instantiated fixtures translates to a database query per test method),
24
+ # then set this back to true.
10
25
  self.use_instantiated_fixtures = false
11
26
 
12
27
  # Add more helper methods to be used by all tests here...
13
- end
28
+ end
@@ -184,7 +184,10 @@ Autocompleter.Base.prototype = {
184
184
  this.show();
185
185
  this.active = true;
186
186
  }
187
- } else this.hide();
187
+ } else {
188
+ this.active = false;
189
+ this.hide();
190
+ }
188
191
  },
189
192
 
190
193
  markPrevious: function() {
@@ -425,6 +428,15 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
425
428
  //
426
429
  // see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
427
430
 
431
+ // Use this if you notice weird scrolling problems on some browsers,
432
+ // the DOM might be a bit confused when this gets called so do this
433
+ // waits 1 ms (with setTimeout) until it does the activation
434
+ Field.scrollFreeActivate = function(field) {
435
+ setTimeout(function() {
436
+ Field.activate(field);
437
+ }, 1);
438
+ }
439
+
428
440
  Ajax.InPlaceEditor = Class.create();
429
441
  Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
430
442
  Ajax.InPlaceEditor.prototype = {
@@ -490,7 +502,7 @@ Ajax.InPlaceEditor.prototype = {
490
502
  Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
491
503
  }
492
504
  },
493
- enterEditMode: function() {
505
+ enterEditMode: function(evt) {
494
506
  if (this.saving) return;
495
507
  if (this.editing) return;
496
508
  this.editing = true;
@@ -501,11 +513,12 @@ Ajax.InPlaceEditor.prototype = {
501
513
  Element.hide(this.element);
502
514
  this.createForm();
503
515
  this.element.parentNode.insertBefore(this.form, this.element);
504
- Field.focus(this.editField);
516
+ Field.scrollFreeActivate(this.editField);
505
517
  // stop the event to avoid a page refresh in Safari
506
- if (arguments.length > 1) {
507
- Event.stop(arguments[0]);
518
+ if (evt) {
519
+ Event.stop(evt);
508
520
  }
521
+ return false;
509
522
  },
510
523
  createForm: function() {
511
524
  this.form = document.createElement("form");
@@ -280,7 +280,7 @@ Draggable.prototype = {
280
280
  style.position = "relative";
281
281
 
282
282
  if(this.options.zindex) {
283
- this.options.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
283
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
284
284
  style.zIndex = this.options.zindex;
285
285
  }
286
286
 
@@ -355,8 +355,8 @@ var Sortable = {
355
355
  hoverclass: null,
356
356
  ghosting: false,
357
357
  format: null,
358
- onChange: function() {},
359
- onUpdate: function() {}
358
+ onChange: Prototype.emptyFunction,
359
+ onUpdate: Prototype.emptyFunction
360
360
  }, arguments[1] || {});
361
361
 
362
362
  // clear any old sortable with same element
@@ -472,7 +472,10 @@ var Sortable = {
472
472
 
473
473
  onEmptyHover: function(element, dropon) {
474
474
  if(element.parentNode!=dropon) {
475
+ var oldParentNode = element.parentNode;
475
476
  dropon.appendChild(element);
477
+ Sortable.options(oldParentNode).onChange(element);
478
+ Sortable.options(dropon).onChange(element);
476
479
  }
477
480
  },
478
481
 
@@ -4,296 +4,181 @@
4
4
  // Mark Pilgrim (http://diveintomark.org/)
5
5
  // Martin Bialasinki
6
6
  //
7
- // See scriptaculous.js for full license.
8
-
9
- Object.debug = function(obj) {
10
- var info = [];
11
-
12
- if(typeof obj in ["string","number"]) {
13
- return obj;
14
- } else {
15
- for(property in obj)
16
- if(typeof obj[property]!="function")
17
- info.push(property + ' => ' +
18
- (typeof obj[property] == "string" ?
19
- '"' + obj[property] + '"' :
20
- obj[property]));
21
- }
22
-
23
- return ("'" + obj + "' #" + typeof obj +
24
- ": {" + info.join(", ") + "}");
25
- }
26
-
27
-
28
- /*--------------------------------------------------------------------------*/
29
-
30
- var Builder = {
31
- NODEMAP: {
32
- AREA: 'map',
33
- CAPTION: 'table',
34
- COL: 'table',
35
- COLGROUP: 'table',
36
- LEGEND: 'fieldset',
37
- OPTGROUP: 'select',
38
- OPTION: 'select',
39
- PARAM: 'object',
40
- TBODY: 'table',
41
- TD: 'table',
42
- TFOOT: 'table',
43
- TH: 'table',
44
- THEAD: 'table',
45
- TR: 'table'
46
- },
47
- // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
48
- // due to a Firefox bug
49
- node: function(elementName) {
50
- elementName = elementName.toUpperCase();
51
-
52
- // try innerHTML approach
53
- var parentTag = this.NODEMAP[elementName] || 'div';
54
- var parentElement = document.createElement(parentTag);
55
- parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
56
- var element = parentElement.firstChild || null;
57
-
58
- // see if browser added wrapping tags
59
- if(element && (element.tagName != elementName))
60
- element = element.getElementsByTagName(elementName)[0];
61
-
62
- // fallback to createElement approach
63
- if(!element) element = document.createElement(elementName);
64
-
65
- // abort if nothing could be created
66
- if(!element) return;
67
-
68
- // attributes (or text)
69
- if(arguments[1])
70
- if(this._isStringOrNumber(arguments[1]) ||
71
- (arguments[1] instanceof Array)) {
72
- this._children(element, arguments[1]);
73
- } else {
74
- var attrs = this._attributes(arguments[1]);
75
- if(attrs.length) {
76
- parentElement.innerHTML = "<" +elementName + " " +
77
- attrs + "></" + elementName + ">";
78
- element = parentElement.firstChild || null;
79
- // workaround firefox 1.0.X bug
80
- if(!element) {
81
- element = document.createElement(elementName);
82
- for(attr in arguments[1])
83
- element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
84
- }
85
- if(element.tagName != elementName)
86
- element = parentElement.getElementsByTagName(elementName)[0];
87
- }
88
- }
89
-
90
- // text, or array of children
91
- if(arguments[2])
92
- this._children(element, arguments[2]);
93
-
94
- return element;
95
- },
96
- _text: function(text) {
97
- return document.createTextNode(text);
98
- },
99
- _attributes: function(attributes) {
100
- var attrs = [];
101
- for(attribute in attributes)
102
- attrs.push((attribute=='className' ? 'class' : attribute) +
103
- '="' + attributes[attribute].toString().escapeHTML() + '"');
104
- return attrs.join(" ");
105
- },
106
- _children: function(element, children) {
107
- if(typeof children=='object') { // array can hold nodes and text
108
- children.flatten().each( function(e) {
109
- if(typeof e=='object')
110
- element.appendChild(e)
111
- else
112
- if(Builder._isStringOrNumber(e))
113
- element.appendChild(Builder._text(e));
114
- });
115
- } else
116
- if(Builder._isStringOrNumber(children))
117
- element.appendChild(Builder._text(children));
118
- },
119
- _isStringOrNumber: function(param) {
120
- return(typeof param=='string' || typeof param=='number');
121
- }
122
- }
123
-
124
- /* ------------- element ext -------------- */
125
-
126
- // converts rgb() and #xxx to #xxxxxx format,
127
- // returns self (or first argument) if not convertable
128
- String.prototype.parseColor = function() {
129
- color = "#";
130
- if(this.slice(0,4) == "rgb(") {
131
- var cols = this.slice(4,this.length-1).split(',');
132
- var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
133
- } else {
134
- if(this.slice(0,1) == '#') {
135
- if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
136
- if(this.length==7) color = this.toLowerCase();
137
- }
138
- }
139
- return(color.length==7 ? color : (arguments[0] || this));
140
- }
141
-
142
- Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
143
- var children = $(element).childNodes;
144
- var text = "";
145
- var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
146
-
147
- for (var i = 0; i < children.length; i++) {
148
- if(children[i].nodeType==3) {
149
- text+=children[i].nodeValue;
150
- } else {
151
- if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
152
- text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
153
- }
154
- }
155
-
156
- return text;
157
- }
158
-
159
- Element.setContentZoom = function(element, percent) {
160
- element = $(element);
161
- element.style.fontSize = (percent/100) + "em";
162
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
163
- }
164
-
165
- Element.getOpacity = function(element){
166
- var opacity;
167
- if (opacity = Element.getStyle(element, "opacity"))
168
- return parseFloat(opacity);
169
- if (opacity = (Element.getStyle(element, "filter") || '').match(/alpha\(opacity=(.*)\)/))
170
- if(opacity[1]) return parseFloat(opacity[1]) / 100;
171
- return 1.0;
172
- }
173
-
174
- Element.setOpacity = function(element, value){
175
- element= $(element);
176
- var els = element.style;
177
- if (value == 1){
178
- els.opacity = '0.999999';
179
- if(/MSIE/.test(navigator.userAgent))
180
- els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'');
181
- } else {
182
- if(value < 0.00001) value = 0;
183
- els.opacity = value;
184
- if(/MSIE/.test(navigator.userAgent))
185
- els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
186
- "alpha(opacity="+value*100+")";
7
+ // See scriptaculous.js for full license.
8
+
9
+ /* ------------- element ext -------------- */
10
+
11
+ // converts rgb() and #xxx to #xxxxxx format,
12
+ // returns self (or first argument) if not convertable
13
+ String.prototype.parseColor = function() {
14
+ color = "#";
15
+ if(this.slice(0,4) == "rgb(") {
16
+ var cols = this.slice(4,this.length-1).split(',');
17
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
18
+ } else {
19
+ if(this.slice(0,1) == '#') {
20
+ if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
21
+ if(this.length==7) color = this.toLowerCase();
22
+ }
187
23
  }
24
+ return(color.length==7 ? color : (arguments[0] || this));
25
+ }
26
+
27
+ Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
28
+ var children = $(element).childNodes;
29
+ var text = "";
30
+ var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
31
+
32
+ for (var i = 0; i < children.length; i++) {
33
+ if(children[i].nodeType==3) {
34
+ text+=children[i].nodeValue;
35
+ } else {
36
+ if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
37
+ text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
38
+ }
39
+ }
40
+
41
+ return text;
188
42
  }
189
43
 
190
- Element.getInlineOpacity = function(element){
191
- element= $(element);
192
- var op;
193
- op = element.style.opacity;
194
- if (typeof op != "undefined" && op != "") return op;
195
- return "";
196
- }
197
-
198
- Element.setInlineOpacity = function(element, value){
199
- element= $(element);
200
- var els = element.style;
201
- els.opacity = value;
202
- }
203
-
204
- /*--------------------------------------------------------------------------*/
205
-
206
- Element.Class = {
207
- // Element.toggleClass(element, className) toggles the class being on/off
208
- // Element.toggleClass(element, className1, className2) toggles between both classes,
209
- // defaulting to className1 if neither exist
210
- toggle: function(element, className) {
211
- if(Element.Class.has(element, className)) {
212
- Element.Class.remove(element, className);
213
- if(arguments.length == 3) Element.Class.add(element, arguments[2]);
214
- } else {
215
- Element.Class.add(element, className);
216
- if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
217
- }
218
- },
219
-
220
- // gets space-delimited classnames of an element as an array
221
- get: function(element) {
222
- return $(element).className.split(' ');
223
- },
224
-
225
- // functions adapted from original functions by Gavin Kistner
226
- remove: function(element) {
227
- element = $(element);
228
- var removeClasses = arguments;
229
- $R(1,arguments.length-1).each( function(index) {
230
- element.className =
231
- element.className.split(' ').reject(
232
- function(klass) { return (klass == removeClasses[index]) } ).join(' ');
233
- });
234
- },
235
-
236
- add: function(element) {
237
- element = $(element);
238
- for(var i = 1; i < arguments.length; i++) {
239
- Element.Class.remove(element, arguments[i]);
240
- element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
241
- }
242
- },
243
-
244
- // returns true if all given classes exist in said element
245
- has: function(element) {
246
- element = $(element);
247
- if(!element || !element.className) return false;
248
- var regEx;
249
- for(var i = 1; i < arguments.length; i++) {
250
- if((typeof arguments[i] == 'object') &&
251
- (arguments[i].constructor == Array)) {
252
- for(var j = 0; j < arguments[i].length; j++) {
253
- regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
254
- if(!regEx.test(element.className)) return false;
255
- }
256
- } else {
257
- regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
258
- if(!regEx.test(element.className)) return false;
259
- }
260
- }
261
- return true;
262
- },
263
-
264
- // expects arrays of strings and/or strings as optional paramters
265
- // Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
266
- has_any: function(element) {
267
- element = $(element);
268
- if(!element || !element.className) return false;
269
- var regEx;
270
- for(var i = 1; i < arguments.length; i++) {
271
- if((typeof arguments[i] == 'object') &&
272
- (arguments[i].constructor == Array)) {
273
- for(var j = 0; j < arguments[i].length; j++) {
274
- regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
275
- if(regEx.test(element.className)) return true;
276
- }
277
- } else {
278
- regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
279
- if(regEx.test(element.className)) return true;
280
- }
281
- }
282
- return false;
283
- },
284
-
285
- childrenWith: function(element, className) {
286
- var children = $(element).getElementsByTagName('*');
287
- var elements = new Array();
288
-
289
- for (var i = 0; i < children.length; i++)
290
- if (Element.Class.has(children[i], className))
291
- elements.push(children[i]);
292
-
293
- return elements;
294
- }
295
- }
296
-
44
+ Element.setContentZoom = function(element, percent) {
45
+ element = $(element);
46
+ element.style.fontSize = (percent/100) + "em";
47
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
48
+ }
49
+
50
+ Element.getOpacity = function(element){
51
+ var opacity;
52
+ if (opacity = Element.getStyle(element, "opacity"))
53
+ return parseFloat(opacity);
54
+ if (opacity = (Element.getStyle(element, "filter") || '').match(/alpha\(opacity=(.*)\)/))
55
+ if(opacity[1]) return parseFloat(opacity[1]) / 100;
56
+ return 1.0;
57
+ }
58
+
59
+ Element.setOpacity = function(element, value){
60
+ element= $(element);
61
+ var els = element.style;
62
+ if (value == 1){
63
+ els.opacity = '0.999999';
64
+ if(/MSIE/.test(navigator.userAgent))
65
+ els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'');
66
+ } else {
67
+ if(value < 0.00001) value = 0;
68
+ els.opacity = value;
69
+ if(/MSIE/.test(navigator.userAgent))
70
+ els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
71
+ "alpha(opacity="+value*100+")";
72
+ }
73
+ }
74
+
75
+ Element.getInlineOpacity = function(element){
76
+ element= $(element);
77
+ var op;
78
+ op = element.style.opacity;
79
+ if (typeof op != "undefined" && op != "") return op;
80
+ return "";
81
+ }
82
+
83
+ Element.setInlineOpacity = function(element, value){
84
+ element= $(element);
85
+ var els = element.style;
86
+ els.opacity = value;
87
+ }
88
+
89
+ /*--------------------------------------------------------------------------*/
90
+
91
+ Element.Class = {
92
+ // Element.toggleClass(element, className) toggles the class being on/off
93
+ // Element.toggleClass(element, className1, className2) toggles between both classes,
94
+ // defaulting to className1 if neither exist
95
+ toggle: function(element, className) {
96
+ if(Element.Class.has(element, className)) {
97
+ Element.Class.remove(element, className);
98
+ if(arguments.length == 3) Element.Class.add(element, arguments[2]);
99
+ } else {
100
+ Element.Class.add(element, className);
101
+ if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
102
+ }
103
+ },
104
+
105
+ // gets space-delimited classnames of an element as an array
106
+ get: function(element) {
107
+ return $(element).className.split(' ');
108
+ },
109
+
110
+ // functions adapted from original functions by Gavin Kistner
111
+ remove: function(element) {
112
+ element = $(element);
113
+ var removeClasses = arguments;
114
+ $R(1,arguments.length-1).each( function(index) {
115
+ element.className =
116
+ element.className.split(' ').reject(
117
+ function(klass) { return (klass == removeClasses[index]) } ).join(' ');
118
+ });
119
+ },
120
+
121
+ add: function(element) {
122
+ element = $(element);
123
+ for(var i = 1; i < arguments.length; i++) {
124
+ Element.Class.remove(element, arguments[i]);
125
+ element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
126
+ }
127
+ },
128
+
129
+ // returns true if all given classes exist in said element
130
+ has: function(element) {
131
+ element = $(element);
132
+ if(!element || !element.className) return false;
133
+ var regEx;
134
+ for(var i = 1; i < arguments.length; i++) {
135
+ if((typeof arguments[i] == 'object') &&
136
+ (arguments[i].constructor == Array)) {
137
+ for(var j = 0; j < arguments[i].length; j++) {
138
+ regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
139
+ if(!regEx.test(element.className)) return false;
140
+ }
141
+ } else {
142
+ regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
143
+ if(!regEx.test(element.className)) return false;
144
+ }
145
+ }
146
+ return true;
147
+ },
148
+
149
+ // expects arrays of strings and/or strings as optional paramters
150
+ // Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
151
+ has_any: function(element) {
152
+ element = $(element);
153
+ if(!element || !element.className) return false;
154
+ var regEx;
155
+ for(var i = 1; i < arguments.length; i++) {
156
+ if((typeof arguments[i] == 'object') &&
157
+ (arguments[i].constructor == Array)) {
158
+ for(var j = 0; j < arguments[i].length; j++) {
159
+ regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
160
+ if(regEx.test(element.className)) return true;
161
+ }
162
+ } else {
163
+ regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
164
+ if(regEx.test(element.className)) return true;
165
+ }
166
+ }
167
+ return false;
168
+ },
169
+
170
+ childrenWith: function(element, className) {
171
+ var children = $(element).getElementsByTagName('*');
172
+ var elements = new Array();
173
+
174
+ for (var i = 0; i < children.length; i++)
175
+ if (Element.Class.has(children[i], className))
176
+ elements.push(children[i]);
177
+
178
+ return elements;
179
+ }
180
+ }
181
+
297
182
  /*--------------------------------------------------------------------------*/
298
183
 
299
184
  var Effect = {
@@ -371,6 +256,9 @@ Effect.Transitions.full = function(pos) {
371
256
 
372
257
  Effect.Queue = {
373
258
  effects: [],
259
+ _each: function(iterator) {
260
+ this.effects._each(iterator);
261
+ },
374
262
  interval: null,
375
263
  add: function(effect) {
376
264
  var timestamp = new Date().getTime();
@@ -407,6 +295,7 @@ Effect.Queue = {
407
295
  this.effects.invoke('loop', timePos);
408
296
  }
409
297
  }
298
+ Object.extend(Effect.Queue, Enumerable);
410
299
 
411
300
  Effect.Base = function() {};
412
301
  Effect.Base.prototype = {
@@ -632,6 +521,8 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype),
632
521
  this.start(options);
633
522
  },
634
523
  setup: function() {
524
+ // Prevent executing on elements not in the layout flow
525
+ if(this.element.style.display=='none') { this.cancel(); return; }
635
526
  // Disable background image during the effect
636
527
  this.oldBgImage = this.element.style.backgroundImage;
637
528
  this.element.style.backgroundImage = "none";
@@ -862,7 +753,7 @@ Effect.SlideDown = function(element) {
862
753
  },
863
754
  afterUpdateInternal: function(effect) {
864
755
  effect.element.firstChild.style.bottom =
865
- (effect.originalHeight - effect.element.clientHeight) + 'px'; },
756
+ (effect.dims[0] - effect.element.clientHeight) + 'px'; },
866
757
  afterFinishInternal: function(effect) {
867
758
  Element.undoClipping(effect.element);
868
759
  Element.undoPositioned(effect.element.firstChild);
@@ -889,7 +780,7 @@ Effect.SlideUp = function(element) {
889
780
  },
890
781
  afterUpdateInternal: function(effect) {
891
782
  effect.element.firstChild.style.bottom =
892
- (effect.originalHeight - effect.element.clientHeight) + 'px'; },
783
+ (effect.dims[0] - effect.element.clientHeight) + 'px'; },
893
784
  afterFinishInternal: function(effect) {
894
785
  Element.hide(effect.element);
895
786
  Element.undoClipping(effect.element);
@@ -987,7 +878,7 @@ Effect.Grow = function(element) {
987
878
  els.top = oldTop;
988
879
  els.left = oldLeft;
989
880
  els.height = oldHeight;
990
- els.width = originalWidth;
881
+ els.width = originalWidth + 'px';
991
882
  Element.setInlineOpacity(el, oldOpacity);
992
883
  }
993
884
  }, options)