actionpack 1.11.0 → 1.11.1

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 (40) hide show
  1. data/CHANGELOG +45 -0
  2. data/lib/action_controller/assertions.rb +1 -1
  3. data/lib/action_controller/base.rb +24 -12
  4. data/lib/action_controller/caching.rb +1 -0
  5. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +1 -0
  6. data/lib/action_controller/cgi_process.rb +44 -27
  7. data/lib/action_controller/components.rb +2 -2
  8. data/lib/action_controller/flash.rb +16 -7
  9. data/lib/action_controller/helpers.rb +12 -1
  10. data/lib/action_controller/layout.rb +3 -1
  11. data/lib/action_controller/macros/in_place_editing.rb +1 -1
  12. data/lib/action_controller/request.rb +20 -16
  13. data/lib/action_controller/session/active_record_store.rb +57 -51
  14. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -2
  15. data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -1
  16. data/lib/action_controller/vendor/html-scanner/html/node.rb.rej +17 -0
  17. data/lib/action_pack/version.rb +2 -2
  18. data/lib/action_view/base.rb +4 -5
  19. data/lib/action_view/helpers/asset_tag_helper.rb +2 -2
  20. data/lib/action_view/helpers/form_options_helper.rb +1 -1
  21. data/lib/action_view/helpers/form_tag_helper.rb +1 -1
  22. data/lib/action_view/helpers/java_script_macros_helper.rb +11 -9
  23. data/lib/action_view/helpers/javascripts/controls.js +30 -1
  24. data/lib/action_view/helpers/javascripts/dragdrop.js +37 -17
  25. data/lib/action_view/helpers/javascripts/effects.js +3 -91
  26. data/lib/action_view/helpers/javascripts/prototype.js +109 -67
  27. data/lib/action_view/helpers/text_helper.rb +30 -9
  28. data/rakefile +2 -2
  29. data/test/controller/active_record_assertions_test.rb +1 -0
  30. data/test/controller/active_record_store_test.rb +12 -6
  31. data/test/controller/flash_test.rb +1 -1
  32. data/test/controller/helper_test.rb +21 -5
  33. data/test/controller/new_render_test.rb +31 -0
  34. data/test/controller/request_test.rb +5 -0
  35. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  36. data/test/fixtures/test/render_file_with_ivar.rhtml +1 -0
  37. data/test/fixtures/test/render_file_with_locals.rhtml +1 -0
  38. data/test/template/form_options_helper_test.rb +16 -6
  39. data/test/template/text_helper_test.rb +7 -0
  40. metadata +7 -3
@@ -86,97 +86,9 @@ Element.setInlineOpacity = function(element, value){
86
86
  els.opacity = value;
87
87
  }
88
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
- }
89
+ Element.childrenWithClassName = function(element, className) {
90
+ return $A($(element).getElementsByTagName('*')).select(
91
+ function(c) { return Element.hasClassName(c, className) });
180
92
  }
181
93
 
182
94
  /*--------------------------------------------------------------------------*/
@@ -1,4 +1,4 @@
1
- /* Prototype JavaScript framework, version 1.4.0_rc2
1
+ /* Prototype JavaScript framework, version 1.4.0_rc4
2
2
  * (c) 2005 Sam Stephenson <sam@conio.net>
3
3
  *
4
4
  * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
@@ -11,7 +11,8 @@
11
11
  /*--------------------------------------------------------------------------*/
12
12
 
