nitro 0.28.0 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/CHANGELOG +382 -0
  2. data/ProjectInfo +4 -4
  3. data/README +1 -1
  4. data/doc/AUTHORS +15 -15
  5. data/doc/MIGRATION +13 -0
  6. data/doc/RELEASES +102 -0
  7. data/lib/glue/sweeper.rb +1 -1
  8. data/lib/nitro.rb +38 -9
  9. data/lib/nitro/adapter/acgi.rb +1 -3
  10. data/lib/nitro/adapter/cgi.rb +1 -1
  11. data/lib/nitro/adapter/fastcgi.rb +1 -3
  12. data/lib/nitro/adapter/mongrel.rb +8 -6
  13. data/lib/nitro/adapter/webrick.rb +1 -2
  14. data/lib/nitro/cgi.rb +1 -1
  15. data/lib/nitro/compiler.rb +21 -40
  16. data/lib/nitro/compiler/elements.rb +72 -32
  17. data/lib/nitro/compiler/errors.rb +92 -42
  18. data/lib/nitro/compiler/include.rb +47 -17
  19. data/lib/nitro/compiler/morphing.rb +1 -3
  20. data/lib/nitro/compiler/script.rb +2 -2
  21. data/lib/nitro/context.rb +36 -0
  22. data/lib/nitro/controller.rb +140 -31
  23. data/lib/nitro/dispatcher.rb +27 -28
  24. data/lib/nitro/element.rb +52 -15
  25. data/lib/nitro/flash.rb +44 -0
  26. data/lib/nitro/helper/buffer.rb +0 -2
  27. data/lib/nitro/helper/form.rb +2 -2
  28. data/lib/nitro/helper/form/controls.rb +14 -3
  29. data/lib/nitro/helper/pager.rb +1 -1
  30. data/lib/nitro/helper/table.rb +4 -3
  31. data/lib/nitro/helper/xml.rb +1 -1
  32. data/lib/nitro/part.rb +20 -0
  33. data/lib/nitro/render.rb +44 -5
  34. data/lib/nitro/router.rb +81 -0
  35. data/lib/nitro/scaffolding.rb +24 -23
  36. data/lib/nitro/server.rb +12 -1
  37. data/lib/nitro/server/runner.rb +12 -0
  38. data/lib/nitro/session.rb +3 -12
  39. data/lib/nitro/session/drb.rb +2 -5
  40. data/lib/nitro/session/file.rb +2 -2
  41. data/lib/nitro/session/memcached.rb +14 -0
  42. data/lib/nitro/session/memory.rb +3 -26
  43. data/lib/nitro/session/og.rb +1 -1
  44. data/lib/nitro/test/assertions.rb +1 -1
  45. data/lib/nitro/test/context.rb +8 -2
  46. data/lib/nitro/test/testcase.rb +16 -7
  47. data/proto/public/error.xhtml +58 -21
  48. data/proto/public/js/controls.js +60 -15
  49. data/proto/public/js/dragdrop.js +105 -16
  50. data/proto/public/js/effects.js +19 -12
  51. data/proto/public/js/scriptaculous.js +1 -1
  52. data/proto/public/js/slider.js +2 -2
  53. data/proto/public/js/unittest.js +29 -20
  54. data/proto/public/scaffold/edit.xhtml +1 -1
  55. data/proto/public/scaffold/index.xhtml +2 -2
  56. data/proto/public/scaffold/list.xhtml +2 -2
  57. data/proto/public/scaffold/new.xhtml +1 -1
  58. data/proto/public/scaffold/search.xhtml +1 -1
  59. data/src/part/admin/controller.rb +5 -5
  60. data/src/part/admin/template/index.xhtml +2 -2
  61. data/test/nitro/compiler/tc_compiler.rb +23 -0
  62. data/test/nitro/helper/tc_table.rb +35 -0
  63. data/test/nitro/tc_cgi.rb +1 -1
  64. data/test/nitro/tc_controller.rb +3 -3
  65. data/test/nitro/tc_controller_aspect.rb +2 -0
  66. data/test/nitro/tc_dispatcher.rb +10 -1
  67. data/test/nitro/tc_flash.rb +14 -0
  68. data/test/nitro/tc_router.rb +58 -0
  69. data/test/nitro/tc_session.rb +26 -9
  70. metadata +13 -12
  71. data/lib/nitro/routing.rb +0 -41
  72. data/test/nitro/caching/tc_stores.rb +0 -17
  73. data/test/nitro/tc_table.rb +0 -66
@@ -128,7 +128,7 @@ var Draggables = {
128
128
  this.activeDraggable = draggable;
129
129
  },
