nitro 0.25.0 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/CHANGELOG +531 -1
  2. data/ProjectInfo +29 -5
  3. data/README +1 -1
  4. data/doc/AUTHORS +12 -6
  5. data/doc/RELEASES +114 -0
  6. data/lib/glue/sweeper.rb +71 -0
  7. data/lib/nitro.rb +19 -12
  8. data/lib/nitro/adapter/cgi.rb +4 -0
  9. data/lib/nitro/adapter/webrick.rb +4 -2
  10. data/lib/nitro/caching.rb +1 -0
  11. data/lib/nitro/caching/fragments.rb +7 -1
  12. data/lib/nitro/caching/output.rb +6 -1
  13. data/lib/nitro/caching/stores.rb +13 -1
  14. data/lib/nitro/cgi.rb +9 -1
  15. data/lib/nitro/cgi/request.rb +11 -3
  16. data/lib/nitro/cgi/utils.rb +24 -2
  17. data/lib/nitro/compiler.rb +89 -63
  18. data/lib/nitro/compiler/cleanup.rb +16 -0
  19. data/lib/nitro/compiler/elements.rb +117 -0
  20. data/lib/nitro/compiler/markup.rb +3 -1
  21. data/lib/nitro/compiler/morphing.rb +203 -73
  22. data/lib/nitro/compiler/script_generator.rb +14 -0
  23. data/lib/nitro/compiler/shaders.rb +1 -1
  24. data/lib/nitro/context.rb +5 -6
  25. data/lib/nitro/controller.rb +43 -21
  26. data/lib/nitro/dispatcher.rb +86 -37
  27. data/lib/nitro/element.rb +3 -105
  28. data/lib/nitro/helper/benchmark.rb +3 -0
  29. data/lib/nitro/helper/dojo.rb +0 -0
  30. data/lib/nitro/helper/form.rb +85 -255
  31. data/lib/nitro/helper/form/controls.rb +274 -0
  32. data/lib/nitro/helper/javascript.rb +86 -6
  33. data/lib/nitro/helper/pager.rb +5 -0
  34. data/lib/nitro/helper/prototype.rb +49 -0
  35. data/lib/nitro/helper/scriptaculous.rb +0 -0
  36. data/lib/nitro/helper/xhtml.rb +11 -8
  37. data/lib/nitro/helper/xml.rb +1 -1
  38. data/lib/nitro/routing.rb +8 -1
  39. data/lib/nitro/scaffolding.rb +344 -0
  40. data/lib/nitro/server.rb +5 -1
  41. data/lib/nitro/server/runner.rb +19 -15
  42. data/lib/nitro/session.rb +32 -56
  43. data/lib/nitro/session/drbserver.rb +1 -1
  44. data/lib/nitro/session/file.rb +34 -15
  45. data/lib/nitro/session/memory.rb +13 -4
  46. data/lib/nitro/session/og.rb +56 -0
  47. data/proto/public/js/controls.js +30 -1
  48. data/proto/public/js/dragdrop.js +211 -146
  49. data/proto/public/js/effects.js +261 -399
  50. data/proto/public/js/prototype.js +131 -72
  51. data/proto/public/scaffold/edit.xhtml +10 -3
  52. data/proto/public/scaffold/form.xhtml +1 -7
  53. data/proto/public/scaffold/index.xhtml +20 -0
  54. data/proto/public/scaffold/list.xhtml +15 -8
  55. data/proto/public/scaffold/new.xhtml +10 -3
  56. data/proto/public/scaffold/search.xhtml +28 -0
  57. data/proto/public/scaffold/view.xhtml +8 -0
  58. data/proto/run.rb +93 -1
  59. data/src/part/admin.rb +4 -2
  60. data/src/part/admin/controller.rb +62 -28
  61. data/src/part/admin/skin.rb +8 -8
  62. data/src/part/admin/system.css +135 -0
  63. data/src/part/admin/template/index.xhtml +8 -12
  64. data/test/nitro/caching/tc_stores.rb +17 -0
  65. data/test/nitro/tc_caching.rb +1 -4
  66. data/test/nitro/tc_dispatcher.rb +22 -10
  67. data/test/nitro/tc_element.rb +1 -1
  68. data/test/nitro/tc_session.rb +23 -11
  69. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  70. metadata +29 -15
  71. data/lib/nitro/dispatcher/general.rb +0 -62
  72. data/lib/nitro/dispatcher/nice.rb +0 -57
  73. data/lib/nitro/scaffold.rb +0 -171
  74. data/proto/public/index.xhtml +0 -83
  75. data/proto/public/js/scaffold.js +0 -74
  76. data/proto/public/settings.xhtml +0 -66
