actionpack 1.10.2 → 1.11.0

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

Potentially problematic release.


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

Files changed (43) hide show
  1. data/CHANGELOG +57 -3
  2. data/README +7 -7
  3. data/lib/action_controller/assertions.rb +28 -11
  4. data/lib/action_controller/base.rb +22 -15
  5. data/lib/action_controller/caching.rb +6 -6
  6. data/lib/action_controller/components.rb +1 -1
  7. data/lib/action_controller/cookies.rb +3 -3
  8. data/lib/action_controller/dependencies.rb +1 -1
  9. data/lib/action_controller/filters.rb +40 -3
  10. data/lib/action_controller/flash.rb +4 -0
  11. data/lib/action_controller/helpers.rb +1 -1
  12. data/lib/action_controller/layout.rb +2 -1
  13. data/lib/action_controller/pagination.rb +2 -1
  14. data/lib/action_controller/rescue.rb +1 -1
  15. data/lib/action_controller/session/active_record_store.rb +18 -29
  16. data/lib/action_controller/templates/rescues/_trace.rhtml +0 -3
  17. data/lib/action_controller/templates/scaffolds/layout.rhtml +1 -1
  18. data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
  19. data/lib/action_pack.rb +24 -0
  20. data/lib/action_pack/version.rb +2 -2
  21. data/lib/action_view/base.rb +1 -1
  22. data/lib/action_view/helpers/asset_tag_helper.rb +21 -3
  23. data/lib/action_view/helpers/form_options_helper.rb +1 -1
  24. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  25. data/lib/action_view/helpers/javascripts/controls.js +18 -5
  26. data/lib/action_view/helpers/javascripts/dragdrop.js +6 -3
  27. data/lib/action_view/helpers/javascripts/effects.js +181 -290
  28. data/lib/action_view/helpers/javascripts/prototype.js +8 -8
  29. data/lib/action_view/helpers/text_helper.rb +22 -0
  30. data/lib/action_view/helpers/url_helper.rb +1 -1
  31. data/lib/action_view/template_error.rb +2 -1
  32. data/rakefile +1 -1
  33. data/test/controller/components_test.rb +5 -0
  34. data/test/controller/filters_test.rb +2 -1
  35. data/test/controller/flash_test.rb +6 -0
  36. data/test/controller/new_render_test.rb +11 -0
  37. data/test/controller/redirect_test.rb +10 -0
  38. data/test/fixtures/layouts/standard.rhtml +1 -1
  39. data/test/template/asset_tag_helper_test.rb +19 -2
  40. data/test/template/javascript_helper_test.rb +1 -0
  41. data/test/template/text_helper_test.rb +9 -0
  42. metadata +5 -4
  43. data/lib/action_view/helpers/javascripts/slider.js +0 -258
@@ -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)