130
130
 
131
- deactivate: function(draggbale) {
131
+ deactivate: function() {
132
132
  this.activeDraggable = null;
133
133
  },
134
134
 
@@ -199,6 +199,9 @@ Draggable.prototype = {
199
199
  },
200
200
  zindex: 1000,
201
201
  revert: false,
202
+ scroll: false,
203
+ scrollSensitivity: 20,
204
+ scrollSpeed: 15,
202
205
  snap: false // false, or xy or [x,y] or function(x,y){ return [x,y] }
203
206
  }, arguments[1] || {});
204
207
 
@@ -208,6 +211,8 @@ Draggable.prototype = {
208
211
  this.handle = Element.childrenWithClassName(this.element, options.handle)[0];
209
212
  if(!this.handle) this.handle = $(options.handle);
210
213
  if(!this.handle) this.handle = this.element;
214
+
215
+ if(options.scroll) options.scroll = $(options.scroll);
211
216
 
212
217
  Element.makePositioned(this.element); // fix IE
213
218
 
@@ -239,6 +244,7 @@ Draggable.prototype = {
239
244
  if(src.tagName && (
240
245
  src.tagName=='INPUT' ||
241
246
  src.tagName=='SELECT' ||
247
+ src.tagName=='OPTION' ||
242
248
  src.tagName=='BUTTON' ||
243
249
  src.tagName=='TEXTAREA')) return;
244
250
 
@@ -270,6 +276,11 @@ Draggable.prototype = {
270
276
  this.element.parentNode.insertBefore(this._clone, this.element);
271
277
  }
272
278
 
279
+ if(this.options.scroll) {
280
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
281
+ this.originalScrollTop = this.options.scroll.scrollTop;
282
+ }
283
+
273
284
  Draggables.notify('onStart', this, event);
274
285
  if(this.options.starteffect) this.options.starteffect(this.element);
275
286
  },
@@ -282,8 +293,25 @@ Draggable.prototype = {
282
293
  this.draw(pointer);
283
294
  if(this.options.change) this.options.change(this);
284
295
 
296
+ if(this.options.scroll) {
297
+ //if(this.scrollInterval) this.scroll();
298
+ this.stopScrolling();
299
+ var p = Position.page(this.options.scroll);
300
+ p[0] += this.options.scroll.scrollLeft;
301
+ p[1] += this.options.scroll.scrollTop;
302
+ p.push(p[0]+this.options.scroll.offsetWidth);
303
+ p.push(p[1]+this.options.scroll.offsetHeight);
304
+ var speed = [0,0];
305
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
306
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
307
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
308
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
309
+ this.startScrolling(speed);
310
+ }
311
+
285
312
  // fix AppleWebKit rendering
286
313
  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
314
+
287
315
  Event.stop(event);
288
316
  },
289
317
 
@@ -321,13 +349,14 @@ Draggable.prototype = {
321
349
  },
322
350
 
323
351
  keyPress: function(event) {
324
- if(!event.keyCode==Event.KEY_ESC) return;
352
+ if(event.keyCode!=Event.KEY_ESC) return;
325
353
  this.finishDrag(event, false);
326
354
  Event.stop(event);
327
355
  },
328
356
 
329
357
  endDrag: function(event) {
330
358
  if(!this.dragging) return;
359
+ this.stopScrolling();
331
360
  this.finishDrag(event, true);
332
361
  Event.stop(event);
333
362
  },
@@ -337,7 +366,14 @@ Draggable.prototype = {
337
366
  var d = this.currentDelta();
338
367
  pos[0] -= d[0]; pos[1] -= d[1];
339
368
 
340
- var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i]) }.bind(this));
369
+ if(this.options.scroll) {
370
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
371
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
372
+ }
373
+
374
+ var p = [0,1].map(function(i){
375
+ return (point[i]-pos[i]-this.offset[i])
376
+ }.bind(this));
341
377
 