@@ -1,4 +1,4 @@
1
- /* Prototype JavaScript framework, version 1.4.0_rc2
1
+ /* Prototype JavaScript framework, version 1.4.0
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',
15
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
15
16
 
16
17
  emptyFunction: function() {},
17
18
  K: function(x) {return x}
@@ -45,10 +46,10 @@ Object.inspect = function(object) {
45
46
  }
46
47
  }
47
48
 
48
- Function.prototype.bind = function(object) {
49
- var __method = this;
49
+ Function.prototype.bind = function() {
50
+ var __method = this, args = $A(arguments), object = args.shift();
50
51
  return function() {
51
- return __method.apply(object, arguments);
52
+ return __method.apply(object, args.concat($A(arguments)));
52
53
  }
53
54
  }
54
55
 
@@ -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;
@@ -376,6 +393,7 @@ Object.extend(Enumerable, {
376
393
  entries: Enumerable.toArray
377
394
  });
378
395
  var $A = Array.from = function(iterable) {
396
+ if (!iterable) return [];
379
397
  if (iterable.toArray) {
380
398
  return iterable.toArray();
381
399
  } else {
@@ -388,12 +406,19 @@ var $A = Array.from = function(iterable) {
388
406
 
389
407
  Object.extend(Array.prototype, Enumerable);
390
408
 
409
+ Array.prototype._reverse = Array.prototype.reverse;
410
+
391
411
  Object.extend(Array.prototype, {
392
412
  _each: function(iterator) {
393
413
  for (var i = 0; i < this.length; i++)
394
414
  iterator(this[i]);
395
415
  },
396
416
 
417
+ clear: function() {
418
+ this.length = 0;
419
+ return this;
420
+ },
421
+
397
422
  first: function() {
398
423
  return this[0];
399
424
  },
@@ -425,13 +450,18 @@ Object.extend(Array.prototype, {
425
450
  indexOf: function(object) {
426
451
  for (var i = 0; i < this.length; i++)
427
452
  if (this[i] == object) return i;
428
- return false;
453
+ return -1;
429
454
  },
430
455
 
431
- reverse: function() {
432
- var result = [];
433
- for (var i = this.length; i > 0; i--)
434
- result.push(this[i-1]);
456
+ reverse: function(inline) {
457
+ return (inline !== false ? this : this.toArray())._reverse();
458
+ },
459
+
460
+ shift: function() {
461
+ var result = this[0];
462
+ for (var i = 0; i < this.length - 1; i++)
463
+ this[i] = this[i + 1];
464
+ this.length--;
435
465
  return result;
436
466
  },
437
467
 
@@ -486,9 +516,9 @@ function $H(object) {
486
516
  Object.extend(hash, Hash);
487
517
  return hash;
488
518
  }
489
- var Range = Class.create();
490
- Object.extend(Range.prototype, Enumerable);
491
- Object.extend(Range.prototype, {
519
+ ObjectRange = Class.create();
520
+ Object.extend(ObjectRange.prototype, Enumerable);
521
+ Object.extend(ObjectRange.prototype, {
492
522
  initialize: function(start, end, exclusive) {
493
523
  this.start = start;
494
524
  this.end = end;
@@ -513,7 +543,7 @@ Object.extend(Range.prototype, {
513
543
  });
514
544
 
515
545
  var $R = function(start, end, exclusive) {
516
- return new Range(start, end, exclusive);
546
+ return new ObjectRange(start, end, exclusive);
517
547
  }
518
548
 
519
549
  var Ajax = {
@@ -549,8 +579,7 @@ Ajax.Responders = {
549
579
  if (responder[callback] && typeof responder[callback] == 'function') {
550
580
  try {
551
581
  responder[callback].apply(responder, [request, transport, json]);
552
- } catch (e) {
553
- }
582
+ } catch (e) {}
554
583
  }
555
584
  });
556
585
  }
@@ -626,8 +655,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
626
655
  this.transport.send(this.options.method == 'post' ? body : null);
627
656
 
628
657
  } catch (e) {
629
- (this.options.onException || Prototype.emptyFunction)(this, e);
630
- Ajax.Responders.dispatch('onException', this, e);
658
+ this.dispatchException(e);
631
659
  }
632
660
  },
633
661
 
@@ -661,12 +689,23 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
661
689
  this.respondToReadyState(this.transport.readyState);
662
690
  },
663
691
 
692
+ header: function(name) {
693
+ try {
694
+ return this.transport.getResponseHeader(name);
695
+ } catch (e) {}
696
+ },
697
+
664
698
  evalJSON: function() {
665
699
  try {
666
- var json = this.transport.getResponseHeader('X-JSON'), object;
667
- object = eval(json);
668
- return object;
700
+ return eval(this.header('X-JSON'));
701
+ } catch (e) {}
702
+ },
703
+
704
+ evalResponse: function() {
705
+ try {
706
+ return eval(this.transport.responseText);
669
707
  } catch (e) {
708
+ this.dispatchException(e);
670
709
  }
671
710
  },
672
711
 
@@ -674,22 +713,38 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
674
713
  var event = Ajax.Request.Events[readyState];
675
714
  var transport = this.transport, json = this.evalJSON();
676
715
 
677
- if (event == 'Complete')
678
- (this.options['on' + this.transport.status]
679
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
680
- || Prototype.emptyFunction)(transport, json);
716
+ if (event == 'Complete') {
717
+ try {
718
+ (this.options['on' + this.transport.status]
719
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
720
+ || Prototype.emptyFunction)(transport, json);
721
+ } catch (e) {
722
+ this.dispatchException(e);
723
+ }
681
724
 
682
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
683
- Ajax.Responders.dispatch('on' + event, this, transport, json);
725
+ if ((this.header('Content-type') || '').match(/^text\/javascript/i))
726
+ this.evalResponse();
727
+ }
728
+
729
+ try {
730
+ (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
731
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
732
+ } catch (e) {
733
+ this.dispatchException(e);
734
+ }
684
735
 
685
736
  /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
686
737
  if (event == 'Complete')
687
738
  this.transport.onreadystatechange = Prototype.emptyFunction;
739
+ },
740
+
741
+ dispatchException: function(exception) {
742
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
743
+ Ajax.Responders.dispatch('onException', this, exception);
688
744
  }
689
745
  });
690
746
 
691
747
  Ajax.Updater = Class.create();
692
- Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
693
748
 
694
749
  Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
695
750
  initialize: function(container, url, options) {
@@ -714,16 +769,16 @@ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
714
769
  updateContent: function() {
715
770
  var receiver = this.responseIsSuccess() ?
716
771
  this.containers.success : this.containers.failure;
772
+ var response = this.transport.responseText;
717
773
 
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);
774
+ if (!this.options.evalScripts)
775
+ response = response.stripScripts();
721
776
 
722
777
  if (receiver) {
723
778
  if (this.options.insertion) {
724
779
  new this.options.insertion(receiver, response);
725
780
  } else {
726
- receiver.innerHTML = response;
781
+ Element.update(receiver, response);
727
782
  }
728
783
  }
729
784
 
@@ -731,14 +786,6 @@ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
731
786
  if (this.onComplete)
732
787
  setTimeout(this.onComplete.bind(this), 10);
733
788
  }
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
789
  }
743
790
  });
744
791
 
@@ -830,6 +877,11 @@ Object.extend(Element, {
830
877
  element.parentNode.removeChild(element);
831
878
  },
832
879
 
880
+ update: function(element, html) {
881
+ $(element).innerHTML = html.stripScripts();
882
+ setTimeout(function() {html.evalScripts()}, 10);
883
+ },
884
+
833
885
  getHeight: function(element) {
834
886
  element = $(element);
835
887
  return element.offsetHeight;
@@ -893,6 +945,12 @@ Object.extend(Element, {
893
945
  return value == 'auto' ? null : value;
894
946
  },
895
947
 
948
+ setStyle: function(element, style) {
949
+ element = $(element);
950
+ for (name in style)
951
+ element.style[name.camelize()] = style[name];
952
+ },
953
+
896
954
  getDimensions: function(element) {
897
955
  element = $(element);
898
956
  if (Element.getStyle(element, 'display') != 'none')
@@ -969,7 +1027,7 @@ Abstract.Insertion = function(adjacency) {
969
1027
  Abstract.Insertion.prototype = {
970
1028
  initialize: function(element, content) {
971
1029
  this.element = $(element);
972
- this.content = content;
1030
+ this.content = content.stripScripts();
973
1031
 
974
1032
  if (this.adjacency && this.element.insertAdjacentHTML) {
975
1033
  try {
@@ -986,6 +1044,8 @@ Abstract.Insertion.prototype = {
986
1044
  if (this.initializeRange) this.initializeRange();
987
1045
  this.insertContent([this.range.createContextualFragment(this.content)]);
988
1046
  }
1047
+
1048
+ setTimeout(function() {content.evalScripts()}, 10);
989
1049
  },
990
1050
 
991
1051
  contentFromAnonymousTable: function() {
@@ -1018,7 +1078,7 @@ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1018
1078
  },
1019
1079
 
1020
1080
  insertContent: function(fragments) {
1021
- fragments.reverse().each((function(fragment) {
1081
+ fragments.reverse(false).each((function(fragment) {
1022
1082
  this.element.insertBefore(fragment, this.element.firstChild);
1023
1083
  }).bind(this));
1024
1084
  }
@@ -1079,7 +1139,7 @@ Element.ClassNames.prototype = {
1079
1139
  if (!this.include(classNameToRemove)) return;
1080
1140
  this.set(this.select(function(className) {
1081
1141
  return className != classNameToRemove;
1082
- }));
1142
+ }).join(' '));
1083
1143
  },
1084
1144
 
1085
1145
  toString: function() {
@@ -1109,8 +1169,10 @@ var Field = {
1109
1169
  },
1110
1170
 
1111
1171
  activate: function(element) {
1112
- $(element).focus();
1113
- $(element).select();
1172
+ element = $(element);
1173
+ element.focus();
1174
+ if (element.select)
1175
+ element.select();
1114
1176
  }
1115
1177
  }
1116
1178
 
@@ -1178,16 +1240,15 @@ var Form = {
1178
1240
  }
1179
1241
  },
1180
1242
 
1243
+ findFirstElement: function(form) {
1244
+ return Form.getElements(form).find(function(element) {
1245
+ return element.type != 'hidden' && !element.disabled &&
1246
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1247
+ });
1248
+ },
1249
+
1181
1250
  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
- }
1251
+ Field.activate(Form.findFirstElement(form));
1191
1252
  },
1192
1253
 
1193
1254
  reset: function(form) {
@@ -1201,9 +1262,17 @@ Form.Element = {
1201
1262
  var method = element.tagName.toLowerCase();
1202
1263
  var parameter = Form.Element.Serializers[method](element);
1203
1264
 
1204
- if (parameter)
1205
- return encodeURIComponent(parameter[0]) + '=' +
1206
- encodeURIComponent(parameter[1]);
1265
+ if (parameter) {
1266
+ var key = encodeURIComponent(parameter[0]);
1267
+ if (key.length == 0) return;
1268
+
1269
+ if (parameter[1].constructor != Array)
1270
+ parameter[1] = [parameter[1]];
1271
+
1272
+ return parameter[1].map(function(value) {
1273
+ return key + '=' + encodeURIComponent(value);
1274
+ }).join('&');
1275
+ }
1207
1276
  },
1208
1277
 
1209
1278
  getValue: function(element) {
@@ -1349,24 +1418,14 @@ Abstract.EventObserver.prototype = {
1349
1418
  switch (element.type.toLowerCase()) {
1350
1419
  case 'checkbox':
1351
1420
  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
- }
1421
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
1358
1422
  break;
1359
1423
  case 'password':
1360
1424
  case 'text':
1361
1425
  case 'textarea':
1362
1426
  case 'select-one':
1363
1427
  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
- }
1428
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
1370
1429
  break;
1371
1430
  }
1372
1431
  }
@@ -1,4 +1,11 @@
1
- <SystemPage name="Edit %name%">
2
- <h2><a href="#@base/%name_plural%">List of %name_plural%</a></h2>
3
- #{form_for(@%name%)}
1
+ <SystemPage>
2
+ <?r base = "#{@base}/%base%" ?>
3
+ <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > Edit %name%</h1>
4
+ <?r if @all ?>
5
+ <a href="#{request.uri.gsub(/\/all$/, '')}">Show editable</a>
6
+ #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list", :all => true}
7
+ <?r else ?>
8
+ <a href="#{request.uri}/all">Show all</a>
9
+ #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list"}
10
+ <?r end ?>
4
11
  </SystemPage>
@@ -1,7 +1 @@
1
- <SystemPage name="Edit %name%">
2
- <h2><a href="#@base/%name_plural%">List of %name_plural%</a></h2>
3
- <?r if errors = session[:ERRORS] ?>
4
- <span class="errors">ERRORS</span>
5
- <?r end ?>
6
- #{form_for(@%name%)}
7
- </SystemPage>
1
+ #{form_for(@%name%)}
@@ -0,0 +1,20 @@
1
+ <SystemPage>
2
+ <?r base = "#{@base}/%base%" ?>
3
+ <h1>#{"%plural%".humanize}</h1>
4
+ <h2><a href="#{base}/new">New %name%</a></h2>
5
+ <form action="search">
6
+ Search %plural%: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
7
+ </form>
8
+ <table>
9
+ <?r for obj in @list ?>
10
+ <tr>
11
+ <td width="100%"><a href="#{base}/edit/#{obj.oid}">#{obj.to_s}</a></td>
12
+ <?r if obj.respond_to?(:update_time) ?>
13
+ <td nowrap="1">#{obj.update_time.stamp(:db)}</td>
14
+ <?r end ?>
15
+ <td><a href="#{base}/edit/#{obj.oid}">edit</a></td>
16
+ <td><a href="#{base}/delete/#{obj.oid}">del</a></td>
17
+ </tr>
18
+ <?r end ?>
19
+ </table>
20
+ </SystemPage>