13
13
  var Prototype = {
14
- Version: '1.4.0_rc2',
14
+ Version: '1.4.0_rc4',
15
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
15
16
 
16
17
  emptyFunction: function() {},
17
18
  K: function(x) {return x}
@@ -143,6 +144,22 @@ Object.extend(String.prototype, {
143
144
  return this.replace(/<\/?[^>]+>/gi, '');
144
145
  },
145
146
 
147
+ stripScripts: function() {
148
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
149
+ },
150
+
151
+ extractScripts: function() {
152
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
153
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
154
+ return (this.match(matchAll) || []).map(function(scriptTag) {
155
+ return (scriptTag.match(matchOne) || ['', ''])[1];
156
+ });
157
+ },
158
+
159
+ evalScripts: function() {
160
+ return this.extractScripts().map(eval);
161
+ },
162
+
146
163
  escapeHTML: function() {
147
164
  var div = document.createElement('div');
148
165
  var text = document.createTextNode(this);
@@ -214,8 +231,8 @@ var Enumerable = {
214
231
  all: function(iterator) {
215
232
  var result = true;
216
233
  this.each(function(value, index) {
217
- if (!(result &= (iterator || Prototype.K)(value, index)))
218
- throw $break;
234
+ result = result && !!(iterator || Prototype.K)(value, index);
235
+ if (!result) throw $break;
219
236
  });
220
237
  return result;
221
238
  },
@@ -223,7 +240,7 @@ var Enumerable = {
223
240
  any: function(iterator) {
224
241
  var result = true;
225
242
  this.each(function(value, index) {
226
- if (result &= (iterator || Prototype.K)(value, index))
243
+ if (result = !!(iterator || Prototype.K)(value, index))
227
244
  throw $break;
228
245
  });
229
246
  return result;
@@ -388,12 +405,19 @@ var $A = Array.from = function(iterable) {
388
405
 
389
406
  Object.extend(Array.prototype, Enumerable);
390
407
 
408
+ Array.prototype._reverse = Array.prototype.reverse;
409
+
391
410
  Object.extend(Array.prototype, {
392
411
  _each: function(iterator) {
393
412
  for (var i = 0; i < this.length; i++)
394
413
  iterator(this[i]);
395
414
  },
396
415
 
416
+ clear: function() {
417
+ this.length = 0;
418
+ return this;
419
+ },
420
+
397
421
  first: function() {
398
422
  return this[0];
399
423
  },
@@ -425,14 +449,11 @@ Object.extend(Array.prototype, {
425
449
  indexOf: function(object) {
426
450
  for (var i = 0; i < this.length; i++)
427
451
  if (this[i] == object) return i;
428
- return false;
452
+ return -1;
429
453
  },
430
454
 
431
- reverse: function() {
432
- var result = [];
433
- for (var i = this.length; i > 0; i--)
434
- result.push(this[i-1]);
435
- return result;
455
+ reverse: function(inline) {
456
+ return (inline !== false ? this : this.toArray())._reverse();
436
457
  },
437
458
 
438
459
  inspect: function() {
@@ -486,9 +507,9 @@ function $H(object) {
486
507
  Object.extend(hash, Hash);
487
508
  return hash;
488
509
  }
489
- var Range = Class.create();
490
- Object.extend(Range.prototype, Enumerable);
491
- Object.extend(Range.prototype, {
510
+ ObjectRange = Class.create();
511
+ Object.extend(ObjectRange.prototype, Enumerable);
512
+ Object.extend(ObjectRange.prototype, {
492
513
  initialize: function(start, end, exclusive) {
493
514
  this.start = start;
494
515
  this.end = end;
@@ -513,7 +534,7 @@ Object.extend(Range.prototype, {
513
534
  });
514
535
 
515
536
  var $R = function(start, end, exclusive) {
516
- return new Range(start, end, exclusive);
537
+ return new ObjectRange(start, end, exclusive);
517
538
  }
518
539
 
519
540
  var Ajax = {
@@ -549,8 +570,7 @@ Ajax.Responders = {
549
570
  if (responder[callback] && typeof responder[callback] == 'function') {
550
571
  try {
551
572
  responder[callback].apply(responder, [request, transport, json]);
552
- } catch (e) {
553
- }
573
+ } catch (e) {}
554
574
  }
555
575
  });
556
576
  }
@@ -626,8 +646,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
626
646
  this.transport.send(this.options.method == 'post' ? body : null);
627
647
 
628
648
  } catch (e) {
629
- (this.options.onException || Prototype.emptyFunction)(this, e);
630
- Ajax.Responders.dispatch('onException', this, e);
649
+ this.dispatchException(e);
631
650
  }
632
651
  },
633
652
 
@@ -661,12 +680,23 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
661
680
  this.respondToReadyState(this.transport.readyState);
662
681
  },
663
682
 
683
+ header: function(name) {
684
+ try {
685
+ return this.transport.getResponseHeader(name);
686
+ } catch (e) {}
687
+ },
688
+
664
689
  evalJSON: function() {
665
690
  try {
666
- var json = this.transport.getResponseHeader('X-JSON'), object;
667
- object = eval(json);
668
- return object;
691
+ return eval(this.header('X-JSON'));
692
+ } catch (e) {}
693
+ },
694
+
695
+ evalResponse: function() {
696
+ try {
697
+ return eval(this.transport.responseText);
669
698
  } catch (e) {
699
+ this.dispatchException(e);
670
700
  }
671
701
  },
672
702
 
@@ -674,22 +704,38 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
674
704
  var event = Ajax.Request.Events[readyState];
675
705
  var transport = this.transport, json = this.evalJSON();
676
706
 
677
- if (event == 'Complete')
678
- (this.options['on' + this.transport.status]
679
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
680
- || Prototype.emptyFunction)(transport, json);
707
+ if (event == 'Complete') {
708
+ try {
709
+ (this.options['on' + this.transport.status]
710
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
711
+ || Prototype.emptyFunction)(transport, json);
712
+ } catch (e) {
713
+ this.dispatchException(e);
714
+ }
681
715
 
682
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
683
- Ajax.Responders.dispatch('on' + event, this, transport, json);
716
+ if ((this.header('Content-type') || '').match(/^text\/javascript/i))
717
+ this.evalResponse();
718
+ }
719
+
720
+ try {
721
+ (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
722
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
723
+ } catch (e) {
724
+ this.dispatchException(e);
725
+ }
684
726
 
685
727
  /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
686
728
  if (event == 'Complete')
687
729
  this.transport.onreadystatechange = Prototype.emptyFunction;
730
+ },
731
+
732
+ dispatchException: function(exception) {
733
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
734
+ Ajax.Responders.dispatch('onException', this, exception);
688
735
  }
689
736
  });
690
737
 
691
738
  Ajax.Updater = Class.create();
692
- Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
693
739
 
694
740
  Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
695
741
  initialize: function(container, url, options) {
@@ -714,16 +760,16 @@ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
714
760
  updateContent: function() {
715
761
  var receiver = this.responseIsSuccess() ?
716
762
  this.containers.success : this.containers.failure;
763
+ var response = this.transport.responseText;
717
764
 
718
- var match = new RegExp(Ajax.Updater.ScriptFragment, 'img');
719
- var response = this.transport.responseText.replace(match, '');
720
- var scripts = this.transport.responseText.match(match);
765
+ if (!this.options.evalScripts)
766
+ response = response.stripScripts();
721
767
 
722
768
  if (receiver) {
723
769
  if (this.options.insertion) {
724
770
  new this.options.insertion(receiver, response);
725
771
  } else {
726
- receiver.innerHTML = response;
772
+ Element.update(receiver, response);
727
773
  }
728
774
  }
729
775
 
@@ -731,14 +777,6 @@ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
731
777
  if (this.onComplete)
732
778
  setTimeout(this.onComplete.bind(this), 10);
733
779
  }
734
-
735
- if (this.options.evalScripts && scripts) {
736
- match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
737
- setTimeout((function() {
738
- for (var i = 0; i < scripts.length; i++)
739
- eval(scripts[i].match(match)[1]);
740
- }).bind(this), 10);
741
- }
742
780
  }
743
781
  });
744
782
 
@@ -830,6 +868,11 @@ Object.extend(Element, {
830
868
  element.parentNode.removeChild(element);
831
869
  },
832
870
 
871
+ update: function(element, html) {
872
+ $(element).innerHTML = html.stripScripts();
873
+ setTimeout(function() {html.evalScripts()}, 10);
874
+ },
875
+
833
876
  getHeight: function(element) {
834
877
  element = $(element);
835
878
  return element.offsetHeight;
@@ -893,6 +936,12 @@ Object.extend(Element, {
893
936
  return value == 'auto' ? null : value;
894
937
  },
895
938
 
939
+ setStyle: function(element, style) {
940
+ element = $(element);
941
+ for (name in style)
942
+ element.style[name.camelize()] = style[name];
943
+ },
944
+
896
945
  getDimensions: function(element) {
897
946
  element = $(element);
898
947
  if (Element.getStyle(element, 'display') != 'none')
@@ -969,7 +1018,7 @@ Abstract.Insertion = function(adjacency) {
969
1018
  Abstract.Insertion.prototype = {
970
1019
  initialize: function(element, content) {
971
1020
  this.element = $(element);
972
- this.content = content;
1021
+ this.content = content.stripScripts();
973
1022
 
974
1023
  if (this.adjacency && this.element.insertAdjacentHTML) {
975
1024
  try {
@@ -986,6 +1035,8 @@ Abstract.Insertion.prototype = {
986
1035
  if (this.initializeRange) this.initializeRange();
987
1036
  this.insertContent([this.range.createContextualFragment(this.content)]);
988
1037
  }
1038
+
1039
+ setTimeout(function() {content.evalScripts()}, 10);
989
1040
  },
990
1041
 
991
1042
  contentFromAnonymousTable: function() {
@@ -1018,7 +1069,7 @@ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1018
1069
  },
1019
1070
 
1020
1071
  insertContent: function(fragments) {
1021
- fragments.reverse().each((function(fragment) {
1072
+ fragments.reverse(false).each((function(fragment) {
1022
1073
  this.element.insertBefore(fragment, this.element.firstChild);
1023
1074
  }).bind(this));
1024
1075
  }
@@ -1079,7 +1130,7 @@ Element.ClassNames.prototype = {
1079
1130
  if (!this.include(classNameToRemove)) return;
1080
1131
  this.set(this.select(function(className) {
1081
1132
  return className != classNameToRemove;
1082
- }));
1133
+ }).join(' '));
1083
1134
  },
1084
1135
 
1085
1136
  toString: function() {
@@ -1109,8 +1160,10 @@ var Field = {
1109
1160
  },
1110
1161
 
1111
1162
  activate: function(element) {
1112
- $(element).focus();
1113
- $(element).select();
1163
+ element = $(element);
1164
+ element.focus();
1165
+ if (element.select)
1166
+ element.select();
1114
1167
  }
1115
1168
  }
1116
1169
 
@@ -1178,16 +1231,15 @@ var Form = {
1178
1231
  }
1179
1232
  },
1180
1233
 
1234
+ findFirstElement: function(form) {
1235
+ return Form.getElements(form).find(function(element) {
1236
+ return element.type != 'hidden' && !element.disabled &&
1237
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1238
+ });
1239
+ },
1240
+
1181
1241
  focusFirstElement: function(form) {
1182
- form = $(form);
1183
- var elements = Form.getElements(form);
1184
- for (var i = 0; i < elements.length; i++) {
1185
- var element = elements[i];
1186
- if (element.type != 'hidden' && !element.disabled) {
1187
- Field.activate(element);
1188
- break;
1189
- }
1190
- }
1242
+ Field.activate(Form.findFirstElement(form));
1191
1243
  },
1192
1244
 
1193
1245
  reset: function(form) {
@@ -1349,24 +1401,14 @@ Abstract.EventObserver.prototype = {
1349
1401
  switch (element.type.toLowerCase()) {
1350
1402
  case 'checkbox':
1351
1403
  case 'radio':
1352
- element.target = this;
1353
- element.prev_onclick = element.onclick || Prototype.emptyFunction;
1354
- element.onclick = function() {
1355
- this.prev_onclick();
1356
- this.target.onElementEvent();
1357
- }
1404
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
1358
1405
  break;
1359
1406
  case 'password':
1360
1407
  case 'text':
1361
1408
  case 'textarea':
1362
1409
  case 'select-one':
1363
1410
  case 'select-multiple':
1364
- element.target = this;
1365
- element.prev_onchange = element.onchange || Prototype.emptyFunction;
1366
- element.onchange = function() {
1367
- this.prev_onchange();
1368
- this.target.onElementEvent();
1369
- }
1411
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
1370
1412
  break;
1371
1413
  }
1372
1414
  }