342
378
  if(this.options.snap) {
343
379
  if(typeof this.options.snap == 'function') {
@@ -358,6 +394,34 @@ Draggable.prototype = {
358
394
  if((!this.options.constraint) || (this.options.constraint=='vertical'))
359
395
  style.top = p[1] + "px";
360
396
  if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
397
+ },
398
+
399
+ stopScrolling: function() {
400
+ if(this.scrollInterval) {
401
+ clearInterval(this.scrollInterval);
402
+ this.scrollInterval = null;
403
+ }
404
+ },
405
+
406
+ startScrolling: function(speed) {
407
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
408
+ this.lastScrolled = new Date();
409
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
410
+ },
411
+
412
+ scroll: function() {
413
+ var current = new Date();
414
+ var delta = current - this.lastScrolled;
415
+ this.lastScrolled = current;
416
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
417
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
418
+
419
+ Position.prepare();
420
+ Droppables.show(Draggables._lastPointer, this.element);
421
+ Draggables.notify('onDrag', this);
422
+ this.draw(Draggables._lastPointer);
423
+
424
+ if(this.options.change) this.options.change(this);
361
425
  }
362
426
  }
363
427
 
@@ -414,7 +478,8 @@ var Sortable = {
414
478
  only: false,
415
479
  hoverclass: null,
416
480
  ghosting: false,
417
- format: null,
481
+ scroll: false,
482
+ format: /^[^_]*_(.*)$/,
418
483
  onChange: Prototype.emptyFunction,
419
484
  onUpdate: Prototype.emptyFunction
420
485
  }, arguments[1] || {});
@@ -425,6 +490,7 @@ var Sortable = {
425
490
  // build options for the draggables
426
491
  var options_for_draggable = {
427
492
  revert: true,
493
+ scroll: options.scroll,
428
494
  ghosting: options.ghosting,
429
495
  constraint: options.constraint,
430
496
  handle: options.handle };
@@ -568,18 +634,41 @@ var Sortable = {
568
634
  Element.show(Sortable._marker);
569
635
  },
570
636
 
571
- serialize: function(element) {
637
+ sequence: function(element) {
572
638
  element = $(element);
573
- var sortableOptions = this.options(element);
574
- var options = Object.extend({
575
- tag: sortableOptions.tag,
576
- only: sortableOptions.only,
577
- name: element.id,
578
- format: sortableOptions.format || /^[^_]*_(.*)$/
579
- }, arguments[1] || {});
639
+ var options = Object.extend(this.options(element), arguments[1] || {});
640
+
580
641
  return $(this.findElements(element, options) || []).map( function(item) {
581
- return (encodeURIComponent(options.name) + "[]=" +
582
- encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : ''));
583
- }).join("&");
642
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
643
+ });
644
+ },
645
+
646
+ setSequence: function(element, new_sequence) {
647
+ element = $(element);
648
+ var options = Object.extend(this.options(element), arguments[2] || {});
649
+
650
+ var nodeMap = {};
651
+ this.findElements(element, options).each( function(n) {
652
+ if (n.id.match(options.format))
653
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
654
+ n.parentNode.removeChild(n);
655
+ });
656
+
657
+ new_sequence.each(function(ident) {
658
+ var n = nodeMap[ident];
659
+ if (n) {
660
+ n[1].appendChild(n[0]);
661
+ delete nodeMap[ident];
662
+ }
663
+ });
664
+ },
665
+
666
+ serialize: function(element) {
667
+ element = $(element);
668
+ var name = encodeURIComponent(
669
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
670
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
671
+ return name + "[]=" + encodeURIComponent(item);
672
+ }).join('&');
584
673
  }
585
- }
674
+ }
@@ -35,7 +35,7 @@ Element.collectTextNodesIgnoreClass = function(element, className) {
35
35
  return $A($(element).childNodes).collect( function(node) {
36
36
  return (node.nodeType==3 ? node.nodeValue :
37
37
  ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
38
- Element.collectTextNodes(node) : ''));
38
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
39
39
  }).flatten().join('');
40
40
  }
41
41
 
