joosy 1.2.0.alpha.38 → 1.2.0.alpha.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gruntfile.coffee +15 -7
  3. data/bower.json +4 -3
  4. data/lib/extensions/resources.js +11 -3
  5. data/lib/joosy.js +235 -300
  6. data/package.json +3 -3
  7. data/spec/helpers/ground.coffee +33 -0
  8. data/spec/helpers/matchers.coffee +65 -0
  9. data/spec/joosy/core/application_spec.coffee +8 -8
  10. data/spec/joosy/core/helpers/view_spec.coffee +9 -5
  11. data/spec/joosy/core/helpers/widgets_spec.coffee +43 -10
  12. data/spec/joosy/core/joosy_spec.coffee +42 -50
  13. data/spec/joosy/core/layout_spec.coffee +30 -34
  14. data/spec/joosy/core/modules/container_spec.coffee +79 -76
  15. data/spec/joosy/core/modules/events_spec.coffee +148 -81
  16. data/spec/joosy/core/modules/filters_spec.coffee +68 -49
  17. data/spec/joosy/core/modules/log_spec.coffee +13 -5
  18. data/spec/joosy/core/modules/module_spec.coffee +24 -14
  19. data/spec/joosy/core/modules/renderer_spec.coffee +95 -89
  20. data/spec/joosy/core/modules/time_manager_spec.coffee +11 -16
  21. data/spec/joosy/core/modules/widget_manager_spec.coffee +89 -71
  22. data/spec/joosy/core/page_spec.coffee +201 -137
  23. data/spec/joosy/core/templaters/jst_spec.coffee +62 -0
  24. data/spec/joosy/core/widget_spec.coffee +25 -29
  25. data/spec/joosy/extensions/form/form_spec.coffee +3 -1
  26. data/spec/joosy/extensions/resources/base_spec.coffee +3 -0
  27. data/spec/joosy/extensions/resources/collection_spec.coffee +3 -0
  28. data/spec/joosy/extensions/resources/rest_collection_spec.coffee +3 -0
  29. data/spec/joosy/extensions/resources/rest_spec.coffee +3 -0
  30. data/src/joosy/core/application.coffee +1 -7
  31. data/src/joosy/core/helpers/view.coffee +12 -0
  32. data/src/joosy/core/helpers/widgets.coffee +19 -9
  33. data/src/joosy/core/joosy.coffee +0 -23
  34. data/src/joosy/core/layout.coffee +7 -5
  35. data/src/joosy/core/module.coffee +24 -4
  36. data/src/joosy/core/modules/container.coffee +29 -28
  37. data/src/joosy/core/modules/events.coffee +85 -72
  38. data/src/joosy/core/modules/filters.coffee +3 -1
  39. data/src/joosy/core/modules/renderer.coffee +91 -74
  40. data/src/joosy/core/modules/widgets_manager.coffee +12 -9
  41. data/src/joosy/core/page.coffee +7 -14
  42. data/src/joosy/core/templaters/{rails_jst.coffee → jst.coffee} +21 -19
  43. data/src/joosy/core/widget.coffee +3 -3
  44. data/src/joosy/extensions/resources/base.coffee +8 -3
  45. data/src/joosy/extensions/resources/rest.coffee +8 -0
  46. data/src/joosy/extensions/resources/rest_collection.coffee +1 -0
  47. data/tasks/joosy.coffee +46 -17
  48. data/templates/application/base/pages/welcome/index.coffee +5 -5
  49. data/templates/application/base/templates/layouts/application.jst.hamlc +2 -2
  50. data/templates/application/base/templates/pages/welcome/index.jst.hamlc +2 -2
  51. data/templates/application/standalone/Gruntfile.coffee +3 -1
  52. metadata +6 -5
  53. data/spec/helpers/helper.coffee +0 -68
  54. data/spec/joosy/core/templaters/rails_jst_spec.coffee +0 -25
data/lib/joosy.js CHANGED
@@ -56,27 +56,6 @@ this.Joosy = {
56
56
  return v.toString(16);
57
57
  }).toUpperCase();
58
58
  },