@@ -137,7 +137,7 @@ var Effect = {
137
137
  element = $(element);
138
138
  effect = (effect || 'appear').toLowerCase();
139
139
  var options = Object.extend({
140
- queue: { position:'end', scope:(element.id || 'global') }
140
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
141
141
  }, arguments[2] || {});
142
142
  Effect[Element.visible(element) ?
143
143
  Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
@@ -209,7 +209,10 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
209
209
 
210
210
  effect.startOn += timestamp;
211
211
  effect.finishOn += timestamp;
212
- this.effects.push(effect);
212
+
213
+ if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
214
+ this.effects.push(effect);
215
+
213
216
  if(!this.interval)
214
217
  this.interval = setInterval(this.loop.bind(this), 40);
215
218
  },
@@ -581,7 +584,6 @@ Effect.BlindUp = function(element) {
581
584
 
582
585
  Effect.BlindDown = function(element) {
583
586
  element = $(element);
584
- var oldHeight = Element.getStyle(element, 'height');
585
587
  var elementDimensions = Element.getDimensions(element);
586
588
  return new Effect.Scale(element, 100,
587
589
  Object.extend({ scaleContent: false,
@@ -594,10 +596,9 @@ Effect.BlindDown = function(element) {
594
596
  setStyle(effect.element, {height: '0px'});
595
597
  show(effect.element);
596
598
  }},
597
- afterFinishInternal: function(effect) { with(Element) {
598
- undoClipping(effect.element);
599
- setStyle(effect.element, {height: oldHeight});
600
- }}
599
+ afterFinishInternal: function(effect) {
600
+ Element.undoClipping(effect.element);
601
+ }
601
602
  }, arguments[1] || {})
602
603
  );
603
604
  }
@@ -690,8 +691,14 @@ Effect.SlideDown = function(element) {
690
691
  (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
691
692
  afterFinishInternal: function(effect) { with(Element) {
692
693
  undoClipping(effect.element);
693
- undoPositioned(effect.element.firstChild);
694
- undoPositioned(effect.element);
694
+ // IE will crash if child is undoPositioned first
695
+ if(/MSIE/.test(navigator.userAgent)){
696
+ undoPositioned(effect.element);
697
+ undoPositioned(effect.element.firstChild);
698
+ }else{
699
+ undoPositioned(effect.element.firstChild);
700
+ undoPositioned(effect.element);
701
+ }
695
702
  setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
696
703
  }, arguments[1] || {})
697
704
  );
@@ -741,7 +748,7 @@ Effect.Grow = function(element) {
741
748
  element = $(element);
742
749
  var options = Object.extend({
743
750
  direction: 'center',
744
- moveTransistion: Effect.Transitions.sinoidal,
751
+ moveTransition: Effect.Transitions.sinoidal,
745
752
  scaleTransition: Effect.Transitions.sinoidal,
746
753
  opacityTransition: Effect.Transitions.full
747
754
  }, arguments[1] || {});
@@ -817,7 +824,7 @@ Effect.Shrink = function(element) {
817
824
  element = $(element);
818
825
  var options = Object.extend({
819
826
  direction: 'center',
820
- moveTransistion: Effect.Transitions.sinoidal,
827
+ moveTransition: Effect.Transitions.sinoidal,
821
828
  scaleTransition: Effect.Transitions.sinoidal,
822
829
  opacityTransition: Effect.Transitions.none
823
830
  }, arguments[1] || {});
@@ -20,7 +20,7 @@
20
20
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  var Scriptaculous = {
23
- Version: '1.5.1',
23
+ Version: '1.5.3',
24
24
  require: function(libraryName) {
25
25
  // inserting via DOM fails in Safari 2.0, so brute force approach
26
26
  document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
@@ -200,10 +200,10 @@ Control.Slider.prototype = {
200
200
  setSpan: function(span, range) {
201
201
  if(this.isVertical()) {
202
202
  span.style.top = this.translateToPx(range.start);
203
- span.style.height = this.translateToPx(range.end - range.start);
203
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
204
204
  } else {
205
205
  span.style.left = this.translateToPx(range.start);
206
- span.style.width = this.translateToPx(range.end - range.start);
206
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
207
207
  }
208
208
  },
209
209
  updateStyles: function() {
@@ -2,7 +2,25 @@
2
2
  // (c) 2005 Jon Tirsen (http://www.tirsen.com)
3
3
  // (c) 2005 Michael Schuerig (http://www.schuerig.de/michael/)
4
4
  //
5
- // See scriptaculous.js for full license.
5
+ // Permission is hereby granted, free of charge, to any person obtaining
6
+ // a copy of this software and associated documentation files (the
7
+ // "Software"), to deal in the Software without restriction, including
8
+ // without limitation the rights to use, copy, modify, merge, publish,
9
+ // distribute, sublicense, and/or sell copies of the Software, and to
10
+ // permit persons to whom the Software is furnished to do so, subject to
11
+ // the following conditions:
12
+ //
13
+ // The above copyright notice and this permission notice shall be
14
+ // included in all copies or substantial portions of the Software.
15
+ //
16
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
6
24
 
7
25
  // experimental, Firefox-only
8
26
  Event.simulateMouse = function(element, eventName) {
@@ -64,24 +82,7 @@ var Test = {}
64
82
  Test.Unit = {};
65
83
 
66
84
  // security exception workaround
67
- Test.Unit.inspect = function(obj) {
68
- var info = [];
69
-
70
- if(typeof obj=="string" ||
71
- typeof obj=="number") {
72
- return obj;
73
- } else {
74
- for(property in obj)
75
- if(typeof obj[property]!="function")
76
- info.push(property + ' => ' +
77
- (typeof obj[property] == "string" ?
78
- '"' + obj[property] + '"' :
79
- obj[property]));
80
- }
81
-
82
- return ("'" + obj + "' #" + typeof obj +
83
- ": {" + info.join(", ") + "}");
84
- }
85
+ Test.Unit.inspect = Object.inspect;
85
86
 
86
87
  Test.Unit.Logger = Class.create();
87
88
  Test.Unit.Logger.prototype = {
@@ -279,6 +280,14 @@ Test.Unit.Assertions.prototype = {
279
280
  '", actual "' + Test.Unit.inspect(actual) + '"'); }
280
281
  catch(e) { this.error(e); }
281
282
  },
283
+ assertEnumEqual: function(expected, actual) {
284
+ var message = arguments[2] || "assertEnumEqual";
285
+ try { $A(expected).length == $A(actual).length &&
286
+ expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
287
+ this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
288
+ ', actual ' + Test.Unit.inspect(actual)); }
289
+ catch(e) { this.error(e); }
290
+ },
282
291
  assertNotEqual: function(expected, actual) {
283
292
  var message = arguments[2] || "assertNotEqual";
284
293
  try { (expected != actual) ? this.pass() :
@@ -360,4 +369,4 @@ Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.p
360
369
  }
361
370
  catch(e) { this.error(e); }
362
371
  }
363
- });
372
+ });
@@ -1,6 +1,6 @@
1
1
  <SystemPage>
2
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>
3
+ <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > Edit #{"%name%".humanize} </h1>
4
4
  <?r if @all ?>
5
5
  <a href="#{request.uri.gsub(/\/all$/, '')}">Show editable</a>
6
6
  #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list", :all => true}
@@ -1,9 +1,9 @@
1
1
  <SystemPage>
2
2
  <?r base = "#{@base}/%base%" ?>
3
3
  <h1>#{"%plural%".humanize}</h1>
4
- <h2><a href="#{base}/new">New %name%</a></h2>
4
+ <h2><a href="#{base}/new">New #{"%name%".humanize}</a></h2>
5
5
  <form action="search">
6
- Search %plural%: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
6
+ Search #{"%plural%".humanize}: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
7
7
  </form>
8
8
  <table>
9
9
  <?r for obj in @list ?>
@@ -1,10 +1,10 @@
1
1
  <SystemPage>
2
2
  <?r base = "#{@base}/%base%" ?>
3
3
  <h1><a href="/"> Home</a> > <a href="#@base">System</a> > #{"%plural%".humanize}</h1>
4
- <a href="#{base}/new">New %name%</a>
4
+ <a href="#{base}/new">New #{"%name%".humanize}</a>
5
5
  <p>
6
6
  <form action="#{base}/search">
7
- Search %plural%: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
7
+ Search #{"%plural%".humanize}: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
8
8
  </form>
9
9
  </p>
10
10
  <table>
@@ -1,6 +1,6 @@
1
1
  <SystemPage>
2
2
  <?r base = "#{@base}/%base%" ?>
3
- <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > New %name%</h1>
3
+ <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > New #{"%name%".humanize}</h1>
4
4
  <?r if @all ?>
5
5
  <a href="#{request.uri.gsub(/\/all$/, '')}">Show editable</a>
6
6
  #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list", :all => true, :enctype => "multipart/form-data"}
@@ -3,7 +3,7 @@
3
3
  <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > Search for '#@query'</h1>
4
4
  <p>
5
5
  <form action="#{base}/search">
6
- Search %plural%: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
6
+ Search #{"%plural%".humanize}: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
7
7
  </form>
8
8
  </p>
9
9
  <?r if @list.nil? ?>
@@ -16,16 +16,16 @@ class AdminController < Nitro::Controller
16
16
 
17
17
  scaffold_all
18
18
 
19
- # Default to views in part dir
20
-
21
- def self.template_root
22
- File.join(File.dirname(__FILE__), 'template')
19
+ def self.setup_template_root(path)
20
+ super
21
+ @template_root << File.join(File.dirname(__FILE__), 'template')
23
22
  end
24
23
 
25
24
  # default method for controller
26
25
 
27
26
  def index
28
- @classes = self.class.scaffolding_classes.keys
27
+ @classes = self.class.scaffolding_classes.keys.sort { |c1, c2| c1.name <=> c2.name }
28
+ @settings = Configuration.settings.sort { |s1, s2| "#{s1.owner}.#{s1.name}" <=> "#{s2.owner}.#{s2.name}" }
29
29
  end
30
30
 
31
31
  # Delete all instances of the class.