59
- preloadImages: function(images, callback) {
60
- var checker, p, result, ticks, _i, _len;
61
- if (!Object.isArray(images)) {
62
- images = [images];
63
- }
64
- if (images.length === 0) {
65
- callback();
66
- }
67
- ticks = images.length;
68
- result = [];
69
- checker = function() {
70
- if ((ticks -= 1) === 0) {
71
- return typeof callback === "function" ? callback() : void 0;
72
- }
73
- };
74
- for (_i = 0, _len = images.length; _i < _len; _i++) {
75
- p = images[_i];
76
- result.push($('<img/>').load(checker).error(checker).attr('src', p));
77
- }
78
- return result;
79
- },
80
59
  buildUrl: function(url, params) {
81
60
  var hash, paramsString;
82
61
  paramsString = [];
@@ -130,16 +109,21 @@ this.Joosy.Module = (function() {
130
109
  return false;
131
110
  };
132
111
 
133
- Module.alias = function(method, feature, action) {
134
- var chained;
135
- chained = "" + method + "Without" + (feature.camelize());
112
+ Module.aliasMethodChain = function(method, feature, action) {
113
+ var camelized, chained;
114
+ camelized = feature.charAt(0).toUpperCase() + feature.slice(1);
115
+ chained = "" + method + "Without" + camelized;
116
+ if (!Object.isFunction(action)) {
117
+ action = this.prototype[action];
118
+ }
136
119
  this.prototype[chained] = this.prototype[method];
137
120
  return this.prototype[method] = action;
138
121
  };
139
122
 
140
- Module.aliasStatic = function(method, feature, action) {
141
- var chained;
142
- chained = "" + method + "Without" + (feature.camelize());
123
+ Module.aliasStaticMethodChain = function(method, feature, action) {
124
+ var camelized, chained;
125
+ camelized = feature.charAt(0).toUpperCase() + feature.slice(1);
126
+ chained = "" + method + "Without" + camelized;
143
127
  this[chained] = this[method];
144
128
  return this[method] = action;
145
129
  };
@@ -220,15 +204,12 @@ Joosy.Application = {
220
204
  this.mergeConfig(window.JoosyEnvironment);
221
205
  }
222
206
  this.mergeConfig(options);
223
- this.templater = new Joosy.Templaters.RailsJST(this.name);
207
+ this.templater = new Joosy.Templaters.JST(this.name);
224
208
  return Joosy.Router.__setupRoutes();
225
209
  },
226
210
  content: function() {
227
211
  return $(this.selector);
228
212
  },
229
- sandbox: function() {
230
- return $(this.sandboxSelector);
231
- },
232
213
  setCurrentPage: function(page, params) {
233
214
  var attempt;
234
215
  attempt = new page(params, this.page);
@@ -293,21 +274,17 @@ Joosy.helpers('Application', function() {
293
274
  /*** src/joosy/core/helpers/widgets ***/
294
275
 
295
276
  Joosy.helpers('Application', function() {
296
- return this.widget = function(element, widget) {
297
- var params, parts, uuid;
298
- uuid = Joosy.uuid();
299
- params = {
300
- id: uuid
301
- };
302
- parts = element.split('.');
303
- if (parts[1]) {
304
- params["class"] = parts.from(1).join(' ');
277
+ return this.widget = function(tag, options, widget) {
278
+ var _this = this;
279
+ if (widget == null) {
280
+ widget = options;
281
+ options = {};
305
282
  }
306
- element = this.tag(parts[0], params);
307
- this.onRefresh(function() {
308
- return this.registerWidget('#' + uuid, widget);
283
+ options.id = Joosy.uid();
284
+ this.__renderer.setTimeout(0, function() {
285
+ return _this.__renderer.registerWidget($('#' + options.id), widget);
309
286
  });
310
- return element;
287
+ return this.tag(tag, options);
311
288
  };
312
289
  });
313
290
 
@@ -362,11 +339,12 @@ Joosy.Modules.Events = {
362
339
  events = name;
363
340
  name = Object.keys(this.__oneShotEvents).length.toString();
364
341
  }
365
- events = this.__splitEvents(events);
366
- this.__validateEvents(events);
367
- this.__oneShotEvents[name] = [events, callback];
342
+ this.__oneShotEvents[name] = [this.__splitEvents(events), callback];
368
343
  return name;
369
344
  },
345
+ unwait: function(target) {
346
+ return delete this.__oneShotEvents[target];
347
+ },
370
348
  bind: function(name, events, callback) {
371
349
  this.__boundEvents || (this.__boundEvents = {});
372
350
  if (Object.isFunction(events)) {
@@ -374,25 +352,11 @@ Joosy.Modules.Events = {
374
352
  events = name;
375
353
  name = Object.keys(this.__boundEvents).length.toString();
376
354
  }
377
- events = this.__splitEvents(events);
378
- this.__validateEvents(events);
379
- this.__boundEvents[name] = [events, callback];
355
+ this.__boundEvents[name] = [this.__splitEvents(events), callback];
380
356
  return name;
381
357
  },
382
358
  unbind: function(target) {
383
- var callback, events, name, needle, _ref, _ref1;
384
- needle = void 0;
385
- _ref = this.__boundEvents;
386
- for (name in _ref) {
387
- _ref1 = _ref[name], events = _ref1[0], callback = _ref1[1];
388
- if ((Object.isFunction(target) && callback === target) || name === target) {
389
- needle = name;
390
- break;
391
- }
392
- }
393
- if (needle != null) {
394
- return delete this.__boundEvents[needle];
395
- }
359
+ return delete this.__boundEvents[target];
396
360
  },
397
361
  trigger: function() {
398
362
  var callback, data, event, events, fire, name, _ref, _ref1, _ref2, _ref3, _results,
@@ -450,76 +414,72 @@ Joosy.Modules.Events = {
450
414
  __splitEvents: function(events) {
451
415
  if (Object.isString(events)) {
452
416
  if (events.isBlank()) {
453
- return [];
417
+ events = [];
454
418
  } else {
455
- return events.trim().split(/\s+/);
419
+ events = events.trim().split(/\s+/);
456
420
  }
457
- } else {
458
- return events;
459
421
  }
460
- },
461
- __validateEvents: function(events) {
462
422
  if (!(Object.isArray(events) && events.length > 0)) {
463
423
  throw new Error("" + (Joosy.Module.__className(this)) + "> bind invalid events: " + events);
464
424
  }
425
+ return events;
465
426
  }
466
427
  };
467
428
 
468
- Joosy.Events = {};
469
-
470
- Joosy.Events.Namespace = (function() {
471
- function Namespace(parent) {
472
- this.parent = parent;
473
- this.bindings = [];
474
- }
475
-
476
- Namespace.prototype.bind = function() {
477
- var args, _ref;
478
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
479
- return this.bindings.push((_ref = this.parent).bind.apply(_ref, args));
480
- };
481
-
482
- Namespace.prototype.unbind = function() {
483
- var b, _i, _len, _ref;
484
- _ref = this.bindings;
485
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
486
- b = _ref[_i];
487
- this.parent.unbind(b);
429
+ Joosy.namespace('Joosy.Events', function() {
430
+ this.Namespace = (function() {
431
+ function Namespace(parent) {
432
+ this.parent = parent;
433
+ this.bindings = [];
488
434
  }
489
- return this.bindings = [];
490
- };
491
435
 
492
- return Namespace;
436
+ Namespace.prototype.bind = function() {
437
+ var args, _ref;
438
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
439
+ return this.bindings.push((_ref = this.parent).bind.apply(_ref, args));
440
+ };
493
441
 
494
- })();
442
+ Namespace.prototype.unbind = function() {
443
+ var b, _i, _len, _ref;
444
+ _ref = this.bindings;
445
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
446
+ b = _ref[_i];
447
+ this.parent.unbind(b);
448
+ }
449
+ return this.bindings = [];
450
+ };
495
451
 
496
- Joosy.Events.SynchronizationContext = (function() {
497
- SynchronizationContext.uid = 0;
452
+ return Namespace;
498
453
 
499
- function SynchronizationContext(parent) {
500
- this.parent = parent;
501
- this.expectations = [];
502
- this.actions = [];
503
- }
454
+ })();
455
+ return this.SynchronizationContext = (function() {
456
+ SynchronizationContext.uid = 0;
504
457
 
505
- SynchronizationContext.prototype.uid = function() {
506
- return this.constructor.uid += 1;
507
- };
458
+ function SynchronizationContext(parent) {
459
+ this.parent = parent;
460
+ this.expectations = [];
461
+ this.actions = [];
462
+ }
508
463
 
509
- SynchronizationContext.prototype["do"] = function(action) {
510
- var event;
511
- event = "synchro-" + (this.uid());
512
- this.expectations.push(event);
513
- return this.actions.push([action, event]);
514
- };
464
+ SynchronizationContext.prototype.uid = function() {
465
+ return this.constructor.uid += 1;
466
+ };
515
467
 
516
- SynchronizationContext.prototype.after = function(after) {
517
- this.after = after;
518
- };
468
+ SynchronizationContext.prototype["do"] = function(action) {
469
+ var event;
470
+ event = "synchro-" + (this.uid());
471
+ this.expectations.push(event);
472
+ return this.actions.push([action, event]);
473
+ };
519
474
 
520
- return SynchronizationContext;
475
+ SynchronizationContext.prototype.after = function(after) {
476
+ this.after = after;
477
+ };
521
478
 
522
- })();
479
+ return SynchronizationContext;
480
+
481
+ })();
482
+ });
523
483
 
524
484
 
525
485
  /*** src/joosy/core/modules/container ***/
@@ -540,31 +500,9 @@ Joosy.Modules.Container = {
540
500
  return Object.merge(this.prototype.__events, map);
541
501
  };
542
502
  },
543
- onRefresh: function(callback) {
544
- if (!this.hasOwnProperty("__onRefreshes")) {
545
- this.__onRefreshes = [];
546
- }
547
- return this.__onRefreshes.push(callback);
548
- },
549
503
  $: function(selector) {
550
504
  return $(selector, this.container);
551
505
  },
552
- refreshElements: function() {
553
- var _this = this;
554
- if (this.hasOwnProperty("__onRefreshes")) {
555
- this.__onRefreshes.each(function(callback) {
556
- return callback.apply(_this);
557
- });
558
- return this.__onRefreshes = [];
559
- }
560
- },
561
- reloadContainer: function(htmlCallback) {
562
- if (typeof this.__removeMetamorphs === "function") {
563
- this.__removeMetamorphs();
564
- }
565
- this.container.html(htmlCallback());
566
- return this.refreshElements();
567
- },
568
506
  swapContainer: function(container, data) {
569
507
  container.unbind().off();
570
508
  container.html(data);
@@ -586,26 +524,33 @@ Joosy.Modules.Container = {
586
524
  return selector.trim();
587
525
  },
588
526
  __assignElements: function(root, entries) {
589
- var _this = this;
527
+ var key, value, _results;
590
528
  root || (root = this);
591
529
  entries || (entries = this.__elements);
592
530
  if (!entries) {
593
531
  return;
594
532
  }
595
- return Object.each(entries, function(key, value) {
533
+ _results = [];
534
+ for (key in entries) {
535
+ value = entries[key];
596
536
  if (Object.isObject(value)) {
597
- return _this.__assignElements(root['$' + key] = {}, value);
537
+ _results.push(this.__assignElements(root['$' + key] = {}, value));
598
538
  } else {
599
- value = _this.__extractSelector(value);
600
- root['$' + key] = function(filter) {
601
- if (!filter) {
602
- return _this.$(value);
603
- }
604
- return _this.$(value).filter(filter);
605
- };
606
- return root['$' + key].selector = value;
539
+ value = this.__extractSelector(value);
540
+ root['$' + key] = this.__wrapElement(value);
541
+ _results.push(root['$' + key].selector = value);
607
542
  }
608
- });
543
+ }
544
+ return _results;
545
+ },
546
+ __wrapElement: function(value) {
547
+ var _this = this;
548
+ return function(filter) {
549
+ if (!filter) {
550
+ return _this.$(value);
551
+ }
552
+ return _this.$(value).filter(filter);
553
+ };
609
554
  },
610
555
  __delegateEvents: function() {
611
556
  var events, module,
@@ -640,31 +585,33 @@ Joosy.Modules.Container = {
640
585
  };
641
586
 
642
587
 
643
- /*** src/joosy/core/templaters/rails_jst ***/
588
+ /*** src/joosy/core/templaters/jst ***/
644
589
 
645
- Joosy.Templaters.RailsJST = (function() {
646
- function RailsJST(applicationName) {
647
- this.applicationName = applicationName;
590
+ Joosy.Templaters.JST = (function() {
591
+ function JST(applicationName) {
592
+ if (Object.isString(applicationName) && applicationName.length > 0) {
593
+ this.applicationName = applicationName;
594
+ }
648
595
  }
649
596
 
650
- RailsJST.prototype.buildView = function(name) {
651
- var haystack, template;
597
+ JST.prototype.buildView = function(name) {
598
+ var haystack, path, template, _i, _len;
652
599
  template = false;
653
- haystack = ["" + this.applicationName + "/templates/" + name + "-" + (typeof I18n !== "undefined" && I18n !== null ? I18n.locale : void 0), "" + this.applicationName + "/templates/" + name, "templates/" + name + "-" + (typeof I18n !== "undefined" && I18n !== null ? I18n.locale : void 0), "templates/" + name];
654
- haystack.each(function(path) {
655
- var location;
656
- if (JST[path]) {
657
- location = path;
658
- return template = JST[path];
600
+ if (this.applicationName) {
601
+ haystack = ["" + this.applicationName + "/templates/" + name + "-" + (typeof I18n !== "undefined" && I18n !== null ? I18n.locale : void 0), "" + this.applicationName + "/templates/" + name];
602
+ } else {
603
+ haystack = ["templates/" + name + "-" + (typeof I18n !== "undefined" && I18n !== null ? I18n.locale : void 0), "templates/" + name];
604
+ }
605
+ for (_i = 0, _len = haystack.length; _i < _len; _i++) {
606
+ path = haystack[_i];
607
+ if (window.JST[path]) {
608
+ return window.JST[path];
659
609
  }
660
- });
661
- if (!template) {
662
- throw new Error("Template '" + name + "' not found. Checked at: " + location);
663
610
  }
664
- return template;
611
+ throw new Error("Template '" + name + "' not found. Checked at: '" + (haystack.join(', ')) + "'");
665
612
  };
666
613
 
667
- RailsJST.prototype.resolveTemplate = function(section, template, entity) {
614
+ JST.prototype.resolveTemplate = function(section, template, entity) {
668
615
  var path, _ref, _ref1;
669
616
  if (template.startsWith('/')) {
670
617
  return template.substr(1);
@@ -674,7 +621,7 @@ Joosy.Templaters.RailsJST = (function() {
674
621
  return "" + (path.join('/')) + "/" + template;
675
622
  };
676
623
 
677
- return RailsJST;
624
+ return JST;
678
625
 
679
626
  })();
680
627
 
@@ -1062,80 +1009,35 @@ Joosy.Templaters.RailsJST = (function() {
1062
1009
  var __slice = [].slice;
1063
1010
 
1064
1011
  Joosy.Modules.Renderer = {
1065
- __renderer: function() {
1012
+ __renderDefault: function() {
1066
1013
  throw new Error("" + (Joosy.Module.__className(this.constructor)) + " does not have an attached template");
1067
1014
  },
1068
- __helpers: null,
1069
1015
  included: function() {
1070
1016
  this.view = function(template, options) {
1071
1017
  if (options == null) {
1072
1018
  options = {};
1073
1019
  }
1074
- if (Object.isFunction(template)) {
1075
- return this.prototype.__renderer = template;
1076
- } else {
1077
- return this.prototype.__renderer = function(locals) {
1078
- if (locals == null) {
1079
- locals = {};
1080
- }
1081
- if (options.dynamic) {
1082
- return this.renderDynamic(template, locals);
1083
- } else {
1084
- return this.render(template, locals);
1085
- }
1086
- };
1087
- }
1020
+ return this.prototype.__renderDefault = function(locals) {
1021
+ if (locals == null) {
1022
+ locals = {};
1023
+ }
1024
+ if (options.dynamic) {
1025
+ return this.renderDynamic(template, locals);
1026
+ } else {
1027
+ return this.render(template, locals);
1028
+ }
1029
+ };
1088
1030
  };
1089
- return this.helpers = function() {
1090
- var helpers, _base,
1091
- _this = this;
1031
+ return this.helper = function() {
1032
+ var helpers, _ref;
1092
1033
  helpers = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1093
- (_base = this.prototype).__helpers || (_base.__helpers = []);
1094
- helpers.map(function(helper) {
1095
- var module;
1096
- module = Joosy.Helpers[helper];
1097
- if (!module) {
1098
- throw new Error("Cannot find helper module " + helper);
1099
- }
1100
- return _this.prototype.__helpers.push(module);
1101
- });
1034
+ if (!this.prototype.hasOwnProperty("__helpers")) {
1035
+ this.prototype.__helpers = ((_ref = this.__super__.__helpers) != null ? _ref.clone() : void 0) || [];
1036
+ }
1037
+ this.prototype.__helpers = this.prototype.__helpers.add(helpers).unique();
1102
1038
  return this.prototype.__helpers = this.prototype.__helpers.unique();
1103
1039
  };
1104
1040
  },
1105
- __instantiateHelpers: function() {
1106
- var helper, _i, _len, _ref,
1107
- _this = this;
1108
- if (!this.__helpersInstance) {
1109
- this.__helpersInstance = Object.extended(Joosy.Helpers.Application);
1110
- if (this.onRefresh) {
1111
- this.__helpersInstance.onRefresh = function(callback) {
1112
- return _this.onRefresh(callback);
1113
- };
1114
- }
1115
- if (this.__helpers) {
1116
- _ref = this.__helpers;
1117
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1118
- helper = _ref[_i];
1119
- Joosy.Module.merge(this.__helpersInstance, helper);
1120
- }
1121
- }
1122
- }
1123
- return this.__helpersInstance;
1124
- },
1125
- __proxifyHelpers: function(locals) {
1126
- if (locals.hasOwnProperty('__proto__')) {
1127
- locals.__proto__ = this.__instantiateHelpers();
1128
- return locals;
1129
- } else {
1130
- if (!this.__helpersProxyInstance) {
1131
- this.__helpersProxyInstance = function(locals) {
1132
- return Joosy.Module.merge(this, locals);
1133
- };
1134
- this.__helpersProxyInstance.prototype = this.__instantiateHelpers();
1135
- }
1136
- return new this.__helpersProxyInstance(locals);
1137
- }
1138
- },
1139
1041
  render: function(template, locals, parentStackPointer) {
1140
1042
  if (locals == null) {
1141
1043
  locals = {};
@@ -1154,8 +1056,67 @@ Joosy.Modules.Renderer = {
1154
1056
  }
1155
1057
  return this.__render(true, template, locals, parentStackPointer);
1156
1058
  },
1059
+ __assignHelpers: function() {
1060
+ var _this = this;
1061
+ if (this.__helpers == null) {
1062
+ return;
1063
+ }
1064
+ if (!this.hasOwnProperty("__helpers")) {
1065
+ this.__helpers = this.__helpers.clone();
1066
+ }
1067
+ return this.__helpers.each(function(helper, i) {
1068
+ if (!Object.isObject(helper)) {
1069
+ if (_this[helper] == null) {
1070
+ throw new Error("Cannot find method '" + helper + "' to use as helper");
1071
+ }
1072
+ _this.__helpers[i] = {};
1073
+ return _this.__helpers[i][helper] = function() {
1074
+ return _this[helper].apply(_this, arguments);
1075
+ };
1076
+ }
1077
+ });
1078
+ },
1079
+ __instantiateHelpers: function() {
1080
+ var helper, _i, _len, _ref;
1081
+ if (!this.__helpersInstance) {
1082
+ this.__assignHelpers();
1083
+ this.__helpersInstance = Object.extended(Joosy.Helpers.Application);
1084
+ this.__helpersInstance.__renderer = this;
1085
+ if (this.__helpers) {
1086
+ _ref = this.__helpers;
1087
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1088
+ helper = _ref[_i];
1089
+ Joosy.Module.merge(this.__helpersInstance, helper);
1090
+ }
1091
+ }
1092
+ }
1093
+ return this.__helpersInstance;
1094
+ },
1095
+ __instantiateRenderers: function(parentStackPointer) {
1096
+ var _this = this;
1097
+ return {
1098
+ render: function(template, locals) {
1099
+ if (locals == null) {
1100
+ locals = {};
1101
+ }
1102
+ return _this.render(template, locals, parentStackPointer);
1103
+ },
1104
+ renderDynamic: function(template, locals) {
1105
+ if (locals == null) {
1106
+ locals = {};
1107
+ }
1108
+ return _this.renderDynamic(template, locals, parentStackPointer);
1109
+ },
1110
+ renderInline: function(locals, template) {
1111
+ if (locals == null) {
1112
+ locals = {};
1113
+ }
1114
+ return _this.renderDynamic(template, locals, parentStackPointer);
1115
+ }
1116
+ };
1117
+ },
1157
1118
  __render: function(dynamic, template, locals, parentStackPointer) {
1158
- var assignContext, binding, context, key, morph, object, renderers, result, stack, update,
1119
+ var binding, context, key, morph, object, result, stack, update,
1159
1120
  _this = this;
1160
1121
  if (locals == null) {
1161
1122
  locals = {};
@@ -1166,65 +1127,38 @@ Joosy.Modules.Renderer = {
1166
1127
  stack = this.__renderingStackChildFor(parentStackPointer);
1167
1128
  stack.template = template;
1168
1129
  stack.locals = locals;
1169
- assignContext = false;
1170
1130
  if (Object.isString(template)) {
1171
1131
  if (this.__renderSection != null) {
1172
1132
  template = Joosy.Application.templater.resolveTemplate(this.__renderSection(), template, this);
1173
1133
  }
1174
1134
  template = Joosy.Application.templater.buildView(template);
1175
- } else if (Object.isFunction(template)) {
1176
- assignContext = true;
1177
1135
  } else if (!Object.isFunction(template)) {
1178
1136
  throw new Error("" + (Joosy.Module.__className(this)) + "> template (maybe @view) does not look like a string or lambda");
1179
1137
  }
1180
1138
  if (!Object.isObject(locals) && Object.extended().constructor !== locals.constructor) {
1181
1139
  throw new Error("" + (Joosy.Module.__className(this)) + "> locals (maybe @data?) is not a hash");
1182
1140
  }
1183
- renderers = {
1184
- render: function(template, locals) {
1185
- if (locals == null) {
1186
- locals = {};
1187
- }
1188
- return _this.render(template, locals, stack);
1189
- },
1190
- renderDynamic: function(template, locals) {
1191
- if (locals == null) {
1192
- locals = {};
1193
- }
1194
- return _this.renderDynamic(template, locals, stack);
1195
- },
1196
- renderInline: function(locals, template) {
1197
- if (locals == null) {
1198
- locals = {};
1199
- }
1200
- return _this.renderDynamic(template, locals, stack);
1201
- }
1202
- };
1203
1141
  context = function() {
1204
1142
  var data;
1205
1143
  data = {};
1206
1144
  Joosy.Module.merge(data, stack.locals);
1207
1145
  Joosy.Module.merge(data, _this.__instantiateHelpers(), false);
1208
- Joosy.Module.merge(data, renderers);
1146
+ Joosy.Module.merge(data, _this.__instantiateRenderers(stack));
1209
1147
  return data;
1210
1148
  };
1211
1149
  result = function() {
1212
- if (assignContext) {
1213
- return template.call(context());
1214
- } else {
1215
- return template(context());
1216
- }
1150
+ return template(context());
1217
1151
  };
1218
1152
  if (dynamic) {
1219
1153
  morph = Metamorph(result());
1220
1154
  update = function() {
1221
- var callback, child, object, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;
1155
+ var binding, child, object, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;
1222
1156
  if (morph.isRemoved()) {
1223
1157
  _ref = morph.__bindings;
1224
1158
  _results = [];
1225
1159
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1226
- _ref1 = _ref[_i], object = _ref1[0], callback = _ref1[1];
1227
- _results.push(object.unbind(callback));
1160
+ _ref1 = _ref[_i], object = _ref1[0], binding = _ref1[1];
1161
+ _results.push(object.unbind(binding));
1228
1162
  }
1229
1163
  return _results;
1230
1164
  } else {
@@ -1234,23 +1168,20 @@ Joosy.Modules.Renderer = {
1234
1168
  _this.__removeMetamorphs(child);
1235
1169
  }
1236
1170
  stack.children = [];
1237
- morph.html(result());
1238
- return typeof _this.refreshElements === "function" ? _this.refreshElements() : void 0;
1171
+ return morph.html(result());
1239
1172
  }
1240
1173
  };
1241
1174
  update = update.debounce(0);
1242
- morph.__bindings = [];
1243
1175
  for (key in locals) {
1244
1176
  object = locals[key];
1245
1177
  if (locals.hasOwnProperty(key)) {
1246
1178
  if (((object != null ? object.bind : void 0) != null) && ((object != null ? object.unbind : void 0) != null)) {
1247
- binding = [object, update];
1248
- object.bind('changed', update);
1179
+ binding = [object, object.bind('changed', update)];
1249
1180
  stack.metamorphBindings.push(binding);
1250
- morph.__bindings.push(binding);
1251
1181
  }
1252
1182
  }
1253
1183
  }
1184
+ morph.__bindings = stack.metamorphBindings;
1254
1185
  return morph.outerHTML();
1255
1186
  } else {
1256
1187
  return result();
@@ -1390,14 +1321,13 @@ Joosy.Modules.WidgetsManager = {
1390
1321
  return this.__activeWidgets.splice(this.__activeWidgets.indexOf(widget), 1);
1391
1322
  },
1392
1323
  __setupWidgets: function() {
1393
- var registered, widgets,
1324
+ var registered,
1394
1325
  _this = this;
1395
- widgets = this.__widgets;
1396
- registered = Object.extended();
1397
- if (!widgets) {
1326
+ if (!this.__widgets) {
1398
1327
  return;
1399
1328
  }
1400
- Object.each(widgets, function(selector, widget) {
1329
+ registered = Object.extended();
1330
+ Object.each(this.__widgets, function(selector, widget) {
1401
1331
  var activeSelector;
1402
1332
  if (selector === '$container') {
1403
1333
  activeSelector = _this.container;
@@ -1415,16 +1345,21 @@ Joosy.Modules.WidgetsManager = {
1415
1345
  } else {
1416
1346
  instance = widget.call(_this, index);
1417
1347
  }
1418
- (_base = registered[selector])[_name = Joosy.Module.__className(instance)] || (_base[_name] = 0);
1419
- registered[selector][Joosy.Module.__className(instance)] += 1;
1348
+ if (Joosy.Application.config.debug) {
1349
+ (_base = registered[selector])[_name = Joosy.Module.__className(instance)] || (_base[_name] = 0);
1350
+ registered[selector][Joosy.Module.__className(instance)] += 1;
1351
+ }
1420
1352
  return _this.registerWidget($(elem), instance);
1421
1353
  });
1422
1354
  });
1423
- return registered.each(function(selector, value) {
1424
- return value.each(function(widget, count) {
1425
- return Joosy.Modules.Log.debugAs(_this, "Widget " + widget + " registered at '" + selector + "'. Elements: " + count);
1355
+ this.__widgets = {};
1356
+ if (Joosy.Application.config.debug) {
1357
+ return registered.each(function(selector, value) {
1358
+ return value.each(function(widget, count) {
1359
+ return Joosy.Modules.Log.debugAs(_this, "Widget " + widget + " registered at '" + selector + "'. Elements: " + count);
1360
+ });
1426
1361
  });
1427
- });
1362
+ }
1428
1363
  },
1429
1364
  __unloadWidgets: function() {
1430
1365
  var widget, _i, _len, _ref, _results;
@@ -1461,7 +1396,9 @@ Joosy.Modules.Filters = {
1461
1396
  };
1462
1397
 
1463
1398
  ['beforeLoad', 'afterLoad', 'afterUnload'].each(function(filter) {
1464
- return Joosy.Modules.Filters["__run" + (filter.camelize(true)) + "s"] = function() {
1399
+ var camelized;
1400
+ camelized = filter.charAt(0).toUpperCase() + filter.slice(1);
1401
+ return Joosy.Modules.Filters["__run" + camelized + "s"] = function() {
1465
1402
  var opts,
1466
1403
  _this = this;
1467
1404
  opts = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
@@ -1503,6 +1440,8 @@ Joosy.Layout = (function(_super) {
1503
1440
 
1504
1441
  Layout.view('default');
1505
1442
 
1443
+ Layout.helper('page');
1444
+
1506
1445
  Layout.beforePaint = function(callback) {
1507
1446
  return this.prototype.__beforePaint = callback;
1508
1447
  };
@@ -1532,6 +1471,7 @@ Joosy.Layout = (function(_super) {
1532
1471
 
1533
1472
  function Layout(params) {
1534
1473
  this.params = params;
1474
+ this.uid = Joosy.uid();
1535
1475
  }
1536
1476
 
1537
1477
  Layout.prototype.navigate = function() {
@@ -1559,12 +1499,16 @@ Joosy.Layout = (function(_super) {
1559
1499
  return this.__runAfterUnloads();
1560
1500
  };
1561
1501
 
1562
- Layout.prototype["yield"] = function() {
1563
- return this.uuid = Joosy.uuid();
1502
+ Layout.prototype.page = function(tag, options) {
1503
+ if (options == null) {
1504
+ options = {};
1505
+ }
1506
+ options.id = this.uid;
1507
+ return Joosy.Helpers.Application.tag(tag, options);
1564
1508
  };
1565
1509
 
1566
1510
  Layout.prototype.content = function() {
1567
- return $("#" + this.uuid);
1511
+ return $("#" + this.uid);
1568
1512
  };
1569
1513
 
1570
1514
  return Layout;
@@ -1697,7 +1641,7 @@ Joosy.Page = (function(_super) {
1697
1641
  this.__layoutClass || (this.__layoutClass = ApplicationLayout);
1698
1642
  if (!(this.halted = !this.__runBeforeLoads(this.params, this.previous))) {
1699
1643
  Joosy.Application.loading = true;
1700
- if ((((_ref = this.previous) != null ? (_ref1 = _ref.layout) != null ? _ref1.uuid : void 0 : void 0) == null) || ((_ref2 = this.previous) != null ? _ref2.__layoutClass : void 0) !== this.__layoutClass) {
1644
+ if ((((_ref = this.previous) != null ? (_ref1 = _ref.layout) != null ? _ref1.uid : void 0 : void 0) == null) || ((_ref2 = this.previous) != null ? _ref2.__layoutClass : void 0) !== this.__layoutClass) {
1701
1645
  this.__bootstrapLayout();
1702
1646
  } else {
1703
1647
  this.__bootstrap();
@@ -1770,10 +1714,9 @@ Joosy.Page = (function(_super) {
1770
1714
  }
1771
1715
  }
1772
1716
  return _this.__callSyncedThrough(_this, '__paint', callbacksParams, function() {
1773
- _this.swapContainer(_this.layout.content(), _this.__renderer(_this.data || {}));
1717
+ _this.swapContainer(_this.layout.content(), _this.__renderDefault(_this.data || {}));
1774
1718
  _this.container = _this.layout.content();
1775
- _this.__load();
1776
- return _this.layout.content();
1719
+ return _this.__load();
1777
1720
  });
1778
1721
  });
1779
1722
  this.__callSyncedThrough(this.previous, '__erase', callbacksParams, function() {
@@ -1802,19 +1745,11 @@ Joosy.Page = (function(_super) {
1802
1745
  }
1803
1746
  this.wait("stageClear dataReceived", function() {
1804
1747
  return _this.__callSyncedThrough(_this.layout, '__paint', callbacksParams, function() {
1805
- var data;
1806
- data = Joosy.Module.merge({}, _this.layout.data || {});
1807
- data = Joosy.Module.merge(data, {
1808
- "yield": function() {
1809
- return _this.layout["yield"]();
1810
- }
1811
- });
1812
- _this.swapContainer(Joosy.Application.content(), _this.layout.__renderer(data));
1813
- _this.swapContainer(_this.layout.content(), _this.__renderer(_this.data || {}));
1748
+ _this.swapContainer(Joosy.Application.content(), _this.layout.__renderDefault(_this.layout.data || {}));
1749
+ _this.swapContainer(_this.layout.content(), _this.__renderDefault(_this.data || {}));
1814
1750
  _this.container = _this.layout.content();
1815
1751
  _this.layout.__load(Joosy.Application.content());
1816
- _this.__load();
1817
- return Joosy.Application.content();
1752
+ return _this.__load();
1818
1753
  });
1819
1754
  });
1820
1755
  this.__callSyncedThrough((_ref = this.previous) != null ? _ref.layout : void 0, '__erase', callbacksParams, function() {
@@ -2215,7 +2150,7 @@ Joosy.Widget = (function(_super) {
2215
2150
 
2216
2151
  Widget.include(Joosy.Modules.WidgetsManager);
2217
2152
 
2218
- Widget.prototype.__renderer = false;
2153
+ Widget.prototype.__renderDefault = false;
2219
2154
 
2220
2155
  Widget.prototype.data = false;
2221
2156
 
@@ -2236,8 +2171,8 @@ Joosy.Widget = (function(_super) {
2236
2171
  render = true;
2237
2172
  }
2238
2173
  this.__runBeforeLoads();
2239
- if (render && this.__renderer) {
2240
- this.swapContainer(this.container, this.__renderer(this.data || {}));
2174
+ if (render && this.__renderDefault) {
2175
+ this.swapContainer(this.container, this.__renderDefault(this.data || {}));
2241
2176
  }
2242
2177
  this.__assignElements();
2243
2178
  this.__delegateEvents();