joosy 1.2.0.alpha.14 → 1.2.0.alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gruntfile.coffee +42 -18
  4. data/README.md +16 -12
  5. data/bower.json +1 -1
  6. data/lib/extensions/form.js +592 -0
  7. data/lib/extensions/preloaders.js +193 -0
  8. data/lib/extensions/resources.js +667 -0
  9. data/lib/joosy.js +1141 -2680
  10. data/lib/joosy.rb +0 -5
  11. data/package.json +1 -1
  12. data/spec/helpers/helper.coffee +1 -1
  13. data/spec/joosy/core/joosy_spec.coffee +1 -28
  14. data/spec/joosy/core/modules/renderer_spec.coffee +0 -95
  15. data/spec/joosy/{core → extensions/form}/form_spec.coffee +2 -2
  16. data/spec/joosy/{core → extensions/form}/helpers/forms_spec.coffee +1 -1
  17. data/spec/joosy/{preloaders → extensions/preloaders}/caching_spec.coffee +0 -0
  18. data/spec/joosy/{preloaders → extensions/preloaders}/inline_spec.coffee +0 -0
  19. data/spec/joosy/{core/resource/generic_spec.coffee → extensions/resources/base_spec.coffee} +19 -20
  20. data/spec/joosy/{core/resource → extensions/resources}/collection_spec.coffee +4 -4
  21. data/spec/joosy/{core/resource → extensions/resources}/rest_collection_spec.coffee +4 -4
  22. data/spec/joosy/{core/resource → extensions/resources}/rest_spec.coffee +6 -7
  23. data/src/joosy.coffee +1 -2
  24. data/src/joosy/core/helpers/view.coffee +0 -8
  25. data/src/joosy/core/joosy.coffee +5 -44
  26. data/src/joosy/core/modules/renderer.coffee +10 -29
  27. data/src/joosy/core/{resource → resources}/watcher.coffee +2 -1
  28. data/src/joosy/{core → extensions/form}/form.coffee +3 -9
  29. data/src/joosy/{core → extensions/form}/helpers/form.coffee +2 -2
  30. data/src/joosy/extensions/form/index.coffee +1 -0
  31. data/src/joosy/{preloaders → extensions/preloaders}/caching.coffee +0 -0
  32. data/src/joosy/extensions/preloaders/index.coffee +1 -0
  33. data/src/joosy/{preloaders → extensions/preloaders}/inline.coffee +0 -0
  34. data/src/joosy/{core/resource/generic.coffee → extensions/resources/base.coffee} +21 -21
  35. data/src/joosy/{core/resource → extensions/resources}/collection.coffee +11 -11
  36. data/src/joosy/extensions/resources/index.coffee +1 -0
  37. data/src/joosy/{core/resource → extensions/resources}/rest.coffee +15 -12
  38. data/src/joosy/{core/resource → extensions/resources}/rest_collection.coffee +4 -2
  39. data/src/joosy/generators/base.coffee +1 -1
  40. metadata +25 -20
  41. data/src/joosy/core/preloader.coffee +0 -13
data/lib/joosy.js CHANGED
@@ -2,12 +2,9 @@
2
2
 
3
3
  /*** src/joosy/core/joosy ***/
4
4
 
5
- var __hasProp = {}.hasOwnProperty,
6
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
7
-
8
5
  this.Joosy = {
9
6
  Modules: {},
10
- Resource: {},
7
+ Resources: {},
11
8
  Templaters: {},
12
9
  namespace: function(name, generator) {
13
10
  var key, klass, part, space, _i, _len, _results;
@@ -97,129 +94,6 @@ this.Joosy = {
97
94
  paramsString = '&' + paramsString;
98
95
  }
99
96
  return url + paramsString + hash;
100
- },
101
- defineResources: function(resources) {
102
- return Object.extended(resources).each(function(namespace, resources) {
103
- if (namespace.isBlank()) {
104
- return Object.extended(resources).each(function(resource, path) {
105
- return Joosy.defineResource(resource, path);
106
- });
107
- } else {
108
- return Joosy.namespace(namespace, function() {
109
- var _this = this;
110
- return Object.extended(resources).each(function(resource, path) {
111
- return Joosy.defineResource(resource, path, _this);
112
- });
113
- });
114
- }
115
- });
116
- },
117
- defineResource: function(resource, path, space) {
118
- var className, collectionName, _ref, _ref1;
119
- if (space == null) {
120
- space = window;
121
- }
122
- className = resource.camelize();
123
- collectionName = "" + (resource.pluralize().camelize()) + "Collection";
124
- if (!space[className]) {
125
- Joosy.Modules.Log.debugAs(space, "Define " + className);
126
- space[className] = (function(_super) {
127
- __extends(_Class, _super);
128
-
129
- function _Class() {
130
- _ref = _Class.__super__.constructor.apply(this, arguments);
131
- return _ref;
132
- }
133
-
134
- _Class.entity(resource);
135
-
136
- _Class.source(path);
137
-
138
- _Class.prototype.__collection = function() {
139
- return space[collectionName];
140
- };
141
-
142
- return _Class;
143
-
144
- })(Joosy.Resource.REST);
145
- }
146
- if (!space[collectionName]) {
147
- Joosy.Modules.Log.debugAs(space, "Define " + collectionName);
148
- return space[collectionName] = (function(_super) {
149
- __extends(_Class, _super);
150
-
151
- function _Class() {
152
- _ref1 = _Class.__super__.constructor.apply(this, arguments);
153
- return _ref1;
154
- }
155
-
156
- _Class.model(space[className]);
157
-
158
- return _Class;
159
-
160
- })(Joosy.Resource.RESTCollection);
161
- }
162
- }
163
- };
164
-
165
-
166
- /*** src/joosy/core/application ***/
167
-
168
- Joosy.Application = {
169
- Pages: {},
170
- Layouts: {},
171
- Controls: {},
172
- loading: true,
173
- identity: true,
174
- debounceForms: false,
175
- config: {
176
- debug: false,
177
- router: {
178
- html5: false,
179
- base: '/'
180
- }
181
- },
182
- initialize: function(name, selector, options) {
183
- this.name = name;
184
- this.selector = selector;
185
- if (options == null) {
186
- options = {};
187
- }
188
- if (window.JoosyEnvironment != null) {
189
- this.mergeConfig(window.JoosyEnvironment);
190
- }
191
- this.mergeConfig(options);
192
- this.templater = new Joosy.Templaters.RailsJST(this.name);
193
- Joosy.Router.__setupRoutes();
194
- this.sandboxSelector = Joosy.uuid();
195
- this.content().after("<div id='" + this.sandboxSelector + "' style='display:none'></div>");
196
- return this.sandboxSelector = '#' + this.sandboxSelector;
197
- },
198
- content: function() {
199
- return $(this.selector);
200
- },
201
- sandbox: function() {
202
- return $(this.sandboxSelector);
203
- },
204
- setCurrentPage: function(page, params) {
205
- var attempt;
206
- attempt = new page(params, this.page);
207
- if (!attempt.halted) {
208
- return this.page = attempt;
209
- }
210
- },
211
- mergeConfig: function(options) {
212
- var key, value, _results;
213
- _results = [];
214
- for (key in options) {
215
- value = options[key];
216
- if (Object.isObject(this.config[key])) {
217
- _results.push(Object.merge(this.config[key], value));
218
- } else {
219
- _results.push(this.config[key] = value);
220
- }
221
- }
222
- return _results;
223
97
  }
224
98
  };
225
99
 
@@ -321,6 +195,127 @@ Joosy.Module = (function() {
321
195
  })();
322
196
 
323
197
 
198
+ /*** src/joosy/core/application ***/
199
+
200
+ Joosy.Application = {
201
+ Pages: {},
202
+ Layouts: {},
203
+ Controls: {},
204
+ loading: true,
205
+ identity: true,
206
+ debounceForms: false,
207
+ config: {
208
+ debug: false,
209
+ router: {
210
+ html5: false,
211
+ base: '/'
212
+ }
213
+ },
214
+ initialize: function(name, selector, options) {
215
+ this.name = name;
216
+ this.selector = selector;
217
+ if (options == null) {
218
+ options = {};
219
+ }
220
+ if (window.JoosyEnvironment != null) {
221
+ this.mergeConfig(window.JoosyEnvironment);
222
+ }
223
+ this.mergeConfig(options);
224
+ this.templater = new Joosy.Templaters.RailsJST(this.name);
225
+ Joosy.Router.__setupRoutes();
226
+ this.sandboxSelector = Joosy.uuid();
227
+ this.content().after("<div id='" + this.sandboxSelector + "' style='display:none'></div>");
228
+ return this.sandboxSelector = '#' + this.sandboxSelector;
229
+ },
230
+ content: function() {
231
+ return $(this.selector);
232
+ },
233
+ sandbox: function() {
234
+ return $(this.sandboxSelector);
235
+ },
236
+ setCurrentPage: function(page, params) {
237
+ var attempt;
238
+ attempt = new page(params, this.page);
239
+ if (!attempt.halted) {
240
+ return this.page = attempt;
241
+ }
242
+ },
243
+ mergeConfig: function(options) {
244
+ var key, value, _results;
245
+ _results = [];
246
+ for (key in options) {
247
+ value = options[key];
248
+ if (Object.isObject(this.config[key])) {
249
+ _results.push(Object.merge(this.config[key], value));
250
+ } else {
251
+ _results.push(this.config[key] = value);
252
+ }
253
+ }
254
+ return _results;
255
+ }
256
+ };
257
+
258
+
259
+ /*** src/joosy/core/helpers/view ***/
260
+
261
+ Joosy.helpers('Application', function() {
262
+ this.tag = function(name, options, content) {
263
+ var e, element, temp;
264
+ if (options == null) {
265
+ options = {};
266
+ }
267
+ if (content == null) {
268
+ content = '';
269
+ }
270
+ if (Object.isFunction(content)) {
271
+ content = content();
272
+ }
273
+ element = document.createElement(name);
274
+ temp = document.createElement('div');
275
+ Object.each(options, function(name, value) {
276
+ return element.setAttribute(name, value);
277
+ });
278
+ try {
279
+ element.innerHTML = content;
280
+ } catch (_error) {
281
+ e = _error;
282
+ if (content) {
283
+ throw e;
284
+ }
285
+ }
286
+ temp.appendChild(element);
287
+ return temp.innerHTML;
288
+ };
289
+ return this.renderWrapped = function(template, lambda) {
290
+ return this.render(template, Joosy.Module.merge(this, {
291
+ "yield": lambda()
292
+ }));
293
+ };
294
+ });
295
+
296
+
297
+ /*** src/joosy/core/helpers/widgets ***/
298
+
299
+ Joosy.helpers('Application', function() {
300
+ return this.widget = function(element, widget) {
301
+ var params, parts, uuid;
302
+ uuid = Joosy.uuid();
303
+ params = {
304
+ id: uuid
305
+ };
306
+ parts = element.split('.');
307
+ if (parts[1]) {
308
+ params["class"] = parts.from(1).join(' ');
309
+ }
310
+ element = this.tag(parts[0], params);
311
+ this.onRefresh(function() {
312
+ return this.registerWidget('#' + uuid, widget);
313
+ });
314
+ return element;
315
+ };
316
+ });
317
+
318
+
324
319
  /*** src/joosy/core/modules/log ***/
325
320
 
326
321
  var __slice = [].slice;
@@ -625,2563 +620,1216 @@ Joosy.Modules.Container = {
625
620
  };
626
621
 
627
622
 
628
- /*** src/joosy/core/form ***/
629
-
630
- var __hasProp = {}.hasOwnProperty,
631
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
632
-
633
- Joosy.Form = (function(_super) {
634
- __extends(Form, _super);
635
-
636
- Form.include(Joosy.Modules.Container);
637
-
638
- Form.include(Joosy.Modules.Log);
639
-
640
- Form.include(Joosy.Modules.Events);
641
-
642
- Form.prototype.invalidationClass = 'field_with_errors';
623
+ /*** src/joosy/core/templaters/rails_jst ***/
643
624
 
644
- Form.prototype.substitutions = {};
625
+ Joosy.Templaters.RailsJST = (function() {
626
+ function RailsJST(applicationName) {
627
+ this.applicationName = applicationName;
628
+ }
645
629
 
646
- Form.prototype.elements = {
647
- 'fields': 'input,select,textarea'
630
+ RailsJST.prototype.buildView = function(name) {
631
+ var haystack, template;
632
+ template = false;
633
+ 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];
634
+ haystack.each(function(path) {
635
+ var location;
636
+ if (JST[path]) {
637
+ location = path;
638
+ return template = JST[path];
639
+ }
640
+ });
641
+ if (!template) {
642
+ throw new Error("Template '" + name + "' not found. Checked at: " + location);
643
+ }
644
+ return template;
648
645
  };
649
646
 
650
- Form.submit = function(form, options) {
651
- if (options == null) {
652
- options = {};
647
+ RailsJST.prototype.resolveTemplate = function(section, template, entity) {
648
+ var path, _ref, _ref1;
649
+ if (template.startsWith('/')) {
650
+ return template.substr(1);
653
651
  }
654
- form = new this(form, options);
655
- form.container.submit();
656
- form.unbind();
657
- return null;
652
+ path = ((_ref = entity.constructor) != null ? (_ref1 = _ref.__namespace__) != null ? _ref1.map('underscore') : void 0 : void 0) || [];
653
+ path.unshift(section);
654
+ return "" + (path.join('/')) + "/" + template;
658
655
  };
659
656
 
660
- Form.attach = function() {
661
- return (function(func, args, ctor) {
662
- ctor.prototype = func.prototype;
663
- var child = new ctor, result = func.apply(child, args);
664
- return Object(result) === result ? result : child;
665
- })(Joosy.Form, arguments, function(){});
666
- };
657
+ return RailsJST;
667
658
 
668
- function Form(form, options) {
669
- var method, _ref,
670
- _this = this;
671
- if (options == null) {
672
- options = {};
673
- }
674
- if (Object.isFunction(options)) {
675
- this.success = options;
676
- } else {
677
- Object.each(options, function(key, value) {
678
- return _this[key] = value;
679
- });
680
- }
681
- this.container = $(form);
682
- if (this.container.length === 0) {
683
- return;
684
- }
685
- this.refreshElements();
686
- this.__delegateEvents();
687
- method = (_ref = this.container.get(0).getAttribute('method')) != null ? _ref.toLowerCase() : void 0;
688
- if (method && !['get', 'post'].any(method)) {
689
- this.__markMethod(method);
690
- this.container.attr('method', 'POST');
691
- }
692
- this.container.ajaxForm({
693
- dataType: 'json',
694
- beforeSend: function() {
695
- if (_this.__debounce.apply(_this, arguments)) {
696
- return false;
697
- }
698
- _this.__before.apply(_this, arguments);
699
- _this.__pending_request = true;
700
- _this.debugAs(_this, 'beforeSend: pending_request = true');
701
- return true;
702
- },
703
- success: function() {
704
- _this.__pending_request = false;
705
- _this.debugAs(_this, 'success: pending_request = false');
706
- return _this.__success.apply(_this, arguments);
707
- },
708
- error: function() {
709
- _this.__pending_request = false;
710
- _this.debugAs(_this, 'error: pending_request = false');
711
- return _this.__error.apply(_this, arguments);
712
- },
713
- xhr: function() {
714
- var xhr;
715
- xhr = $.ajaxSettings.xhr();
716
- if ((xhr.upload != null) && _this.progress) {
717
- xhr.upload.onprogress = function(event) {
718
- if (event.lengthComputable) {
719
- return _this.progress((event.position / event.total * 100).round(2));
720
- }
721
- };
722
- }
723
- return xhr;
724
- }
725
- });
726
- if (this.resource != null) {
727
- this.fill(this.resource, options);
728
- delete this.resource;
729
- }
730
- if (this.action != null) {
731
- this.container.attr('action', this.action);
732
- this.container.attr('method', 'POST');
733
- }
734
- if (this.method != null) {
735
- this.__markMethod(this.method);
736
- }
737
- }
738
-
739
- Form.prototype.unbind = function() {
740
- return this.container.unbind('submit').find('input:submit,input:image,button:submit').unbind('click');
741
- };
742
-
743
- Form.prototype.fill = function(resource, options) {
744
- var data, filler, url,
745
- _this = this;
746
- if (Object.isFunction(resource.build)) {
747
- resource = resource.build();
748
- }
749
- this.__resource = resource;
750
- if ((options != null ? options.decorator : void 0) != null) {
751
- data = options.decorator(resource.data);
752
- } else {
753
- data = resource.data;
754
- }
755
- filler = function(data, scope) {
756
- if (data.__joosy_form_filler_lock) {
757
- return;
758
- }
759
- data.__joosy_form_filler_lock = true;
760
- Object.each(data, function(property, val) {
761
- var entity, i, input, key, _i, _len, _ref, _results;
762
- key = _this.concatFieldName(scope, property);
763
- input = _this.$fields.filter("[name='" + key + "']:not(:file),[name='" + (key.underscore()) + "']:not(:file),[name='" + (key.camelize(false)) + "']:not(:file)");
764
- if (input.length > 0) {
765
- if (input.is(':checkbox')) {
766
- if (val) {
767
- input.attr('checked', 'checked');
768
- } else {
769
- input.removeAttr('checked');
770
- }
771
- } else if (input.is(':radio')) {
772
- input.filter("[value='" + val + "']").attr('checked', 'checked');
773
- } else {
774
- input.val(val);
775
- }
776
- }
777
- if (val instanceof Joosy.Resource.RESTCollection) {
778
- _ref = val.data;
779
- _results = [];
780
- for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
781
- entity = _ref[i];
782
- _results.push(filler(entity.data, _this.concatFieldName(scope, "[" + property + "_attributes][" + i + "]")));
783
- }
784
- return _results;
785
- } else if (val instanceof Joosy.Resource.REST) {
786
- return filler(val.data, _this.concatFieldName(scope, "[" + property + "_attributes][0]"));
787
- } else if (Object.isObject(val) || Object.isArray(val)) {
788
- return filler(val, key);
789
- } else {
790
-
791
- }
792
- });
793
- return delete data.__joosy_form_filler_lock;
794
- };
795
- filler(data, resource.__entityName || options.resourceName);
796
- $('input[name=_method]', this.container).remove();
797
- if (resource.id()) {
798
- this.__markMethod((options != null ? options.method : void 0) || 'PUT');
799
- }
800
- url = (options != null ? options.action : void 0) || (resource.id() != null ? resource.memberPath() : resource.collectionPath());
801
- this.container.attr('action', url);
802
- return this.container.attr('method', 'POST');
803
- };
659
+ })();
804
660
 
805
- Form.prototype.submit = function() {
806
- return this.container.submit();
807
- };
808
661
 
809
- Form.prototype.serialize = function(skipMethod) {
810
- var data;
811
- if (skipMethod == null) {
812
- skipMethod = true;
813
- }
814
- data = this.container.serialize();
815
- if (skipMethod) {
816
- data = data.replace(/\&?\_method\=put/i, '');
817
- }
818
- return data;
819
- };
662
+ /*** src/vendor/metamorph ***/
820
663
 
821
- Form.prototype.__success = function(response, status, xhr) {
822
- var _ref;
823
- if (xhr) {
824
- return typeof this.success === "function" ? this.success(response) : void 0;
825
- } else if ((200 <= (_ref = response.status) && _ref < 300)) {
826
- return this.success(response.json);
664
+ (function(window) {
665
+ var K, Metamorph, afterFunc, appendToFunc, document, endTagFunc, findChildById, firstNodeFor, fixParentage, guid, htmlFunc, movesWhitespace, needsShy, outerHTMLFunc, prependFunc, rangeFor, realNode, removeFunc, setInnerHTML, startTagFunc, supportsRange, wrapMap;
666
+ K = function() {};
667
+ guid = 0;
668
+ document = window.document;
669
+ supportsRange = document && ("createRange" in document) && (typeof Range !== "undefined") && Range.prototype.createContextualFragment;
670
+ needsShy = document && (function() {
671
+ var testEl;
672
+ testEl = document.createElement("div");
673
+ testEl.innerHTML = "<div></div>";
674
+ testEl.firstChild.innerHTML = "<script></script>";
675
+ return testEl.firstChild.innerHTML === "";
676
+ })();
677
+ movesWhitespace = document && (function() {
678
+ var testEl;
679
+ testEl = document.createElement("div");
680
+ testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
681
+ return testEl.childNodes[0].nodeValue === "Test:" && testEl.childNodes[2].nodeValue === " Value";
682
+ })();
683
+ Metamorph = function(html) {
684
+ var myGuid, self;
685
+ self = void 0;
686
+ if (this instanceof Metamorph) {
687
+ self = this;
827
688
  } else {
828
- return this.__error(response.json);
829
- }
830
- };
831
-
832
- Form.prototype.__before = function(xhr, settings) {
833
- if ((this.before == null) || this.before.apply(this, arguments) === true) {
834
- return this.$fields.removeClass(this.invalidationClass);
835
- }
836
- };
837
-
838
- Form.prototype.__error = function(data) {
839
- var error, errors,
840
- _this = this;
841
- errors = (function() {
842
- if (data.responseText) {
843
- try {
844
- return data = jQuery.parseJSON(data.responseText);
845
- } catch (_error) {
846
- error = _error;
847
- return {};
848
- }
849
- } else {
850
- return data;
851
- }
852
- })();
853
- if ((this.error == null) || this.error(errors) === true) {
854
- errors = this.__stringifyErrors(errors);
855
- Object.each(errors, function(field, notifications) {
856
- var input;
857
- input = _this.findField(field).addClass(_this.invalidationClass);
858
- return typeof _this.notification === "function" ? _this.notification(input, notifications) : void 0;
859
- });
860
- return errors;
861
- }
862
- return false;
863
- };
864
-
865
- Form.prototype.__debounce = function(xhr) {
866
- this.debugAs(this, "debounce: pending_request == " + this.__pending_request);
867
- if (this.__pending_request && this.debounce !== false) {
868
- if (this.debounce || Joosy.Application.debounceForms) {
869
- xhr.abort();
870
- this.debugAs(this, "debounce: xhr aborted");
871
- return true;
872
- }
873
- }
874
- return false;
875
- };
876
-
877
- Form.prototype.findField = function(field) {
878
- return this.$fields.filter("[name='" + field + "']");
879
- };
880
-
881
- Form.prototype.__markMethod = function(method) {
882
- if (method == null) {
883
- method = 'PUT';
689
+ self = new K();
884
690
  }
885
- method = $('<input/>', {
886
- type: 'hidden',
887
- name: '_method',
888
- value: method
889
- });
890
- return this.container.append(method);
691
+ self.innerHTML = html;
692
+ myGuid = "metamorph-" + (guid++);
693
+ self.start = myGuid + "-start";
694
+ self.end = myGuid + "-end";
695
+ return self;
891
696
  };
892
-
893
- Form.prototype.__stringifyErrors = function(errors) {
894
- var result,
895
- _this = this;
896
- result = {};
897
- Object.each(errors, function(field, notifications) {
898
- var f, name, splited, _i, _len;
899
- if (_this.substitutions[field] != null) {
900
- field = _this.substitutions[field];
901
- }
902
- if (Object.isObject(notifications) || _this.isArrayOfObjects(notifications)) {
903
- return Object.each(_this.__foldInlineEntities(notifications), function(key, value) {
904
- return result[field + key] = value;
905
- });
906
- } else {
907
- if (field.indexOf(".") !== -1) {
908
- splited = field.split('.');
909
- field = splited.shift();
910
- if (_this.resourceName || _this.__resource) {
911
- name = _this.resourceName || _this.__resource.__entityName;
912
- field = name + ("[" + field + "]");
913
- }
914
- for (_i = 0, _len = splited.length; _i < _len; _i++) {
915
- f = splited[_i];
916
- field += "[" + f + "]";
917
- }
918
- } else if (_this.resourceName || _this.__resource) {
919
- name = _this.resourceName || _this.__resource.__entityName;
920
- field = name + ("[" + field + "]");
921
- }
922
- return result[field] = notifications;
923
- }
924
- });
925
- return result;
697
+ K.prototype = Metamorph.prototype;
698
+ rangeFor = void 0;
699
+ htmlFunc = void 0;
700
+ removeFunc = void 0;
701
+ outerHTMLFunc = void 0;
702
+ appendToFunc = void 0;
703
+ afterFunc = void 0;
704
+ prependFunc = void 0;
705
+ startTagFunc = void 0;
706
+ endTagFunc = void 0;
707
+ outerHTMLFunc = function() {
708
+ return this.startTag() + this.innerHTML + this.endTag();
926
709
  };
927
-
928
- Form.prototype.__foldInlineEntities = function(hash, scope, result) {
929
- var _this = this;
930
- if (scope == null) {
931
- scope = "";
932
- }
933
- if (result == null) {
934
- result = {};
935
- }
936
- Object.each(hash, function(key, value) {
937
- if (Object.isObject(value) || _this.isArrayOfObjects(value)) {
938
- return _this.__foldInlineEntities(value, "" + scope + "[" + key + "]", result);
939
- } else {
940
- return result["" + scope + "[" + key + "]"] = value;
941
- }
942
- });
943
- return result;
710
+ startTagFunc = function() {
711
+ return "<script id='" + this.start + "' type='text/x-placeholder'></script>";
944
712
  };
945
-
946
- Form.prototype.concatFieldName = function(wrapper, name) {
947
- var items;
948
- items = this.splitFieldName(wrapper).concat(this.splitFieldName(name));
949
- return "" + items[0] + "[" + (items.slice(1).join('][')) + "]";
713
+ endTagFunc = function() {
714
+ return "<script id='" + this.end + "' type='text/x-placeholder'></script>";
950
715
  };
951
-
952
- Form.prototype.splitFieldName = function(name) {
953
- var first, items;
954
- items = name.split('][');
955
- first = items[0].split('[');
956
- if (first.length === 2) {
957
- if (first[0].isBlank()) {
958
- items.splice(0, 1, first[1]);
716
+ if (supportsRange) {
717
+ rangeFor = function(morph, outerToo) {
718
+ var after, before, range;
719
+ range = document.createRange();
720
+ before = document.getElementById(morph.start);
721
+ after = document.getElementById(morph.end);
722
+ if (outerToo) {
723
+ range.setStartBefore(before);
724
+ range.setEndAfter(after);
959
725
  } else {
960
- items.splice(0, 1, first[0], first[1]);
726
+ range.setStartAfter(before);
727
+ range.setEndBefore(after);
961
728
  }
962
- items[items.length - 1] = items[items.length - 1].split(']')[0];
963
- }
964
- return items;
965
- };
966
-
967
- Form.prototype.isArrayOfObjects = function(array) {
968
- return Object.isArray(array) && array.every(function(elem) {
969
- return Object.isObject(elem);
970
- });
971
- };
972
-
973
- return Form;
974
-
975
- })(Joosy.Module);
976
-
977
-
978
- /*** src/joosy/core/helpers/form ***/
979
-
980
- Joosy.helpers('Application', function() {
981
- var Form, description, input,
982
- _this = this;
983
- description = function(resource, method, extendIds, idSuffix) {
984
- var id;
985
- if (Joosy.Module.hasAncestor(resource.constructor, Joosy.Resource.Generic)) {
986
- id = resource.id();
987
- resource = resource.__entityName;
988
- }
989
- return {
990
- name: resource + ("" + (method.match(/^\[.*\]$/) ? method : "[" + method + "]")),
991
- id: resource + (id && extendIds ? '_' + id : '') + ("_" + (method.parameterize().underscore())) + (idSuffix ? '_' + idSuffix : '')
729
+ return range;
992
730
  };
993
- };
994
- input = function(type, resource, method, options) {
995
- var d;
996
- if (options == null) {
997
- options = {};
998
- }
999
- d = description(resource, method, options.extendIds, options.idSuffix);
1000
- delete options.extendIds;
1001
- delete options.idSuffix;
1002
- return _this.tag('input', Joosy.Module.merge({
1003
- type: type,
1004
- name: d.name,
1005
- id: d.id
1006
- }, options));
1007
- };
1008
- Form = (function() {
1009
- function Form(context, resource, options) {
1010
- this.context = context;
1011
- this.resource = resource;
1012
- this.options = options;
1013
- }
1014
-
1015
- Form.prototype.label = function(method, options, content) {
1016
- if (options == null) {
1017
- options = {};
1018
- }
1019
- if (content == null) {
1020
- content = '';
1021
- }
1022
- if (!Object.isObject(options)) {
1023
- content = options;
1024
- options = {};
1025
- }
1026
- return this.context.label(this.resource, method, Joosy.Module.merge({
1027
- extendIds: this.options.extendIds
1028
- }, options), content);
731
+ htmlFunc = function(html, outerToo) {
732
+ var fragment, range;
733
+ range = rangeFor(this, outerToo);
734
+ range.deleteContents();
735
+ fragment = range.createContextualFragment(html);
736
+ return range.insertNode(fragment);
1029
737
  };
1030
-
1031
- Form.prototype.radioButton = function(method, tagValue, options) {
1032
- if (options == null) {
1033
- options = {};
1034
- }
1035
- return this.context.radioButton(this.resource, method, tagValue, Joosy.Module.merge({
1036
- extendIds: this.options.extendIds
1037
- }, options));
738
+ removeFunc = function() {
739
+ var range;
740
+ range = rangeFor(this, true);
741
+ return range.deleteContents();
1038
742
  };
1039
-
1040
- Form.prototype.textArea = function(method, options) {
1041
- if (options == null) {
1042
- options = {};
1043
- }
1044
- return this.context.textArea(this.resource, method, Joosy.Module.merge({
1045
- extendIds: this.options.extendIds
1046
- }, options));
743
+ appendToFunc = function(node) {
744
+ var frag, range;
745
+ range = document.createRange();
746
+ range.setStart(node);
747
+ range.collapse(false);
748
+ frag = range.createContextualFragment(this.outerHTML());
749
+ return node.appendChild(frag);
1047
750
  };
1048
-
1049
- Form.prototype.checkBox = function(method, options, checkedValue, uncheckedValue) {
1050
- if (options == null) {
1051
- options = {};
1052
- }
1053
- if (checkedValue == null) {
1054
- checkedValue = 1;
1055
- }
1056
- if (uncheckedValue == null) {
1057
- uncheckedValue = 0;
1058
- }
1059
- return this.context.checkBox(this.resource, method, Joosy.Module.merge({
1060
- extendIds: this.options.extendIds
1061
- }, options), checkedValue, uncheckedValue);
751
+ afterFunc = function(html) {
752
+ var after, fragment, range;
753
+ range = document.createRange();
754
+ after = document.getElementById(this.end);
755
+ range.setStartAfter(after);
756
+ range.setEndAfter(after);
757
+ fragment = range.createContextualFragment(html);
758
+ return range.insertNode(fragment);
1062
759
  };
1063
-
1064
- Form.prototype.select = function(method, options, htmlOptions) {
1065
- if (options == null) {
1066
- options = {};
1067
- }
1068
- if (htmlOptions == null) {
1069
- htmlOptions = {};
1070
- }
1071
- return this.context.select(this.resource, method, options, Joosy.Module.merge({
1072
- extendIds: this.options.extendIds
1073
- }, htmlOptions));
760
+ prependFunc = function(html) {
761
+ var fragment, range, start;
762
+ range = document.createRange();
763
+ start = document.getElementById(this.start);
764
+ range.setStartAfter(start);
765
+ range.setEndAfter(start);
766
+ fragment = range.createContextualFragment(html);
767
+ return range.insertNode(fragment);
1074
768
  };
769
+ } else {
770
+ /*
771
+ This code is mostly taken from jQuery, with one exception. In jQuery's case, we
772
+ have some HTML and we need to figure out how to convert it into some nodes.
773
+
774
+ In this case, jQuery needs to scan the HTML looking for an opening tag and use
775
+ that as the key for the wrap map. In our case, we know the parent node, and
776
+ can use its type as the key for the wrap map.
777
+ */
1075
778
 
1076
- return Form;
1077
-
1078
- })();
1079
- ['text', 'file', 'hidden', 'password'].each(function(type) {
1080
- return Form.prototype[type + 'Field'] = function(method, options) {
1081
- if (options == null) {
1082
- options = {};
1083
- }
1084
- return this.context[type + 'Field'](this.resource, method, Joosy.Module.merge({
1085
- extendIds: this.options.extendIds
1086
- }, options));
779
+ wrapMap = {
780
+ select: [1, "<select multiple='multiple'>", "</select>"],
781
+ fieldset: [1, "<fieldset>", "</fieldset>"],
782
+ table: [1, "<table>", "</table>"],
783
+ tbody: [2, "<table><tbody>", "</tbody></table>"],
784
+ tr: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
785
+ colgroup: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"],
786
+ map: [1, "<map>", "</map>"],
787
+ _default: [0, "", ""]
1087
788
  };
1088
- });
1089
- this.formFor = function(resource, options, block) {
1090
- var form, uuid;
1091
- if (options == null) {
1092
- options = {};
1093
- }
1094
- if (Object.isFunction(options)) {
1095
- block = options;
1096
- options = {};
1097
- }
1098
- uuid = Joosy.uuid();
1099
- form = this.tag('form', Joosy.Module.merge(options.html || {}, {
1100
- id: uuid
1101
- }), block != null ? block.call(this, new Form(this, resource, options)) : void 0);
1102
- if (typeof this.onRefresh === "function") {
1103
- this.onRefresh(function() {
1104
- return Joosy.Form.attach('#' + uuid, Joosy.Module.merge(options, {
1105
- resource: resource
1106
- }));
1107
- });
1108
- }
1109
- return form;
1110
- };
1111
- this.label = function(resource, method, options, content) {
1112
- var d;
1113
- if (options == null) {
1114
- options = {};
1115
- }
1116
- if (content == null) {
1117
- content = '';
1118
- }
1119
- if (!Object.isObject(options)) {
1120
- content = options;
1121
- options = {};
1122
- }
1123
- d = description(resource, method, options.extendIds);
1124
- delete options.extendIds;
1125
- return this.tag('label', Joosy.Module.merge(options, {
1126
- "for": d.id
1127
- }), content);
1128
- };
1129
- ['text', 'file', 'hidden', 'password'].each(function(type) {
1130
- return _this[type + 'Field'] = function(resource, method, options) {
1131
- if (options == null) {
1132
- options = {};
1133
- }
1134
- return input(type, resource, method, options);
1135
- };
1136
- });
1137
- this.radioButton = function(resource, method, tagValue, options) {
1138
- if (options == null) {
1139
- options = {};
1140
- }
1141
- return input('radio', resource, method, Joosy.Module.merge({
1142
- value: tagValue,
1143
- idSuffix: tagValue
1144
- }, options));
1145
- };
1146
- this.checkBox = function(resource, method, options, checkedValue, uncheckedValue) {
1147
- var box, spy;
1148
- if (options == null) {
1149
- options = {};
1150
- }
1151
- if (checkedValue == null) {
1152
- checkedValue = 1;
1153
- }
1154
- if (uncheckedValue == null) {
1155
- uncheckedValue = 0;
1156
- }
1157
- spy = this.tag('input', Joosy.Module.merge({
1158
- name: description(resource, method).name,
1159
- value: uncheckedValue,
1160
- type: 'hidden'
1161
- }));
1162
- box = input('checkbox', resource, method, Joosy.Module.merge({
1163
- value: checkedValue
1164
- }, options));
1165
- return spy + box;
1166
- };
1167
- this.select = function(resource, method, options, htmlOptions) {
1168
- var extendIds, key, opts, val,
1169
- _this = this;
1170
- if (Object.isObject(options)) {
1171
- opts = [];
1172
- for (key in options) {
1173
- val = options[key];
1174
- opts.push([val, key]);
1175
- }
1176
- } else {
1177
- opts = options;
1178
- }
1179
- if (htmlOptions.includeBlank) {
1180
- delete htmlOptions.includeBlank;
1181
- opts.unshift(['', '']);
1182
- }
1183
- opts = opts.reduce(function(str, vals) {
1184
- var params;
1185
- params = Object.isArray(vals) ? [
1186
- 'option', {
1187
- value: vals[1]
1188
- }, vals[0]
1189
- ] : ['option', {}, vals];
1190
- if (htmlOptions.value === (Object.isArray(vals) ? vals[1] : vals)) {
1191
- params[1].selected = 'selected';
1192
- }
1193
- return str += _this.tag.apply(_this, params);
1194
- }, '');
1195
- extendIds = htmlOptions.extendIds;
1196
- delete htmlOptions.value;
1197
- delete htmlOptions.extendIds;
1198
- return this.tag('select', Joosy.Module.merge(description(resource, method, extendIds), htmlOptions), opts);
1199
- };
1200
- return this.textArea = function(resource, method, options) {
1201
- var extendIds, value;
1202
- if (options == null) {
1203
- options = {};
1204
- }
1205
- value = options.value;
1206
- extendIds = options.extendIds;
1207
- delete options.value;
1208
- delete options.extendIds;
1209
- return this.tag('textarea', Joosy.Module.merge(description(resource, method, extendIds), options), value);
1210
- };
1211
- });
1212
-
1213
-
1214
- /*** src/joosy/core/helpers/view ***/
1215
-
1216
- Joosy.helpers('Application', function() {
1217
- this.tag = function(name, options, content) {
1218
- var e, element, temp;
1219
- if (options == null) {
1220
- options = {};
1221
- }
1222
- if (content == null) {
1223
- content = '';
1224
- }
1225
- if (Object.isFunction(content)) {
1226
- content = content();
1227
- }
1228
- element = document.createElement(name);
1229
- temp = document.createElement('div');
1230
- Object.each(options, function(name, value) {
1231
- return element.setAttribute(name, value);
1232
- });
1233
- try {
1234
- element.innerHTML = content;
1235
- } catch (_error) {
1236
- e = _error;
1237
- if (content) {
1238
- throw e;
1239
- }
1240
- }
1241
- temp.appendChild(element);
1242
- return temp.innerHTML;
1243
- };
1244
- this.nl2br = function(text) {
1245
- return text.toString().replace(/\n/g, '<br/>');
1246
- };
1247
- return this.renderWrapped = function(template, lambda) {
1248
- return this.render(template, Joosy.Module.merge(this, {
1249
- "yield": lambda()
1250
- }));
1251
- };
1252
- });
1253
-
1254
-
1255
- /*** src/joosy/core/helpers/widgets ***/
1256
-
1257
- Joosy.helpers('Application', function() {
1258
- return this.widget = function(element, widget) {
1259
- var params, parts, uuid;
1260
- uuid = Joosy.uuid();
1261
- params = {
1262
- id: uuid
1263
- };
1264
- parts = element.split('.');
1265
- if (parts[1]) {
1266
- params["class"] = parts.from(1).join(' ');
1267
- }
1268
- element = this.tag(parts[0], params);
1269
- this.onRefresh(function() {
1270
- return this.registerWidget('#' + uuid, widget);
1271
- });
1272
- return element;
1273
- };
1274
- });
1275
-
1276
-
1277
- /*** src/joosy/core/templaters/rails_jst ***/
1278
-
1279
- Joosy.Templaters.RailsJST = (function() {
1280
- function RailsJST(applicationName) {
1281
- this.applicationName = applicationName;
1282
- }
1283
-
1284
- RailsJST.prototype.buildView = function(name) {
1285
- var haystack, template;
1286
- template = false;
1287
- 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];
1288
- haystack.each(function(path) {
1289
- var location;
1290
- if (JST[path]) {
1291
- location = path;
1292
- return template = JST[path];
1293
- }
1294
- });
1295
- if (!template) {
1296
- throw new Error("Template '" + name + "' not found. Checked at: " + location);
1297
- }
1298
- return template;
1299
- };
1300
-
1301
- RailsJST.prototype.resolveTemplate = function(section, template, entity) {
1302
- var path, _ref, _ref1;
1303
- if (template.startsWith('/')) {
1304
- return template.substr(1);
1305
- }
1306
- path = ((_ref = entity.constructor) != null ? (_ref1 = _ref.__namespace__) != null ? _ref1.map('underscore') : void 0 : void 0) || [];
1307
- path.unshift(section);
1308
- return "" + (path.join('/')) + "/" + template;
1309
- };
1310
-
1311
- return RailsJST;
1312
-
1313
- })();
1314
-
1315
-
1316
- /*** src/vendor/metamorph ***/
1317
-
1318
- (function(window) {
1319
- var K, Metamorph, afterFunc, appendToFunc, document, endTagFunc, findChildById, firstNodeFor, fixParentage, guid, htmlFunc, movesWhitespace, needsShy, outerHTMLFunc, prependFunc, rangeFor, realNode, removeFunc, setInnerHTML, startTagFunc, supportsRange, wrapMap;
1320
- K = function() {};
1321
- guid = 0;
1322
- document = window.document;
1323
- supportsRange = document && ("createRange" in document) && (typeof Range !== "undefined") && Range.prototype.createContextualFragment;
1324
- needsShy = document && (function() {
1325
- var testEl;
1326
- testEl = document.createElement("div");
1327
- testEl.innerHTML = "<div></div>";
1328
- testEl.firstChild.innerHTML = "<script></script>";
1329
- return testEl.firstChild.innerHTML === "";
1330
- })();
1331
- movesWhitespace = document && (function() {
1332
- var testEl;
1333
- testEl = document.createElement("div");
1334
- testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
1335
- return testEl.childNodes[0].nodeValue === "Test:" && testEl.childNodes[2].nodeValue === " Value";
1336
- })();
1337
- Metamorph = function(html) {
1338
- var myGuid, self;
1339
- self = void 0;
1340
- if (this instanceof Metamorph) {
1341
- self = this;
1342
- } else {
1343
- self = new K();
1344
- }
1345
- self.innerHTML = html;
1346
- myGuid = "metamorph-" + (guid++);
1347
- self.start = myGuid + "-start";
1348
- self.end = myGuid + "-end";
1349
- return self;
1350
- };
1351
- K.prototype = Metamorph.prototype;
1352
- rangeFor = void 0;
1353
- htmlFunc = void 0;
1354
- removeFunc = void 0;
1355
- outerHTMLFunc = void 0;
1356
- appendToFunc = void 0;
1357
- afterFunc = void 0;
1358
- prependFunc = void 0;
1359
- startTagFunc = void 0;
1360
- endTagFunc = void 0;
1361
- outerHTMLFunc = function() {
1362
- return this.startTag() + this.innerHTML + this.endTag();
1363
- };
1364
- startTagFunc = function() {
1365
- return "<script id='" + this.start + "' type='text/x-placeholder'></script>";
1366
- };
1367
- endTagFunc = function() {
1368
- return "<script id='" + this.end + "' type='text/x-placeholder'></script>";
1369
- };
1370
- if (supportsRange) {
1371
- rangeFor = function(morph, outerToo) {
1372
- var after, before, range;
1373
- range = document.createRange();
1374
- before = document.getElementById(morph.start);
1375
- after = document.getElementById(morph.end);
1376
- if (outerToo) {
1377
- range.setStartBefore(before);
1378
- range.setEndAfter(after);
1379
- } else {
1380
- range.setStartAfter(before);
1381
- range.setEndBefore(after);
1382
- }
1383
- return range;
1384
- };
1385
- htmlFunc = function(html, outerToo) {
1386
- var fragment, range;
1387
- range = rangeFor(this, outerToo);
1388
- range.deleteContents();
1389
- fragment = range.createContextualFragment(html);
1390
- return range.insertNode(fragment);
1391
- };
1392
- removeFunc = function() {
1393
- var range;
1394
- range = rangeFor(this, true);
1395
- return range.deleteContents();
1396
- };
1397
- appendToFunc = function(node) {
1398
- var frag, range;
1399
- range = document.createRange();
1400
- range.setStart(node);
1401
- range.collapse(false);
1402
- frag = range.createContextualFragment(this.outerHTML());
1403
- return node.appendChild(frag);
1404
- };
1405
- afterFunc = function(html) {
1406
- var after, fragment, range;
1407
- range = document.createRange();
1408
- after = document.getElementById(this.end);
1409
- range.setStartAfter(after);
1410
- range.setEndAfter(after);
1411
- fragment = range.createContextualFragment(html);
1412
- return range.insertNode(fragment);
1413
- };
1414
- prependFunc = function(html) {
1415
- var fragment, range, start;
1416
- range = document.createRange();
1417
- start = document.getElementById(this.start);
1418
- range.setStartAfter(start);
1419
- range.setEndAfter(start);
1420
- fragment = range.createContextualFragment(html);
1421
- return range.insertNode(fragment);
1422
- };
1423
- } else {
1424
- /*
1425
- This code is mostly taken from jQuery, with one exception. In jQuery's case, we
1426
- have some HTML and we need to figure out how to convert it into some nodes.
1427
-
1428
- In this case, jQuery needs to scan the HTML looking for an opening tag and use
1429
- that as the key for the wrap map. In our case, we know the parent node, and
1430
- can use its type as the key for the wrap map.
1431
- */
1432
-
1433
- wrapMap = {
1434
- select: [1, "<select multiple='multiple'>", "</select>"],
1435
- fieldset: [1, "<fieldset>", "</fieldset>"],
1436
- table: [1, "<table>", "</table>"],
1437
- tbody: [2, "<table><tbody>", "</tbody></table>"],
1438
- tr: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
1439
- colgroup: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"],
1440
- map: [1, "<map>", "</map>"],
1441
- _default: [0, "", ""]
1442
- };
1443
- findChildById = function(element, id) {
1444
- var found, idx, len, node;
1445
- if (element.getAttribute("id") === id) {
1446
- return element;
1447
- }
1448
- len = element.childNodes.length;
1449
- idx = void 0;
1450
- node = void 0;
1451
- found = void 0;
1452
- idx = 0;
1453
- while (idx < len) {
1454
- node = element.childNodes[idx];
1455
- found = node.nodeType === 1 && findChildById(node, id);
1456
- if (found) {
1457
- return found;
1458
- }
1459
- idx++;
1460
- }
1461
- };
1462
- setInnerHTML = function(element, html) {
1463
- var idx, len, matches, node, script, _results;
1464
- matches = [];
1465
- if (movesWhitespace) {
1466
- html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
1467
- matches.push([id, spaces]);
1468
- return tag;
1469
- });
1470
- }
1471
- element.innerHTML = html;
1472
- if (matches.length > 0) {
1473
- len = matches.length;
1474
- idx = void 0;
1475
- idx = 0;
1476
- _results = [];
1477
- while (idx < len) {
1478
- script = findChildById(element, matches[idx][0]);
1479
- node = document.createTextNode(matches[idx][1]);
1480
- script.parentNode.insertBefore(node, script);
1481
- _results.push(idx++);
1482
- }
1483
- return _results;
1484
- }
1485
- };
1486
- /*
1487
- Given a parent node and some HTML, generate a set of nodes. Return the first
1488
- node, which will allow us to traverse the rest using nextSibling.
1489
-
1490
- We need to do this because innerHTML in IE does not really parse the nodes.
1491
- */
1492
-
1493
- firstNodeFor = function(parentNode, html) {
1494
- var arr, depth, element, end, i, shyElement, start;
1495
- arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
1496
- depth = arr[0];
1497
- start = arr[1];
1498
- end = arr[2];
1499
- if (needsShy) {
1500
- html = "&shy;" + html;
1501
- }
1502
- element = document.createElement("div");
1503
- setInnerHTML(element, start + html + end);
1504
- i = 0;
1505
- while (i <= depth) {
1506
- element = element.firstChild;
1507
- i++;
1508
- }
1509
- if (needsShy) {
1510
- shyElement = element;
1511
- while (shyElement.nodeType === 1 && !shyElement.nodeName) {
1512
- shyElement = shyElement.firstChild;
1513
- }
1514
- if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "­") {
1515
- shyElement.nodeValue = shyElement.nodeValue.slice(1);
1516
- }
1517
- }
1518
- return element;
1519
- };
1520
- /*
1521
- In some cases, Internet Explorer can create an anonymous node in
1522
- the hierarchy with no tagName. You can create this scenario via:
1523
-
1524
- div = document.createElement("div");
1525
- div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
1526
- div.firstChild.firstChild.tagName //=> ""
1527
-
1528
- If our script markers are inside such a node, we need to find that
1529
- node and use *it* as the marker.
1530
- */
1531
-
1532
- realNode = function(start) {
1533
- while (start.parentNode.tagName === "") {
1534
- start = start.parentNode;
1535
- }
1536
- return start;
1537
- };
1538
- /*
1539
- When automatically adding a tbody, Internet Explorer inserts the
1540
- tbody immediately before the first <tr>. Other browsers create it
1541
- before the first node, no matter what.
1542
-
1543
- This means the the following code:
1544
-
1545
- div = document.createElement("div");
1546
- div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
1547
-
1548
- Generates the following DOM in IE:
1549
-
1550
- + div
1551
- + table
1552
- - script id='first'
1553
- + tbody
1554
- + tr
1555
- + td
1556
- - "hi"
1557
- - script id='last'
1558
-
1559
- Which means that the two script tags, even though they were
1560
- inserted at the same point in the hierarchy in the original
1561
- HTML, now have different parents.
1562
-
1563
- This code reparents the first script tag by making it the tbody's
1564
- first child.
1565
- */
1566
-
1567
- fixParentage = function(start, end) {
1568
- if (start.parentNode !== end.parentNode) {
1569
- return end.parentNode.insertBefore(start, end.parentNode.firstChild);
1570
- }
1571
- };
1572
- htmlFunc = function(html, outerToo) {
1573
- var end, last, nextSibling, node, parentNode, start, _results;
1574
- start = realNode(document.getElementById(this.start));
1575
- end = document.getElementById(this.end);
1576
- parentNode = end.parentNode;
1577
- node = void 0;
1578
- nextSibling = void 0;
1579
- last = void 0;
1580
- fixParentage(start, end);
1581
- node = start.nextSibling;
1582
- while (node) {
1583
- nextSibling = node.nextSibling;
1584
- last = node === end;
1585
- if (last) {
1586
- if (outerToo) {
1587
- end = node.nextSibling;
1588
- } else {
1589
- break;
1590
- }
1591
- }
1592
- node.parentNode.removeChild(node);
1593
- if (last) {
1594
- break;
1595
- }
1596
- node = nextSibling;
1597
- }
1598
- node = firstNodeFor(start.parentNode, html);
1599
- _results = [];
1600
- while (node) {
1601
- nextSibling = node.nextSibling;
1602
- parentNode.insertBefore(node, end);
1603
- _results.push(node = nextSibling);
1604
- }
1605
- return _results;
1606
- };
1607
- removeFunc = function() {
1608
- var end, start;
1609
- start = realNode(document.getElementById(this.start));
1610
- end = document.getElementById(this.end);
1611
- this.html("");
1612
- start.parentNode.removeChild(start);
1613
- return end.parentNode.removeChild(end);
1614
- };
1615
- appendToFunc = function(parentNode) {
1616
- var nextSibling, node, _results;
1617
- node = firstNodeFor(parentNode, this.outerHTML());
1618
- nextSibling = void 0;
1619
- _results = [];
1620
- while (node) {
1621
- nextSibling = node.nextSibling;
1622
- parentNode.appendChild(node);
1623
- _results.push(node = nextSibling);
1624
- }
1625
- return _results;
1626
- };
1627
- afterFunc = function(html) {
1628
- var end, insertBefore, nextSibling, node, parentNode, _results;
1629
- end = document.getElementById(this.end);
1630
- insertBefore = end.nextSibling;
1631
- parentNode = end.parentNode;
1632
- nextSibling = void 0;
1633
- node = void 0;
1634
- node = firstNodeFor(parentNode, html);
1635
- _results = [];
1636
- while (node) {
1637
- nextSibling = node.nextSibling;
1638
- parentNode.insertBefore(node, insertBefore);
1639
- _results.push(node = nextSibling);
1640
- }
1641
- return _results;
1642
- };
1643
- prependFunc = function(html) {
1644
- var insertBefore, nextSibling, node, parentNode, start, _results;
1645
- start = document.getElementById(this.start);
1646
- parentNode = start.parentNode;
1647
- nextSibling = void 0;
1648
- node = void 0;
1649
- node = firstNodeFor(parentNode, html);
1650
- insertBefore = start.nextSibling;
1651
- _results = [];
1652
- while (node) {
1653
- nextSibling = node.nextSibling;
1654
- parentNode.insertBefore(node, insertBefore);
1655
- _results.push(node = nextSibling);
1656
- }
1657
- return _results;
1658
- };
1659
- }
1660
- Metamorph.prototype.html = function(html) {
1661
- this.checkRemoved();
1662
- if (html === undefined) {
1663
- return this.innerHTML;
1664
- }
1665
- htmlFunc.call(this, html);
1666
- return this.innerHTML = html;
1667
- };
1668
- Metamorph.prototype.replaceWith = function(html) {
1669
- this.checkRemoved();
1670
- return htmlFunc.call(this, html, true);
1671
- };
1672
- Metamorph.prototype.remove = removeFunc;
1673
- Metamorph.prototype.outerHTML = outerHTMLFunc;
1674
- Metamorph.prototype.appendTo = appendToFunc;
1675
- Metamorph.prototype.after = afterFunc;
1676
- Metamorph.prototype.prepend = prependFunc;
1677
- Metamorph.prototype.startTag = startTagFunc;
1678
- Metamorph.prototype.endTag = endTagFunc;
1679
- Metamorph.prototype.isRemoved = function() {
1680
- var after, before;
1681
- before = document.getElementById(this.start);
1682
- after = document.getElementById(this.end);
1683
- return !before || !after;
1684
- };
1685
- Metamorph.prototype.checkRemoved = function() {
1686
- if (this.isRemoved()) {
1687
- throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
1688
- }
1689
- };
1690
- return window.Metamorph = Metamorph;
1691
- })(this);
1692
-
1693
-
1694
- /*** src/joosy/core/modules/renderer ***/
1695
-
1696
- var __slice = [].slice;
1697
-
1698
- Joosy.Modules.Renderer = {
1699
- __renderer: function() {
1700
- throw new Error("" + (Joosy.Module.__className(this.constructor)) + " does not have an attached template");
1701
- },
1702
- __helpers: null,
1703
- included: function() {
1704
- this.view = function(template, options) {
1705
- if (options == null) {
1706
- options = {};
1707
- }
1708
- if (Object.isFunction(template)) {
1709
- return this.prototype.__renderer = template;
1710
- } else {
1711
- return this.prototype.__renderer = function(locals) {
1712
- if (locals == null) {
1713
- locals = {};
1714
- }
1715
- if (options.dynamic) {
1716
- return this.renderDynamic(template, locals);
1717
- } else {
1718
- return this.render(template, locals);
1719
- }
1720
- };
1721
- }
1722
- };
1723
- return this.helpers = function() {
1724
- var helpers, _base,
1725
- _this = this;
1726
- helpers = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1727
- (_base = this.prototype).__helpers || (_base.__helpers = []);
1728
- helpers.map(function(helper) {
1729
- var module;
1730
- module = Joosy.Helpers[helper];
1731
- if (!module) {
1732
- throw new Error("Cannot find helper module " + helper);
1733
- }
1734
- return _this.prototype.__helpers.push(module);
1735
- });
1736
- return this.prototype.__helpers = this.prototype.__helpers.unique();
1737
- };
1738
- },
1739
- __instantiateHelpers: function() {
1740
- var helper, _i, _len, _ref,
1741
- _this = this;
1742
- if (!this.__helpersInstance) {
1743
- this.__helpersInstance = Object.extended(Joosy.Helpers.Application);
1744
- if (this.onRefresh) {
1745
- this.__helpersInstance.onRefresh = function(callback) {
1746
- return _this.onRefresh(callback);
1747
- };
1748
- }
1749
- if (this.__helpers) {
1750
- _ref = this.__helpers;
1751
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1752
- helper = _ref[_i];
1753
- Joosy.Module.merge(this.__helpersInstance, helper);
1754
- }
1755
- }
1756
- }
1757
- return this.__helpersInstance;
1758
- },
1759
- __proxifyHelpers: function(locals) {
1760
- if (locals.hasOwnProperty('__proto__')) {
1761
- locals.__proto__ = this.__instantiateHelpers();
1762
- return locals;
1763
- } else {
1764
- if (!this.__helpersProxyInstance) {
1765
- this.__helpersProxyInstance = function(locals) {
1766
- return Joosy.Module.merge(this, locals);
1767
- };
1768
- this.__helpersProxyInstance.prototype = this.__instantiateHelpers();
1769
- }
1770
- return new this.__helpersProxyInstance(locals);
1771
- }
1772
- },
1773
- render: function(template, locals, parentStackPointer) {
1774
- if (locals == null) {
1775
- locals = {};
1776
- }
1777
- if (parentStackPointer == null) {
1778
- parentStackPointer = false;
1779
- }
1780
- return this.__render(false, template, locals, parentStackPointer);
1781
- },
1782
- renderDynamic: function(template, locals, parentStackPointer) {
1783
- if (locals == null) {
1784
- locals = {};
1785
- }
1786
- if (parentStackPointer == null) {
1787
- parentStackPointer = false;
1788
- }
1789
- return this.__render(true, template, locals, parentStackPointer);
1790
- },
1791
- __render: function(dynamic, template, locals, parentStackPointer) {
1792
- var assignContext, binding, context, isCollection, isResource, key, morph, object, renderers, resource, result, stack, update, _i, _len, _ref,
1793
- _this = this;
1794
- if (locals == null) {
1795
- locals = {};
1796
- }
1797
- if (parentStackPointer == null) {
1798
- parentStackPointer = false;
1799
- }
1800
- stack = this.__renderingStackChildFor(parentStackPointer);
1801
- stack.template = template;
1802
- stack.locals = locals;
1803
- assignContext = false;
1804
- isResource = Joosy.Module.hasAncestor(locals.constructor, Joosy.Resource.Generic);
1805
- isCollection = Joosy.Module.hasAncestor(locals.constructor, Joosy.Resource.Collection);
1806
- if (Object.isString(template)) {
1807
- if (this.__renderSection != null) {
1808
- template = Joosy.Application.templater.resolveTemplate(this.__renderSection(), template, this);
1809
- }
1810
- template = Joosy.Application.templater.buildView(template);
1811
- } else if (Object.isFunction(template)) {
1812
- assignContext = true;
1813
- } else if (!Object.isFunction(template)) {
1814
- throw new Error("" + (Joosy.Module.__className(this)) + "> template (maybe @view) does not look like a string or lambda");
1815
- }
1816
- if (!Object.isObject(locals) && Object.extended().constructor !== locals.constructor && !isResource && !isCollection) {
1817
- throw new Error("" + (Joosy.Module.__className(this)) + "> locals (maybe @data?) not in: dumb hash, Resource, Collection");
1818
- }
1819
- renderers = {
1820
- render: function(template, locals) {
1821
- if (locals == null) {
1822
- locals = {};
1823
- }
1824
- return _this.render(template, locals, stack);
1825
- },
1826
- renderDynamic: function(template, locals) {
1827
- if (locals == null) {
1828
- locals = {};
1829
- }
1830
- return _this.renderDynamic(template, locals, stack);
1831
- },
1832
- renderInline: function(locals, template) {
1833
- if (locals == null) {
1834
- locals = {};
1835
- }
1836
- return _this.renderDynamic(template, locals, stack);
1837
- }
1838
- };
1839
- context = function() {
1840
- var data;
1841
- data = {};
1842
- if (isResource) {
1843
- Joosy.Module.merge(data, stack.locals.data);
1844
- } else {
1845
- Joosy.Module.merge(data, stack.locals);
1846
- }
1847
- Joosy.Module.merge(data, _this.__instantiateHelpers(), false);
1848
- Joosy.Module.merge(data, renderers);
1849
- return data;
1850
- };
1851
- result = function() {
1852
- if (assignContext) {
1853
- return template.call(context());
1854
- } else {
1855
- return template(context());
1856
- }
1857
- };
1858
- if (dynamic) {
1859
- morph = Metamorph(result());
1860
- update = function() {
1861
- var callback, child, object, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;
1862
- if (morph.isRemoved()) {
1863
- _ref = morph.__bindings;
1864
- _results = [];
1865
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1866
- _ref1 = _ref[_i], object = _ref1[0], callback = _ref1[1];
1867
- _results.push(object.unbind(callback));
1868
- }
1869
- return _results;
1870
- } else {
1871
- _ref2 = stack.children;
1872
- for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
1873
- child = _ref2[_j];
1874
- _this.__removeMetamorphs(child);
1875
- }
1876
- stack.children = [];
1877
- morph.html(result());
1878
- return typeof _this.refreshElements === "function" ? _this.refreshElements() : void 0;
1879
- }
1880
- };
1881
- update = update.debounce(0);
1882
- morph.__bindings = [];
1883
- if (isCollection) {
1884
- _ref = locals.data;
1885
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1886
- resource = _ref[_i];
1887
- binding = [resource, update];
1888
- resource.bind('changed', update);
1889
- stack.metamorphBindings.push(binding);
1890
- morph.__bindings.push(binding);
1891
- }
1892
- }
1893
- if (isResource || isCollection) {
1894
- binding = [locals, update];
1895
- locals.bind('changed', update);
1896
- stack.metamorphBindings.push(binding);
1897
- morph.__bindings.push(binding);
1898
- } else {
1899
- for (key in locals) {
1900
- object = locals[key];
1901
- if (locals.hasOwnProperty(key)) {
1902
- if (((object != null ? object.bind : void 0) != null) && ((object != null ? object.unbind : void 0) != null)) {
1903
- binding = [object, update];
1904
- object.bind('changed', update);
1905
- stack.metamorphBindings.push(binding);
1906
- morph.__bindings.push(binding);
1907
- }
1908
- }
1909
- }
1910
- }
1911
- return morph.outerHTML();
1912
- } else {
1913
- return result();
1914
- }
1915
- },
1916
- __renderingStackElement: function(parent) {
1917
- if (parent == null) {
1918
- parent = null;
1919
- }
1920
- return {
1921
- metamorphBindings: [],
1922
- locals: null,
1923
- template: null,
1924
- children: [],
1925
- parent: parent
1926
- };
1927
- },
1928
- __renderingStackChildFor: function(parentPointer) {
1929
- var element;
1930
- if (!this.__renderingStack) {
1931
- this.__renderingStack = [];
1932
- }
1933
- if (!parentPointer) {
1934
- element = this.__renderingStackElement();
1935
- this.__renderingStack.push(element);
1936
- return element;
1937
- } else {
1938
- element = this.__renderingStackElement(parentPointer);
1939
- parentPointer.children.push(element);
1940
- return element;
1941
- }
1942
- },
1943
- __removeMetamorphs: function(stackPointer) {
1944
- var remove, _ref,
1945
- _this = this;
1946
- if (stackPointer == null) {
1947
- stackPointer = false;
1948
- }
1949
- remove = function(stackPointer) {
1950
- var callback, child, object, _i, _j, _len, _len1, _ref, _ref1, _ref2;
1951
- if (stackPointer != null ? stackPointer.children : void 0) {
1952
- _ref = stackPointer.children;
1953
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1954
- child = _ref[_i];
1955
- _this.__removeMetamorphs(child);
1956
- }
1957
- }
1958
- if (stackPointer != null ? stackPointer.metamorphBindings : void 0) {
1959
- _ref1 = stackPointer.metamorphBindings;
1960
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
1961
- _ref2 = _ref1[_j], object = _ref2[0], callback = _ref2[1];
1962
- object.unbind(callback);
1963
- }
1964
- return stackPointer.metamorphBindings = [];
1965
- }
1966
- };
1967
- if (!stackPointer) {
1968
- return (_ref = this.__renderingStack) != null ? _ref.each(function(stackPointer) {
1969
- return remove(stackPointer);
1970
- }) : void 0;
1971
- } else {
1972
- return remove(stackPointer);
1973
- }
1974
- }
1975
- };
1976
-
1977
-
1978
- /*** src/joosy/core/modules/time_manager ***/
1979
-
1980
- Joosy.Modules.TimeManager = {
1981
- setTimeout: function(timeout, action) {
1982
- var timer,
1983
- _this = this;
1984
- this.__timeouts || (this.__timeouts = []);
1985
- timer = window.setTimeout((function() {
1986
- return action();
1987
- }), timeout);
1988
- this.__timeouts.push(timer);
1989
- return timer;
1990
- },
1991
- setInterval: function(delay, action) {
1992
- var timer,
1993
- _this = this;
1994
- this.__intervals || (this.__intervals = []);
1995
- timer = window.setInterval((function() {
1996
- return action();
1997
- }), delay);
1998
- this.__intervals.push(timer);
1999
- return timer;
2000
- },
2001
- __clearTime: function() {
2002
- var entry, _i, _j, _len, _len1, _ref, _ref1, _results;
2003
- if (this.__intervals) {
2004
- _ref = this.__intervals;
2005
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2006
- entry = _ref[_i];
2007
- window.clearInterval(entry);
2008
- }
2009
- }
2010
- if (this.__timeouts) {
2011
- _ref1 = this.__timeouts;
2012
- _results = [];
2013
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
2014
- entry = _ref1[_j];
2015
- _results.push(window.clearTimeout(entry));
2016
- }
2017
- return _results;
2018
- }
2019
- }
2020
- };
2021
-
2022
-
2023
- /*** src/joosy/core/modules/widgets_manager ***/
2024
-
2025
- Joosy.Modules.WidgetsManager = {
2026
- registerWidget: function(container, widget) {
2027
- if (Joosy.Module.hasAncestor(widget, Joosy.Widget)) {
2028
- widget = new widget();
2029
- }
2030
- if (Object.isFunction(widget)) {
2031
- widget = widget();
2032
- }
2033
- this.__activeWidgets || (this.__activeWidgets = []);
2034
- this.__activeWidgets.push(widget.__load(this, $(container)));
2035
- return widget;
2036
- },
2037
- unregisterWidget: function(widget) {
2038
- widget.__unload();
2039
- return this.__activeWidgets.splice(this.__activeWidgets.indexOf(widget), 1);
2040
- },
2041
- __collectWidgets: function() {
2042
- var klass, widgets;
2043
- widgets = Object.extended(this.widgets || {});
2044
- klass = this;
2045
- while (klass = klass.constructor.__super__) {
2046
- Joosy.Module.merge(widgets, klass.widgets, false);
2047
- }
2048
- return widgets;
2049
- },
2050
- __setupWidgets: function() {
2051
- var registered, widgets,
2052
- _this = this;
2053
- widgets = this.__collectWidgets();
2054
- registered = Object.extended();
2055
- widgets.each(function(selector, widget) {
2056
- var activeSelector, r;
2057
- if (selector === '$container') {
2058
- activeSelector = _this.container;
2059
- } else {
2060
- if (r = selector.match(/\$([A-z_]+)/)) {
2061
- selector = _this.elements[r[1]];
2062
- }
2063
- activeSelector = $(selector, _this.container);
2064
- }
2065
- registered[selector] = Object.extended();
2066
- return activeSelector.each(function(index, elem) {
2067
- var instance, _base, _name;
2068
- if (Joosy.Module.hasAncestor(widget, Joosy.Widget)) {
2069
- instance = new widget;
2070
- } else {
2071
- instance = widget.call(_this, index);
2072
- }
2073
- (_base = registered[selector])[_name = Joosy.Module.__className(instance)] || (_base[_name] = 0);
2074
- registered[selector][Joosy.Module.__className(instance)] += 1;
2075
- return _this.registerWidget($(elem), instance);
2076
- });
2077
- });
2078
- return registered.each(function(selector, value) {
2079
- return value.each(function(widget, count) {
2080
- return Joosy.Modules.Log.debugAs(_this, "Widget " + widget + " registered at '" + selector + "'. Elements: " + count);
2081
- });
2082
- });
2083
- },
2084
- __unloadWidgets: function() {
2085
- var widget, _i, _len, _ref, _results;
2086
- if (this.__activeWidgets) {
2087
- _ref = this.__activeWidgets;
2088
- _results = [];
2089
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2090
- widget = _ref[_i];
2091
- _results.push(widget.__unload());
789
+ findChildById = function(element, id) {
790
+ var found, idx, len, node;
791
+ if (element.getAttribute("id") === id) {
792
+ return element;
2092
793
  }
2093
- return _results;
2094
- }
2095
- }
2096
- };
2097
-
2098
-
2099
- /*** src/joosy/core/modules/filters ***/
2100
-
2101
- var _this = this,
2102
- __slice = [].slice;
2103
-
2104
- Joosy.Modules.Filters = {
2105
- included: function() {
2106
- var _this = this;
2107
- return ['beforeLoad', 'afterLoad', 'afterUnload'].each(function(filter) {
2108
- return _this[filter] = function(callback) {
2109
- if (!this.prototype.hasOwnProperty("__" + filter + "s")) {
2110
- this.prototype["__" + filter + "s"] = [].concat(this.__super__["__" + filter + "s"] || []);
794
+ len = element.childNodes.length;
795
+ idx = void 0;
796
+ node = void 0;
797
+ found = void 0;
798
+ idx = 0;
799
+ while (idx < len) {
800
+ node = element.childNodes[idx];
801
+ found = node.nodeType === 1 && findChildById(node, id);
802
+ if (found) {
803
+ return found;
2111
804
  }
2112
- return this.prototype["__" + filter + "s"].push(callback);
2113
- };
2114
- });
2115
- }
2116
- };
2117
-
2118
- ['beforeLoad', 'afterLoad', 'afterUnload'].each(function(filter) {
2119
- return Joosy.Modules.Filters["__run" + (filter.camelize(true)) + "s"] = function() {
2120
- var opts,
2121
- _this = this;
2122
- opts = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2123
- if (!this["__" + filter + "s"]) {
2124
- return true;
2125
- }
2126
- return this["__" + filter + "s"].reduce(function(flag, func) {
2127
- if (!Object.isFunction(func)) {
2128
- func = _this[func];
805
+ idx++;
2129
806
  }
2130
- return flag && func.apply(_this, opts) !== false;
2131
- }, true);
2132
- };
2133
- });
2134
-
2135
-
2136
- /*** src/joosy/core/layout ***/
2137
-
2138
- var __hasProp = {}.hasOwnProperty,
2139
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
2140
- __slice = [].slice;
2141
-
2142
- Joosy.Layout = (function(_super) {
2143
- __extends(Layout, _super);
2144
-
2145
- Layout.include(Joosy.Modules.Log);
2146
-
2147
- Layout.include(Joosy.Modules.Events);
2148
-
2149
- Layout.include(Joosy.Modules.Container);
2150
-
2151
- Layout.include(Joosy.Modules.Renderer);
2152
-
2153
- Layout.include(Joosy.Modules.TimeManager);
2154
-
2155
- Layout.include(Joosy.Modules.WidgetsManager);
2156
-
2157
- Layout.include(Joosy.Modules.Filters);
2158
-
2159
- Layout.view('default');
2160
-
2161
- Layout.beforePaint = function(callback) {
2162
- return this.prototype.__beforePaint = callback;
2163
- };
2164
-
2165
- Layout.paint = function(callback) {
2166
- return this.prototype.__paint = callback;
2167
- };
2168
-
2169
- Layout.erase = function(callback) {
2170
- return this.prototype.__erase = callback;
2171
- };
2172
-
2173
- Layout.fetch = function(callback) {
2174
- return this.prototype.__fetch = function(complete) {
2175
- var _this = this;
2176
- this.data = {};
2177
- return callback.call(this, function() {
2178
- _this.dataFetched = true;
2179
- return complete();
2180
- });
2181
- };
2182
- };
2183
-
2184
- Layout.prototype.data = false;
2185
-
2186
- Layout.prototype.dataFetched = false;
2187
-
2188
- function Layout(params) {
2189
- this.params = params;
2190
- }
2191
-
2192
- Layout.prototype.navigate = function() {
2193
- var args, _ref;
2194
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2195
- return (_ref = Joosy.Router).navigate.apply(_ref, args);
2196
- };
2197
-
2198
- Layout.prototype.__renderSection = function() {
2199
- return 'layouts';
2200
- };
2201
-
2202
- Layout.prototype.__load = function(container) {
2203
- this.container = container;
2204
- this.refreshElements();
2205
- this.__delegateEvents();
2206
- this.__setupWidgets();
2207
- return this.__runAfterLoads();
2208
- };
2209
-
2210
- Layout.prototype.__unload = function() {
2211
- this.__clearTime();
2212
- this.__unloadWidgets();
2213
- this.__removeMetamorphs();
2214
- return this.__runAfterUnloads();
2215
- };
2216
-
2217
- Layout.prototype["yield"] = function() {
2218
- return this.uuid = Joosy.uuid();
2219
- };
2220
-
2221
- Layout.prototype.content = function() {
2222
- return $("#" + this.uuid);
2223
- };
2224
-
2225
- return Layout;
2226
-
2227
- })(Joosy.Module);
2228
-
2229
-
2230
- /*** src/joosy/core/page ***/
2231
-
2232
- var __hasProp = {}.hasOwnProperty,
2233
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
2234
- __slice = [].slice;
2235
-
2236
- Joosy.Page = (function(_super) {
2237
- __extends(Page, _super);
2238
-
2239
- Page.include(Joosy.Modules.Log);
2240
-
2241
- Page.include(Joosy.Modules.Events);
2242
-
2243
- Page.include(Joosy.Modules.Container);
2244
-
2245
- Page.include(Joosy.Modules.Renderer);
2246
-
2247
- Page.include(Joosy.Modules.TimeManager);
2248
-
2249
- Page.include(Joosy.Modules.WidgetsManager);
2250
-
2251
- Page.include(Joosy.Modules.Filters);
2252
-
2253
- Page.prototype.halted = false;
2254
-
2255
- Page.prototype.layout = false;
2256
-
2257
- Page.prototype.previous = false;
2258
-
2259
- Page.prototype.params = false;
2260
-
2261
- Page.prototype.data = false;
2262
-
2263
- Page.prototype.dataFetched = false;
2264
-
2265
- Page.layout = function(layoutClass) {
2266
- return this.prototype.__layoutClass = layoutClass;
2267
- };
2268
-
2269
- Page.beforePaint = function(callback) {
2270
- return this.prototype.__beforePaint = callback;
2271
- };
2272
-
2273
- Page.paint = function(callback) {
2274
- return this.prototype.__paint = callback;
2275
- };
2276
-
2277
- Page.afterPaint = function(callback) {
2278
- return this.prototype.__afterPaint = callback;
2279
- };
2280
-
2281
- Page.erase = function(callback) {
2282
- return this.prototype.__erase = callback;
2283
- };
2284
-
2285
- Page.fetch = function(callback) {
2286
- return this.prototype.__fetch = function(complete) {
2287
- var _this = this;
2288
- this.data = {};
2289
- return callback.call(this, function() {
2290
- _this.dataFetched = true;
2291
- return complete();
2292
- });
2293
807
  };
2294
- };
2295
-
2296
- Page.fetchSynchronized = function(callback) {
2297
- return this.prototype.__fetch = function(complete) {
2298
- return this.synchronize(function(context) {
2299
- context.after(function() {
2300
- return complete();
808
+ setInnerHTML = function(element, html) {
809
+ var idx, len, matches, node, script, _results;
810
+ matches = [];
811
+ if (movesWhitespace) {
812
+ html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
813
+ matches.push([id, spaces]);
814
+ return tag;
2301
815
  });
2302
- return callback.call(this, context);
2303
- });
816
+ }
817
+ element.innerHTML = html;
818
+ if (matches.length > 0) {
819
+ len = matches.length;
820
+ idx = void 0;
821
+ idx = 0;
822
+ _results = [];
823
+ while (idx < len) {
824
+ script = findChildById(element, matches[idx][0]);
825
+ node = document.createTextNode(matches[idx][1]);
826
+ script.parentNode.insertBefore(node, script);
827
+ _results.push(idx++);
828
+ }
829
+ return _results;
830
+ }
2304
831
  };
2305
- };
2306
-
2307
- Page.scroll = function(element, options) {
2308
- if (options == null) {
2309
- options = {};
2310
- }
2311
- this.prototype.__scrollElement = element;
2312
- this.prototype.__scrollSpeed = options.speed || 500;
2313
- return this.prototype.__scrollMargin = options.margin || 0;
2314
- };
832
+ /*
833
+ Given a parent node and some HTML, generate a set of nodes. Return the first
834
+ node, which will allow us to traverse the rest using nextSibling.
835
+
836
+ We need to do this because innerHTML in IE does not really parse the nodes.
837
+ */
2315
838
 
2316
- Page.prototype.__performScrolling = function() {
2317
- var scroll, _ref,
2318
- _this = this;
2319
- scroll = ((_ref = $(this.__extractSelector(this.__scrollElement)).offset()) != null ? _ref.top : void 0) + this.__scrollMargin;
2320
- Joosy.Modules.Log.debugAs(this, "Scrolling to " + (this.__extractSelector(this.__scrollElement)));
2321
- return $('html, body').animate({
2322
- scrollTop: scroll
2323
- }, this.__scrollSpeed, function() {
2324
- if (_this.__scrollSpeed !== 0) {
2325
- return _this.__releaseHeight();
839
+ firstNodeFor = function(parentNode, html) {
840
+ var arr, depth, element, end, i, shyElement, start;
841
+ arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
842
+ depth = arr[0];
843
+ start = arr[1];
844
+ end = arr[2];
845
+ if (needsShy) {
846
+ html = "&shy;" + html;
2326
847
  }
2327
- });
2328
- };
848
+ element = document.createElement("div");
849
+ setInnerHTML(element, start + html + end);
850
+ i = 0;
851
+ while (i <= depth) {
852
+ element = element.firstChild;
853
+ i++;
854
+ }
855
+ if (needsShy) {
856
+ shyElement = element;
857
+ while (shyElement.nodeType === 1 && !shyElement.nodeName) {
858
+ shyElement = shyElement.firstChild;
859
+ }
860
+ if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "­") {
861
+ shyElement.nodeValue = shyElement.nodeValue.slice(1);
862
+ }
863
+ }
864
+ return element;
865
+ };
866
+ /*
867
+ In some cases, Internet Explorer can create an anonymous node in
868
+ the hierarchy with no tagName. You can create this scenario via:
869
+
870
+ div = document.createElement("div");
871
+ div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
872
+ div.firstChild.firstChild.tagName //=> ""
873
+
874
+ If our script markers are inside such a node, we need to find that
875
+ node and use *it* as the marker.
876
+ */
2329
877
 
2330
- Page.title = function(title, separator) {
2331
- if (separator == null) {
2332
- separator = ' / ';
2333
- }
2334
- this.afterLoad(function() {
2335
- var titleStr;
2336
- titleStr = Object.isFunction(title) ? title.apply(this) : title;
2337
- if (Object.isArray(titleStr)) {
2338
- titleStr = titleStr.join(separator);
878
+ realNode = function(start) {
879
+ while (start.parentNode.tagName === "") {
880
+ start = start.parentNode;
2339
881
  }
2340
- this.__previousTitle = document.title;
2341
- return document.title = titleStr;
2342
- });
2343
- return this.afterUnload(function() {
2344
- return document.title = this.__previousTitle;
2345
- });
2346
- };
882
+ return start;
883
+ };
884
+ /*
885
+ When automatically adding a tbody, Internet Explorer inserts the
886
+ tbody immediately before the first <tr>. Other browsers create it
887
+ before the first node, no matter what.
888
+
889
+ This means the the following code:
890
+
891
+ div = document.createElement("div");
892
+ div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
893
+
894
+ Generates the following DOM in IE:
895
+
896
+ + div
897
+ + table
898
+ - script id='first'
899
+ + tbody
900
+ + tr
901
+ + td
902
+ - "hi"
903
+ - script id='last'
904
+
905
+ Which means that the two script tags, even though they were
906
+ inserted at the same point in the hierarchy in the original
907
+ HTML, now have different parents.
908
+
909
+ This code reparents the first script tag by making it the tbody's
910
+ first child.
911
+ */
2347
912
 
2348
- function Page(params, previous) {
2349
- var _ref, _ref1, _ref2;
2350
- this.params = params;
2351
- this.previous = previous;
2352
- this.__layoutClass || (this.__layoutClass = ApplicationLayout);
2353
- if (!(this.halted = !this.__runBeforeLoads(this.params, this.previous))) {
2354
- Joosy.Application.loading = true;
2355
- 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) {
2356
- this.__bootstrapLayout();
2357
- } else {
2358
- this.__bootstrap();
913
+ fixParentage = function(start, end) {
914
+ if (start.parentNode !== end.parentNode) {
915
+ return end.parentNode.insertBefore(start, end.parentNode.firstChild);
2359
916
  }
2360
- }
917
+ };
918
+ htmlFunc = function(html, outerToo) {
919
+ var end, last, nextSibling, node, parentNode, start, _results;
920
+ start = realNode(document.getElementById(this.start));
921
+ end = document.getElementById(this.end);
922
+ parentNode = end.parentNode;
923
+ node = void 0;
924
+ nextSibling = void 0;
925
+ last = void 0;
926
+ fixParentage(start, end);
927
+ node = start.nextSibling;
928
+ while (node) {
929
+ nextSibling = node.nextSibling;
930
+ last = node === end;
931
+ if (last) {
932
+ if (outerToo) {
933
+ end = node.nextSibling;
934
+ } else {
935
+ break;
936
+ }
937
+ }
938
+ node.parentNode.removeChild(node);
939
+ if (last) {
940
+ break;
941
+ }
942
+ node = nextSibling;
943
+ }
944
+ node = firstNodeFor(start.parentNode, html);
945
+ _results = [];
946
+ while (node) {
947
+ nextSibling = node.nextSibling;
948
+ parentNode.insertBefore(node, end);
949
+ _results.push(node = nextSibling);
950
+ }
951
+ return _results;
952
+ };
953
+ removeFunc = function() {
954
+ var end, start;
955
+ start = realNode(document.getElementById(this.start));
956
+ end = document.getElementById(this.end);
957
+ this.html("");
958
+ start.parentNode.removeChild(start);
959
+ return end.parentNode.removeChild(end);
960
+ };
961
+ appendToFunc = function(parentNode) {
962
+ var nextSibling, node, _results;
963
+ node = firstNodeFor(parentNode, this.outerHTML());
964
+ nextSibling = void 0;
965
+ _results = [];
966
+ while (node) {
967
+ nextSibling = node.nextSibling;
968
+ parentNode.appendChild(node);
969
+ _results.push(node = nextSibling);
970
+ }
971
+ return _results;
972
+ };
973
+ afterFunc = function(html) {
974
+ var end, insertBefore, nextSibling, node, parentNode, _results;
975
+ end = document.getElementById(this.end);
976
+ insertBefore = end.nextSibling;
977
+ parentNode = end.parentNode;
978
+ nextSibling = void 0;
979
+ node = void 0;
980
+ node = firstNodeFor(parentNode, html);
981
+ _results = [];
982
+ while (node) {
983
+ nextSibling = node.nextSibling;
984
+ parentNode.insertBefore(node, insertBefore);
985
+ _results.push(node = nextSibling);
986
+ }
987
+ return _results;
988
+ };
989
+ prependFunc = function(html) {
990
+ var insertBefore, nextSibling, node, parentNode, start, _results;
991
+ start = document.getElementById(this.start);
992
+ parentNode = start.parentNode;
993
+ nextSibling = void 0;
994
+ node = void 0;
995
+ node = firstNodeFor(parentNode, html);
996
+ insertBefore = start.nextSibling;
997
+ _results = [];
998
+ while (node) {
999
+ nextSibling = node.nextSibling;
1000
+ parentNode.insertBefore(node, insertBefore);
1001
+ _results.push(node = nextSibling);
1002
+ }
1003
+ return _results;
1004
+ };
2361
1005
  }
2362
-
2363
- Page.prototype.navigate = function() {
2364
- var args, _ref;
2365
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2366
- return (_ref = Joosy.Router).navigate.apply(_ref, args);
2367
- };
2368
-
2369
- Page.prototype.__renderSection = function() {
2370
- return 'pages';
1006
+ Metamorph.prototype.html = function(html) {
1007
+ this.checkRemoved();
1008
+ if (html === undefined) {
1009
+ return this.innerHTML;
1010
+ }
1011
+ htmlFunc.call(this, html);
1012
+ return this.innerHTML = html;
2371
1013
  };
2372
-
2373
- Page.prototype.__fixHeight = function() {
2374
- return $('html').css('min-height', $(document).height());
1014
+ Metamorph.prototype.replaceWith = function(html) {
1015
+ this.checkRemoved();
1016
+ return htmlFunc.call(this, html, true);
2375
1017
  };
2376
-
2377
- Page.prototype.__releaseHeight = function() {
2378
- return $('html').css('min-height', '');
1018
+ Metamorph.prototype.remove = removeFunc;
1019
+ Metamorph.prototype.outerHTML = outerHTMLFunc;
1020
+ Metamorph.prototype.appendTo = appendToFunc;
1021
+ Metamorph.prototype.after = afterFunc;
1022
+ Metamorph.prototype.prepend = prependFunc;
1023
+ Metamorph.prototype.startTag = startTagFunc;
1024
+ Metamorph.prototype.endTag = endTagFunc;
1025
+ Metamorph.prototype.isRemoved = function() {
1026
+ var after, before;
1027
+ before = document.getElementById(this.start);
1028
+ after = document.getElementById(this.end);
1029
+ return !before || !after;
2379
1030
  };
2380
-
2381
- Page.prototype.__load = function() {
2382
- this.refreshElements();
2383
- this.__delegateEvents();
2384
- this.__setupWidgets();
2385
- this.__runAfterLoads(this.params, this.previous);
2386
- if (this.__scrollElement) {
2387
- this.__performScrolling();
1031
+ Metamorph.prototype.checkRemoved = function() {
1032
+ if (this.isRemoved()) {
1033
+ throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
2388
1034
  }
2389
- Joosy.Application.loading = false;
2390
- Joosy.Router.trigger('loaded', this);
2391
- this.trigger('loaded');
2392
- return Joosy.Modules.Log.debugAs(this, "Page loaded");
2393
1035
  };
1036
+ return window.Metamorph = Metamorph;
1037
+ })(this);
2394
1038
 
2395
- Page.prototype.__unload = function() {
2396
- this.__clearTime();
2397
- this.__unloadWidgets();
2398
- this.__removeMetamorphs();
2399
- this.__runAfterUnloads(this.params, this.previous);
2400
- return delete this.previous;
2401
- };
2402
1039
 
2403
- Page.prototype.__callSyncedThrough = function(entity, receiver, params, callback) {
2404
- if ((entity != null ? entity[receiver] : void 0) != null) {
2405
- return entity[receiver].apply(entity, params.clone().add(callback));
1040
+ /*** src/joosy/core/modules/renderer ***/
1041
+
1042
+ var __slice = [].slice;
1043
+
1044
+ Joosy.Modules.Renderer = {
1045
+ __renderer: function() {
1046
+ throw new Error("" + (Joosy.Module.__className(this.constructor)) + " does not have an attached template");
1047
+ },
1048
+ __helpers: null,
1049
+ included: function() {
1050
+ this.view = function(template, options) {
1051
+ if (options == null) {
1052
+ options = {};
1053
+ }
1054
+ if (Object.isFunction(template)) {
1055
+ return this.prototype.__renderer = template;
1056
+ } else {
1057
+ return this.prototype.__renderer = function(locals) {
1058
+ if (locals == null) {
1059
+ locals = {};
1060
+ }
1061
+ if (options.dynamic) {
1062
+ return this.renderDynamic(template, locals);
1063
+ } else {
1064
+ return this.render(template, locals);
1065
+ }
1066
+ };
1067
+ }
1068
+ };
1069
+ return this.helpers = function() {
1070
+ var helpers, _base,
1071
+ _this = this;
1072
+ helpers = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1073
+ (_base = this.prototype).__helpers || (_base.__helpers = []);
1074
+ helpers.map(function(helper) {
1075
+ var module;
1076
+ module = Joosy.Helpers[helper];
1077
+ if (!module) {
1078
+ throw new Error("Cannot find helper module " + helper);
1079
+ }
1080
+ return _this.prototype.__helpers.push(module);
1081
+ });
1082
+ return this.prototype.__helpers = this.prototype.__helpers.unique();
1083
+ };
1084
+ },
1085
+ __instantiateHelpers: function() {
1086
+ var helper, _i, _len, _ref,
1087
+ _this = this;
1088
+ if (!this.__helpersInstance) {
1089
+ this.__helpersInstance = Object.extended(Joosy.Helpers.Application);
1090
+ if (this.onRefresh) {
1091
+ this.__helpersInstance.onRefresh = function(callback) {
1092
+ return _this.onRefresh(callback);
1093
+ };
1094
+ }
1095
+ if (this.__helpers) {
1096
+ _ref = this.__helpers;
1097
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1098
+ helper = _ref[_i];
1099
+ Joosy.Module.merge(this.__helpersInstance, helper);
1100
+ }
1101
+ }
1102
+ }
1103
+ return this.__helpersInstance;
1104
+ },
1105
+ __proxifyHelpers: function(locals) {
1106
+ if (locals.hasOwnProperty('__proto__')) {
1107
+ locals.__proto__ = this.__instantiateHelpers();
1108
+ return locals;
2406
1109
  } else {
2407
- return callback();
1110
+ if (!this.__helpersProxyInstance) {
1111
+ this.__helpersProxyInstance = function(locals) {
1112
+ return Joosy.Module.merge(this, locals);
1113
+ };
1114
+ this.__helpersProxyInstance.prototype = this.__instantiateHelpers();
1115
+ }
1116
+ return new this.__helpersProxyInstance(locals);
2408
1117
  }
2409
- };
2410
-
2411
- Page.prototype.__bootstrap = function() {
2412
- var callbacksParams,
1118
+ },
1119
+ render: function(template, locals, parentStackPointer) {
1120
+ if (locals == null) {
1121
+ locals = {};
1122
+ }
1123
+ if (parentStackPointer == null) {
1124
+ parentStackPointer = false;
1125
+ }
1126
+ return this.__render(false, template, locals, parentStackPointer);
1127
+ },
1128
+ renderDynamic: function(template, locals, parentStackPointer) {
1129
+ if (locals == null) {
1130
+ locals = {};
1131
+ }
1132
+ if (parentStackPointer == null) {
1133
+ parentStackPointer = false;
1134
+ }
1135
+ return this.__render(true, template, locals, parentStackPointer);
1136
+ },
1137
+ __render: function(dynamic, template, locals, parentStackPointer) {
1138
+ var assignContext, binding, context, key, morph, object, renderers, result, stack, update,
2413
1139
  _this = this;
2414
- Joosy.Modules.Log.debugAs(this, "Boostraping page");
2415
- this.layout = this.previous.layout;
2416
- callbacksParams = [this.layout.content()];
2417
- if (this.__scrollElement && this.__scrollSpeed !== 0) {
2418
- this.__fixHeight();
1140
+ if (locals == null) {
1141
+ locals = {};
2419
1142
  }
2420
- this.wait("stageClear dataReceived", function() {
2421
- var _ref;
2422
- if ((_ref = _this.previous) != null) {
2423
- if (typeof _ref.__afterPaint === "function") {
2424
- _ref.__afterPaint(callbacksParams);
1143
+ if (parentStackPointer == null) {
1144
+ parentStackPointer = false;
1145
+ }
1146
+ stack = this.__renderingStackChildFor(parentStackPointer);
1147
+ stack.template = template;
1148
+ stack.locals = locals;
1149
+ assignContext = false;
1150
+ if (Object.isString(template)) {
1151
+ if (this.__renderSection != null) {
1152
+ template = Joosy.Application.templater.resolveTemplate(this.__renderSection(), template, this);
1153
+ }
1154
+ template = Joosy.Application.templater.buildView(template);
1155
+ } else if (Object.isFunction(template)) {
1156
+ assignContext = true;
1157
+ } else if (!Object.isFunction(template)) {
1158
+ throw new Error("" + (Joosy.Module.__className(this)) + "> template (maybe @view) does not look like a string or lambda");
1159
+ }
1160
+ if (!Object.isObject(locals) && Object.extended().constructor !== locals.constructor) {
1161
+ throw new Error("" + (Joosy.Module.__className(this)) + "> locals (maybe @data?) is not a hash");
1162
+ }
1163
+ renderers = {
1164
+ render: function(template, locals) {
1165
+ if (locals == null) {
1166
+ locals = {};
1167
+ }
1168
+ return _this.render(template, locals, stack);
1169
+ },
1170
+ renderDynamic: function(template, locals) {
1171
+ if (locals == null) {
1172
+ locals = {};
2425
1173
  }
1174
+ return _this.renderDynamic(template, locals, stack);
1175
+ },
1176
+ renderInline: function(locals, template) {
1177
+ if (locals == null) {
1178
+ locals = {};
1179
+ }
1180
+ return _this.renderDynamic(template, locals, stack);
2426
1181
  }
2427
- return _this.__callSyncedThrough(_this, '__paint', callbacksParams, function() {
2428
- _this.swapContainer(_this.layout.content(), _this.__renderer(_this.data || {}));
2429
- _this.container = _this.layout.content();
2430
- _this.__load();
2431
- return _this.layout.content();
2432
- });
2433
- });
2434
- this.__callSyncedThrough(this.previous, '__erase', callbacksParams, function() {
2435
- var _ref;
2436
- if ((_ref = _this.previous) != null) {
2437
- _ref.__unload();
1182
+ };
1183
+ context = function() {
1184
+ var data;
1185
+ data = {};
1186
+ Joosy.Module.merge(data, stack.locals);
1187
+ Joosy.Module.merge(data, _this.__instantiateHelpers(), false);
1188
+ Joosy.Module.merge(data, renderers);
1189
+ return data;
1190
+ };
1191
+ result = function() {
1192
+ if (assignContext) {
1193
+ return template.call(context());
1194
+ } else {
1195
+ return template(context());
2438
1196
  }
2439
- return _this.__callSyncedThrough(_this, '__beforePaint', callbacksParams, function() {
2440
- return _this.trigger('stageClear');
2441
- });
2442
- });
2443
- return this.__callSyncedThrough(this, '__fetch', [], function() {
2444
- Joosy.Modules.Log.debugAs(_this, "Fetch complete");
2445
- return _this.trigger('dataReceived');
2446
- });
2447
- };
2448
-
2449
- Page.prototype.__bootstrapLayout = function() {
2450
- var callbacksParams, _ref,
1197
+ };
1198
+ if (dynamic) {
1199
+ morph = Metamorph(result());
1200
+ update = function() {
1201
+ var callback, child, object, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;
1202
+ if (morph.isRemoved()) {
1203
+ _ref = morph.__bindings;
1204
+ _results = [];
1205
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1206
+ _ref1 = _ref[_i], object = _ref1[0], callback = _ref1[1];
1207
+ _results.push(object.unbind(callback));
1208
+ }
1209
+ return _results;
1210
+ } else {
1211
+ _ref2 = stack.children;
1212
+ for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
1213
+ child = _ref2[_j];
1214
+ _this.__removeMetamorphs(child);
1215
+ }
1216
+ stack.children = [];
1217
+ morph.html(result());
1218
+ return typeof _this.refreshElements === "function" ? _this.refreshElements() : void 0;
1219
+ }
1220
+ };
1221
+ update = update.debounce(0);
1222
+ morph.__bindings = [];
1223
+ for (key in locals) {
1224
+ object = locals[key];
1225
+ if (locals.hasOwnProperty(key)) {
1226
+ if (((object != null ? object.bind : void 0) != null) && ((object != null ? object.unbind : void 0) != null)) {
1227
+ binding = [object, update];
1228
+ object.bind('changed', update);
1229
+ stack.metamorphBindings.push(binding);
1230
+ morph.__bindings.push(binding);
1231
+ }
1232
+ }
1233
+ }
1234
+ return morph.outerHTML();
1235
+ } else {
1236
+ return result();
1237
+ }
1238
+ },
1239
+ __renderingStackElement: function(parent) {
1240
+ if (parent == null) {
1241
+ parent = null;
1242
+ }
1243
+ return {
1244
+ metamorphBindings: [],
1245
+ locals: null,
1246
+ template: null,
1247
+ children: [],
1248
+ parent: parent
1249
+ };
1250
+ },
1251
+ __renderingStackChildFor: function(parentPointer) {
1252
+ var element;
1253
+ if (!this.__renderingStack) {
1254
+ this.__renderingStack = [];
1255
+ }
1256
+ if (!parentPointer) {
1257
+ element = this.__renderingStackElement();
1258
+ this.__renderingStack.push(element);
1259
+ return element;
1260
+ } else {
1261
+ element = this.__renderingStackElement(parentPointer);
1262
+ parentPointer.children.push(element);
1263
+ return element;
1264
+ }
1265
+ },
1266
+ __removeMetamorphs: function(stackPointer) {
1267
+ var remove, _ref,
2451
1268
  _this = this;
2452
- Joosy.Modules.Log.debugAs(this, "Boostraping page with layout");
2453
- this.layout = new this.__layoutClass(this.params);
2454
- callbacksParams = [Joosy.Application.content(), this];
2455
- if (this.__scrollElement && this.__scrollSpeed !== 0) {
2456
- this.__fixHeight();
1269
+ if (stackPointer == null) {
1270
+ stackPointer = false;
2457
1271
  }
2458
- this.wait("stageClear dataReceived", function() {
2459
- return _this.__callSyncedThrough(_this.layout, '__paint', callbacksParams, function() {
2460
- var data;
2461
- data = Joosy.Module.merge({}, _this.layout.data || {});
2462
- data = Joosy.Module.merge(data, {
2463
- "yield": function() {
2464
- return _this.layout["yield"]();
2465
- }
2466
- });
2467
- _this.swapContainer(Joosy.Application.content(), _this.layout.__renderer(data));
2468
- _this.swapContainer(_this.layout.content(), _this.__renderer(_this.data || {}));
2469
- _this.container = _this.layout.content();
2470
- _this.layout.__load(Joosy.Application.content());
2471
- _this.__load();
2472
- return Joosy.Application.content();
2473
- });
2474
- });
2475
- this.__callSyncedThrough((_ref = this.previous) != null ? _ref.layout : void 0, '__erase', callbacksParams, function() {
2476
- var _ref1, _ref2, _ref3;
2477
- if ((_ref1 = _this.previous) != null) {
2478
- if ((_ref2 = _ref1.layout) != null) {
2479
- if (typeof _ref2.__unload === "function") {
2480
- _ref2.__unload();
2481
- }
1272
+ remove = function(stackPointer) {
1273
+ var callback, child, object, _i, _j, _len, _len1, _ref, _ref1, _ref2;
1274
+ if (stackPointer != null ? stackPointer.children : void 0) {
1275
+ _ref = stackPointer.children;
1276
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1277
+ child = _ref[_i];
1278
+ _this.__removeMetamorphs(child);
2482
1279
  }
2483
1280
  }
2484
- if ((_ref3 = _this.previous) != null) {
2485
- _ref3.__unload();
1281
+ if (stackPointer != null ? stackPointer.metamorphBindings : void 0) {
1282
+ _ref1 = stackPointer.metamorphBindings;
1283
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
1284
+ _ref2 = _ref1[_j], object = _ref2[0], callback = _ref2[1];
1285
+ object.unbind(callback);
1286
+ }
1287
+ return stackPointer.metamorphBindings = [];
2486
1288
  }
2487
- return _this.__callSyncedThrough(_this.layout, '__beforePaint', callbacksParams, function() {
2488
- return _this.trigger('stageClear');
2489
- });
2490
- });
2491
- return this.__callSyncedThrough(this.layout, '__fetch', [], function() {
2492
- return _this.__callSyncedThrough(_this, '__fetch', [], function() {
2493
- Joosy.Modules.Log.debugAs(_this, "Fetch complete");
2494
- return _this.trigger('dataReceived');
2495
- });
2496
- });
2497
- };
2498
-
2499
- return Page;
2500
-
2501
- })(Joosy.Module);
2502
-
2503
-
2504
- /*** src/joosy/core/preloader ***/
2505
-
2506
- this.Preloader = {
2507
- load: function(libraries, options) {
2508
- var key, val, _ref;
2509
- for (key in options) {
2510
- val = options[key];
2511
- this[key] = val;
1289
+ };
1290
+ if (!stackPointer) {
1291
+ return (_ref = this.__renderingStack) != null ? _ref.each(function(stackPointer) {
1292
+ return remove(stackPointer);
1293
+ }) : void 0;
1294
+ } else {
1295
+ return remove(stackPointer);
2512
1296
  }
2513
- return (_ref = this.complete) != null ? _ref.call(window) : void 0;
2514
1297
  }
2515
1298
  };
2516
1299
 
2517
1300
 
2518
- /*** src/joosy/core/resource/collection ***/
2519
-
2520
- var __hasProp = {}.hasOwnProperty,
2521
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
2522
- __slice = [].slice;
2523
-
2524
- Joosy.Resource.Collection = (function(_super) {
2525
- __extends(Collection, _super);
2526
-
2527
- Collection.include(Joosy.Modules.Events);
2528
-
2529
- Collection.beforeLoad = function(action) {
2530
- return this.prototype.__beforeLoad = action;
2531
- };
2532
-
2533
- Collection.model = function(model) {
2534
- return this.prototype.model = model;
2535
- };
1301
+ /*** src/joosy/core/modules/time_manager ***/
2536
1302
 
2537
- function Collection(model, findOptions) {
2538
- if (model == null) {
2539
- model = false;
2540
- }
2541
- this.findOptions = findOptions;
2542
- if (model) {
2543
- this.model = model;
1303
+ Joosy.Modules.TimeManager = {
1304
+ setTimeout: function(timeout, action) {
1305
+ var timer,
1306
+ _this = this;
1307
+ this.__timeouts || (this.__timeouts = []);
1308
+ timer = window.setTimeout((function() {
1309
+ return action();
1310
+ }), timeout);
1311
+ this.__timeouts.push(timer);
1312
+ return timer;
1313
+ },
1314
+ setInterval: function(delay, action) {
1315
+ var timer,
1316
+ _this = this;
1317
+ this.__intervals || (this.__intervals = []);
1318
+ timer = window.setInterval((function() {
1319
+ return action();
1320
+ }), delay);
1321
+ this.__intervals.push(timer);
1322
+ return timer;
1323
+ },
1324
+ __clearTime: function() {
1325
+ var entry, _i, _j, _len, _len1, _ref, _ref1, _results;
1326
+ if (this.__intervals) {
1327
+ _ref = this.__intervals;
1328
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1329
+ entry = _ref[_i];
1330
+ window.clearInterval(entry);
1331
+ }
2544
1332
  }
2545
- this.data = [];
2546
- if (!this.model) {
2547
- throw new Error("" + (Joosy.Module.__className(this)) + "> model can't be empty");
1333
+ if (this.__timeouts) {
1334
+ _ref1 = this.__timeouts;
1335
+ _results = [];
1336
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
1337
+ entry = _ref1[_j];
1338
+ _results.push(window.clearTimeout(entry));
1339
+ }
1340
+ return _results;
2548
1341
  }
2549
1342
  }
1343
+ };
1344
+
1345
+
1346
+ /*** src/joosy/core/modules/widgets_manager ***/
2550
1347
 
2551
- Collection.prototype.load = function(entities, notify) {
2552
- if (notify == null) {
2553
- notify = true;
1348
+ Joosy.Modules.WidgetsManager = {
1349
+ registerWidget: function(container, widget) {
1350
+ if (Joosy.Module.hasAncestor(widget, Joosy.Widget)) {
1351
+ widget = new widget();
2554
1352
  }
2555
- if (this.__beforeLoad != null) {
2556
- entities = this.__beforeLoad(entities);
1353
+ if (Object.isFunction(widget)) {
1354
+ widget = widget();
2557
1355
  }
2558
- this.data = this.modelize(entities);
2559
- if (notify) {
2560
- this.trigger('changed');
1356
+ this.__activeWidgets || (this.__activeWidgets = []);
1357
+ this.__activeWidgets.push(widget.__load(this, $(container)));
1358
+ return widget;
1359
+ },
1360
+ unregisterWidget: function(widget) {
1361
+ widget.__unload();
1362
+ return this.__activeWidgets.splice(this.__activeWidgets.indexOf(widget), 1);
1363
+ },
1364
+ __collectWidgets: function() {
1365
+ var klass, widgets;
1366
+ widgets = Object.extended(this.widgets || {});
1367
+ klass = this;
1368
+ while (klass = klass.constructor.__super__) {
1369
+ Joosy.Module.merge(widgets, klass.widgets, false);
2561
1370
  }
2562
- return this;
2563
- };
2564
-
2565
- Collection.prototype.modelize = function(collection) {
2566
- var root,
1371
+ return widgets;
1372
+ },
1373
+ __setupWidgets: function() {
1374
+ var registered, widgets,
2567
1375
  _this = this;
2568
- root = this.model.prototype.__entityName.pluralize();
2569
- if (!(collection instanceof Array)) {
2570
- collection = collection != null ? collection[root.camelize(false)] : void 0;
2571
- if (!(collection instanceof Array)) {
2572
- throw new Error("Can not read incoming JSON");
1376
+ widgets = this.__collectWidgets();
1377
+ registered = Object.extended();
1378
+ widgets.each(function(selector, widget) {
1379
+ var activeSelector, r;
1380
+ if (selector === '$container') {
1381
+ activeSelector = _this.container;
1382
+ } else {
1383
+ if (r = selector.match(/\$([A-z_]+)/)) {
1384
+ selector = _this.elements[r[1]];
1385
+ }
1386
+ activeSelector = $(selector, _this.container);
2573
1387
  }
2574
- }
2575
- return collection.map(function(x) {
2576
- return _this.model.build(x);
1388
+ registered[selector] = Object.extended();
1389
+ return activeSelector.each(function(index, elem) {
1390
+ var instance, _base, _name;
1391
+ if (Joosy.Module.hasAncestor(widget, Joosy.Widget)) {
1392
+ instance = new widget;
1393
+ } else {
1394
+ instance = widget.call(_this, index);
1395
+ }
1396
+ (_base = registered[selector])[_name = Joosy.Module.__className(instance)] || (_base[_name] = 0);
1397
+ registered[selector][Joosy.Module.__className(instance)] += 1;
1398
+ return _this.registerWidget($(elem), instance);
1399
+ });
2577
1400
  });
2578
- };
2579
-
2580
- Collection.prototype.each = function(callback) {
2581
- return this.data.each(callback);
2582
- };
1401
+ return registered.each(function(selector, value) {
1402
+ return value.each(function(widget, count) {
1403
+ return Joosy.Modules.Log.debugAs(_this, "Widget " + widget + " registered at '" + selector + "'. Elements: " + count);
1404
+ });
1405
+ });
1406
+ },
1407
+ __unloadWidgets: function() {
1408
+ var widget, _i, _len, _ref, _results;
1409
+ if (this.__activeWidgets) {
1410
+ _ref = this.__activeWidgets;
1411
+ _results = [];
1412
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1413
+ widget = _ref[_i];
1414
+ _results.push(widget.__unload());
1415
+ }
1416
+ return _results;
1417
+ }
1418
+ }
1419
+ };
2583
1420
 
2584
- Collection.prototype.size = function() {
2585
- return this.data.length;
2586
- };
2587
1421
 
2588
- Collection.prototype.find = function(description) {
2589
- return this.data.find(description);
2590
- };
1422
+ /*** src/joosy/core/modules/filters ***/
2591
1423
 
2592
- Collection.prototype.sortBy = function() {
2593
- var params, _ref;
2594
- params = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2595
- return (_ref = this.data).sortBy.apply(_ref, params);
2596
- };
1424
+ var _this = this,
1425
+ __slice = [].slice;
2597
1426
 
2598
- Collection.prototype.findById = function(id) {
2599
- return this.data.find(function(x) {
2600
- return x.id().toString() === id.toString();
1427
+ Joosy.Modules.Filters = {
1428
+ included: function() {
1429
+ var _this = this;
1430
+ return ['beforeLoad', 'afterLoad', 'afterUnload'].each(function(filter) {
1431
+ return _this[filter] = function(callback) {
1432
+ if (!this.prototype.hasOwnProperty("__" + filter + "s")) {
1433
+ this.prototype["__" + filter + "s"] = [].concat(this.__super__["__" + filter + "s"] || []);
1434
+ }
1435
+ return this.prototype["__" + filter + "s"].push(callback);
1436
+ };
2601
1437
  });
2602
- };
2603
-
2604
- Collection.prototype.at = function(i) {
2605
- return this.data[i];
2606
- };
2607
-
2608
- Collection.prototype.remove = function(target, notify) {
2609
- var index, result;
2610
- if (notify == null) {
2611
- notify = true;
2612
- }
2613
- if (Object.isNumber(target)) {
2614
- index = target;
2615
- } else {
2616
- index = this.data.indexOf(target);
2617
- }
2618
- if (index >= 0) {
2619
- result = this.data.splice(index, 1)[0];
2620
- if (notify) {
2621
- this.trigger('changed');
2622
- }
2623
- }
2624
- return result;
2625
- };
1438
+ }
1439
+ };
2626
1440
 
2627
- Collection.prototype.add = function(element, index, notify) {
2628
- if (index == null) {
2629
- index = false;
2630
- }
2631
- if (notify == null) {
2632
- notify = true;
2633
- }
2634
- if (typeof index === 'number') {
2635
- this.data.splice(index, 0, element);
2636
- } else {
2637
- this.data.push(element);
2638
- }
2639
- if (notify) {
2640
- this.trigger('changed');
1441
+ ['beforeLoad', 'afterLoad', 'afterUnload'].each(function(filter) {
1442
+ return Joosy.Modules.Filters["__run" + (filter.camelize(true)) + "s"] = function() {
1443
+ var opts,
1444
+ _this = this;
1445
+ opts = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1446
+ if (!this["__" + filter + "s"]) {
1447
+ return true;
2641
1448
  }
2642
- return element;
1449
+ return this["__" + filter + "s"].reduce(function(flag, func) {
1450
+ if (!Object.isFunction(func)) {
1451
+ func = _this[func];
1452
+ }
1453
+ return flag && func.apply(_this, opts) !== false;
1454
+ }, true);
2643
1455
  };
1456
+ });
2644
1457
 
2645
- return Collection;
2646
1458
 
2647
- })(Joosy.Module);
1459
+ /*** src/joosy/core/layout ***/
1460
+
1461
+ var __hasProp = {}.hasOwnProperty,
1462
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
1463
+ __slice = [].slice;
1464
+
1465
+ Joosy.Layout = (function(_super) {
1466
+ __extends(Layout, _super);
2648
1467
 
1468
+ Layout.include(Joosy.Modules.Log);
2649
1469
 
2650
- /*** src/joosy/core/resource/generic ***/
1470
+ Layout.include(Joosy.Modules.Events);
2651
1471
 
2652
- var __hasProp = {}.hasOwnProperty,
2653
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
1472
+ Layout.include(Joosy.Modules.Container);
2654
1473
 
2655
- Joosy.Resource.Generic = (function(_super) {
2656
- __extends(Generic, _super);
1474
+ Layout.include(Joosy.Modules.Renderer);
2657
1475
 
2658
- Generic.include(Joosy.Modules.Log);
1476
+ Layout.include(Joosy.Modules.TimeManager);
2659
1477
 
2660
- Generic.include(Joosy.Modules.Events);
1478
+ Layout.include(Joosy.Modules.WidgetsManager);
2661
1479
 
2662
- Generic.prototype.__primaryKey = 'id';
1480
+ Layout.include(Joosy.Modules.Filters);
2663
1481
 
2664
- Generic.prototype.__source = false;
1482
+ Layout.view('default');
2665
1483
 
2666
- Generic.resetIdentity = function() {
2667
- return Joosy.Resource.Generic.identity = {};
1484
+ Layout.beforePaint = function(callback) {
1485
+ return this.prototype.__beforePaint = callback;
2668
1486
  };
2669
1487
 
2670
- Generic.beforeLoad = function(action) {
2671
- if (!this.prototype.hasOwnProperty('__beforeLoads')) {
2672
- this.prototype.__beforeLoads = [].concat(this.__super__.__beforeLoads || []);
2673
- }
2674
- return this.prototype.__beforeLoads.push(action);
1488
+ Layout.paint = function(callback) {
1489
+ return this.prototype.__paint = callback;
2675
1490
  };
2676
1491
 
2677
- Generic.primaryKey = function(primaryKey) {
2678
- return this.prototype.__primaryKey = primaryKey;
1492
+ Layout.erase = function(callback) {
1493
+ return this.prototype.__erase = callback;
2679
1494
  };
2680
1495
 
2681
- Generic.source = function(location) {
2682
- return this.__source = location;
1496
+ Layout.fetch = function(callback) {
1497
+ return this.prototype.__fetch = function(complete) {
1498
+ var _this = this;
1499
+ this.data = {};
1500
+ return callback.call(this, function() {
1501
+ _this.dataFetched = true;
1502
+ return complete();
1503
+ });
1504
+ };
2683
1505
  };
2684
1506
 
2685
- Generic.at = function(entity) {
2686
- var Clone, _ref;
2687
- Clone = (function(_super1) {
2688
- __extends(Clone, _super1);
1507
+ Layout.prototype.data = false;
2689
1508
 
2690
- function Clone() {
2691
- _ref = Clone.__super__.constructor.apply(this, arguments);
2692
- return _ref;
2693
- }
1509
+ Layout.prototype.dataFetched = false;
2694
1510
 
2695
- return Clone;
1511
+ function Layout(params) {
1512
+ this.params = params;
1513
+ }
2696
1514
 
2697
- })(this);
2698
- if (entity instanceof Joosy.Resource.Generic) {
2699
- Clone.__source = entity.memberPath();
2700
- if (this.prototype.__entityName) {
2701
- Clone.__source += '/' + this.prototype.__entityName.pluralize();
2702
- }
2703
- } else {
2704
- Clone.__source = entity;
2705
- }
2706
- return Clone;
1515
+ Layout.prototype.navigate = function() {
1516
+ var args, _ref;
1517
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1518
+ return (_ref = Joosy.Router).navigate.apply(_ref, args);
2707
1519
  };
2708
1520
 
2709
- Generic.entity = function(name) {
2710
- return this.prototype.__entityName = name;
1521
+ Layout.prototype.__renderSection = function() {
1522
+ return 'layouts';
2711
1523
  };
2712
1524
 
2713
- Generic.collection = function(klass) {
2714
- return this.prototype.__collection = function() {
2715
- return klass;
2716
- };
1525
+ Layout.prototype.__load = function(container) {
1526
+ this.container = container;
1527
+ this.refreshElements();
1528
+ this.__delegateEvents();
1529
+ this.__setupWidgets();
1530
+ return this.__runAfterLoads();
2717
1531
  };
2718
1532
 
2719
- Generic.prototype.__collection = function() {
2720
- var named;
2721
- named = this.__entityName.camelize().pluralize() + 'Collection';
2722
- if (window[named]) {
2723
- return window[named];
2724
- } else {
2725
- return Joosy.Resource.Collection;
2726
- }
1533
+ Layout.prototype.__unload = function() {
1534
+ this.__clearTime();
1535
+ this.__unloadWidgets();
1536
+ this.__removeMetamorphs();
1537
+ return this.__runAfterUnloads();
2727
1538
  };
2728
1539
 
2729
- Generic.map = function(name, klass) {
2730
- if (klass == null) {
2731
- klass = false;
2732
- }
2733
- if (!klass) {
2734
- klass = window[name.singularize().camelize()];
2735
- }
2736
- if (!klass) {
2737
- throw new Error("" + (Joosy.Module.__className(this)) + "> class can not be detected for '" + name + "' mapping");
2738
- }
2739
- return this.beforeLoad(function(data) {
2740
- if (!Joosy.Module.hasAncestor(klass, Joosy.Resource.Generic)) {
2741
- klass = klass();
2742
- }
2743
- return this.__map(data, name, klass);
2744
- });
1540
+ Layout.prototype["yield"] = function() {
1541
+ return this.uuid = Joosy.uuid();
2745
1542
  };
2746
1543
 
2747
- Generic.build = function(data) {
2748
- var id, key, klass, shim, value, _base, _base1, _ref;
2749
- if (data == null) {
2750
- data = {};
2751
- }
2752
- klass = this.prototype.__entityName;
2753
- (_base = Joosy.Resource.Generic).identity || (_base.identity = {});
2754
- (_base1 = Joosy.Resource.Generic.identity)[klass] || (_base1[klass] = {});
2755
- shim = function() {
2756
- return shim.__call.apply(shim, arguments);
2757
- };
2758
- if (shim.__proto__) {
2759
- shim.__proto__ = this.prototype;
2760
- } else {
2761
- _ref = this.prototype;
2762
- for (key in _ref) {
2763
- value = _ref[key];
2764
- shim[key] = value;
2765
- }
2766
- }
2767
- shim.constructor = this;
2768
- if (Object.isNumber(data) || Object.isString(data)) {
2769
- id = data;
2770
- data = {};
2771
- data[shim.__primaryKey] = id;
2772
- }
2773
- if (Joosy.Application.identity) {
2774
- id = data[shim.__primaryKey];
2775
- if ((id != null) && Joosy.Resource.Generic.identity[klass][id]) {
2776
- shim = Joosy.Resource.Generic.identity[klass][id];
2777
- shim.load(data);
2778
- } else {
2779
- Joosy.Resource.Generic.identity[klass][id] = shim;
2780
- this.apply(shim, [data]);
2781
- }
2782
- } else {
2783
- this.apply(shim, [data]);
2784
- }
2785
- return shim;
1544
+ Layout.prototype.content = function() {
1545
+ return $("#" + this.uuid);
2786
1546
  };
2787
1547
 
2788
- function Generic(data) {
2789
- if (data == null) {
2790
- data = {};
2791
- }
2792
- this.__fillData(data, false);
2793
- }
1548
+ return Layout;
2794
1549
 
2795
- Generic.prototype.id = function() {
2796
- return this.data[this.__primaryKey];
2797
- };
1550
+ })(Joosy.Module);
2798
1551
 
2799
- Generic.prototype.knownAttributes = function() {
2800
- return this.data.keys();
2801
- };
2802
1552
 
2803
- Generic.prototype.load = function(data) {
2804
- this.__fillData(data);
2805
- return this;
2806
- };
1553
+ /*** src/joosy/core/page ***/
2807
1554
 
2808
- Generic.prototype.__get = function(path) {
2809
- var target;
2810
- target = this.__callTarget(path);
2811
- if (target[0] instanceof Joosy.Resource.Generic) {
2812
- return target[0](target[1]);
2813
- } else {
2814
- return target[0][target[1]];
2815
- }
2816
- };
1555
+ var __hasProp = {}.hasOwnProperty,
1556
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
1557
+ __slice = [].slice;
2817
1558
 
2818
- Generic.prototype.__set = function(path, value) {
2819
- var target;
2820
- target = this.__callTarget(path);
2821
- if (target[0] instanceof Joosy.Resource.Generic) {
2822
- target[0](target[1], value);
2823
- } else {
2824
- target[0][target[1]] = value;
2825
- }
2826
- this.trigger('changed');
2827
- return null;
2828
- };
1559
+ Joosy.Page = (function(_super) {
1560
+ __extends(Page, _super);
2829
1561
 
2830
- Generic.prototype.__callTarget = function(path) {
2831
- var keyword, part, target, _i, _len;
2832
- if (path.has(/\./) && (this.data[path] == null)) {
2833
- path = path.split('.');
2834
- keyword = path.pop();
2835
- target = this.data;
2836
- for (_i = 0, _len = path.length; _i < _len; _i++) {
2837
- part = path[_i];
2838
- target[part] || (target[part] = {});
2839
- if (target instanceof Joosy.Resource.Generic) {
2840
- target = target(part);
2841
- } else {
2842
- target = target[part];
2843
- }
2844
- }
2845
- return [target, keyword];
2846
- } else {
2847
- return [this.data, path];
2848
- }
2849
- };
1562
+ Page.include(Joosy.Modules.Log);
2850
1563
 
2851
- Generic.prototype.__call = function(path, value) {
2852
- if (arguments.length > 1) {
2853
- return this.__set(path, value);
2854
- } else {
2855
- return this.__get(path);
2856
- }
2857
- };
1564
+ Page.include(Joosy.Modules.Events);
2858
1565
 
2859
- Generic.prototype.__fillData = function(data, notify) {
2860
- if (notify == null) {
2861
- notify = true;
2862
- }
2863
- this.raw = data;
2864
- if (!this.hasOwnProperty('data')) {
2865
- this.data = {};
2866
- }
2867
- Joosy.Module.merge(this.data, this.__prepareData(data));
2868
- if (notify) {
2869
- this.trigger('changed');
2870
- }
2871
- return null;
2872
- };
1566
+ Page.include(Joosy.Modules.Container);
2873
1567
 
2874
- Generic.prototype.__prepareData = function(data) {
2875
- var bl, name, _i, _len, _ref;
2876
- if (Object.isObject(data) && Object.keys(data).length === 1 && this.__entityName) {
2877
- name = this.__entityName.camelize(false);
2878
- if (data[name]) {
2879
- data = data[name];
2880
- }
2881
- }
2882
- if (this.__beforeLoads != null) {
2883
- _ref = this.__beforeLoads;
2884
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2885
- bl = _ref[_i];
2886
- data = bl.call(this, data);
2887
- }
2888
- }
2889
- return data;
2890
- };
1568
+ Page.include(Joosy.Modules.Renderer);
2891
1569
 
2892
- Generic.prototype.__map = function(data, name, klass) {
2893
- var entry;
2894
- if (Object.isArray(data[name])) {
2895
- entry = new (klass.prototype.__collection())(klass);
2896
- entry.load(data[name]);
2897
- data[name] = entry;
2898
- } else if (Object.isObject(data[name])) {
2899
- data[name] = klass.build(data[name]);
2900
- }
2901
- return data;
2902
- };
1570
+ Page.include(Joosy.Modules.TimeManager);
2903
1571
 
2904
- return Generic;
1572
+ Page.include(Joosy.Modules.WidgetsManager);
2905
1573
 
2906
- })(Joosy.Module);
1574
+ Page.include(Joosy.Modules.Filters);
1575
+
1576
+ Page.prototype.halted = false;
2907
1577
 
1578
+ Page.prototype.layout = false;
2908
1579
 
2909
- /*** src/joosy/core/resource/rest ***/
1580
+ Page.prototype.previous = false;
2910
1581
 
2911
- var _ref,
2912
- __hasProp = {}.hasOwnProperty,
2913
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
1582
+ Page.prototype.params = false;
2914
1583
 
2915
- Joosy.Resource.REST = (function(_super) {
2916
- __extends(REST, _super);
1584
+ Page.prototype.data = false;
2917
1585
 
2918
- function REST() {
2919
- _ref = REST.__super__.constructor.apply(this, arguments);
2920
- return _ref;
2921
- }
1586
+ Page.prototype.dataFetched = false;
2922
1587
 
2923
- REST.prototype.__collection = function() {
2924
- var named;
2925
- named = this.__entityName.camelize().pluralize() + 'Collection';
2926
- if (window[named]) {
2927
- return window[named];
2928
- } else {
2929
- return Joosy.Resource.RESTCollection;
2930
- }
1588
+ Page.layout = function(layoutClass) {
1589
+ return this.prototype.__layoutClass = layoutClass;
2931
1590
  };
2932
1591
 
2933
- REST.__parentsPath = function(parents) {
2934
- return parents.reduce(function(path, parent) {
2935
- return path += Joosy.Module.hasAncestor(parent.constructor, Joosy.Resource.REST) ? parent.memberPath() : parent;
2936
- }, '');
1592
+ Page.beforePaint = function(callback) {
1593
+ return this.prototype.__beforePaint = callback;
2937
1594
  };
2938
1595
 
2939
- REST.basePath = function(options) {
2940
- var path;
2941
- if (options == null) {
2942
- options = {};
2943
- }
2944
- if ((this.__source != null) && (options.parent == null)) {
2945
- path = this.__source;
2946
- } else {
2947
- path = '/';
2948
- if (this.__namespace__.length > 0) {
2949
- path += this.__namespace__.map(function(s) {
2950
- return s.toLowerCase();
2951
- }).join('/') + '/';
2952
- }
2953
- path += this.prototype.__entityName.pluralize();
2954
- }
2955
- if (options.parent != null) {
2956
- path = this.__parentsPath(Object.isArray(options.parent) ? options.parent : [options.parent]) + path;
2957
- }
2958
- return path;
1596
+ Page.paint = function(callback) {
1597
+ return this.prototype.__paint = callback;
2959
1598
  };
2960
1599
 
2961
- REST.prototype.basePath = function(options) {
2962
- if (options == null) {
2963
- options = {};
2964
- }
2965
- return this.constructor.basePath(options);
1600
+ Page.afterPaint = function(callback) {
1601
+ return this.prototype.__afterPaint = callback;
2966
1602
  };
2967
1603
 
2968
- REST.memberPath = function(id, options) {
2969
- var path;
2970
- if (options == null) {
2971
- options = {};
2972
- }
2973
- path = this.basePath(options) + ("/" + id);
2974
- if (options.from != null) {
2975
- path += "/" + options.from;
2976
- }
2977
- return path;
1604
+ Page.erase = function(callback) {
1605
+ return this.prototype.__erase = callback;
2978
1606
  };
2979
1607
 
2980
- REST.prototype.memberPath = function(options) {
2981
- if (options == null) {
2982
- options = {};
2983
- }
2984
- return this.constructor.memberPath(this.id(), options);
1608
+ Page.fetch = function(callback) {
1609
+ return this.prototype.__fetch = function(complete) {
1610
+ var _this = this;
1611
+ this.data = {};
1612
+ return callback.call(this, function() {
1613
+ _this.dataFetched = true;
1614
+ return complete();
1615
+ });
1616
+ };
1617
+ };
1618
+
1619
+ Page.fetchSynchronized = function(callback) {
1620
+ return this.prototype.__fetch = function(complete) {
1621
+ return this.synchronize(function(context) {
1622
+ context.after(function() {
1623
+ return complete();
1624
+ });
1625
+ return callback.call(this, context);
1626
+ });
1627
+ };
2985
1628
  };
2986
1629
 
2987
- REST.collectionPath = function(options) {
2988
- var path;
1630
+ Page.scroll = function(element, options) {
2989
1631
  if (options == null) {
2990
1632
  options = {};
2991
1633
  }
2992
- path = this.basePath(options);
2993
- if (options.from != null) {
2994
- path += "/" + options.from;
2995
- }
2996
- return path;
1634
+ this.prototype.__scrollElement = element;
1635
+ this.prototype.__scrollSpeed = options.speed || 500;
1636
+ return this.prototype.__scrollMargin = options.margin || 0;
2997
1637
  };
2998
1638
 
2999
- REST.prototype.collectionPath = function(options) {
3000
- if (options == null) {
3001
- options = {};
1639
+ Page.prototype.__performScrolling = function() {
1640
+ var scroll, _ref,
1641
+ _this = this;
1642
+ scroll = ((_ref = $(this.__extractSelector(this.__scrollElement)).offset()) != null ? _ref.top : void 0) + this.__scrollMargin;
1643
+ Joosy.Modules.Log.debugAs(this, "Scrolling to " + (this.__extractSelector(this.__scrollElement)));
1644
+ return $('html, body').animate({
1645
+ scrollTop: scroll
1646
+ }, this.__scrollSpeed, function() {
1647
+ if (_this.__scrollSpeed !== 0) {
1648
+ return _this.__releaseHeight();
1649
+ }
1650
+ });
1651
+ };
1652
+
1653
+ Page.title = function(title, separator) {
1654
+ if (separator == null) {
1655
+ separator = ' / ';
3002
1656
  }
3003
- return this.constructor.collectionPath(options);
1657
+ this.afterLoad(function() {
1658
+ var titleStr;
1659
+ titleStr = Object.isFunction(title) ? title.apply(this) : title;
1660
+ if (Object.isArray(titleStr)) {
1661
+ titleStr = titleStr.join(separator);
1662
+ }
1663
+ this.__previousTitle = document.title;
1664
+ return document.title = titleStr;
1665
+ });
1666
+ return this.afterUnload(function() {
1667
+ return document.title = this.__previousTitle;
1668
+ });
3004
1669
  };
3005
1670
 
3006
- REST.get = function(options, callback) {
3007
- if (Object.isFunction(options)) {
3008
- callback = options;
3009
- options = {};
1671
+ function Page(params, previous) {
1672
+ var _ref, _ref1, _ref2;
1673
+ this.params = params;
1674
+ this.previous = previous;
1675
+ this.__layoutClass || (this.__layoutClass = ApplicationLayout);
1676
+ if (!(this.halted = !this.__runBeforeLoads(this.params, this.previous))) {
1677
+ Joosy.Application.loading = true;
1678
+ 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) {
1679
+ this.__bootstrapLayout();
1680
+ } else {
1681
+ this.__bootstrap();
1682
+ }
3010
1683
  }
3011
- return this.__query(this.collectionPath(options), 'GET', options.params, callback);
3012
- };
1684
+ }
3013
1685
 
3014
- REST.post = function(options, callback) {
3015
- if (Object.isFunction(options)) {
3016
- callback = options;
3017
- options = {};
3018
- }
3019
- return this.__query(this.collectionPath(options), 'POST', options.params, callback);
1686
+ Page.prototype.navigate = function() {
1687
+ var args, _ref;
1688
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1689
+ return (_ref = Joosy.Router).navigate.apply(_ref, args);
3020
1690
  };
3021
1691
 
3022
- REST.put = function(options, callback) {
3023
- if (Object.isFunction(options)) {
3024
- callback = options;
3025
- options = {};
3026
- }
3027
- return this.__query(this.collectionPath(options), 'PUT', options.params, callback);
1692
+ Page.prototype.__renderSection = function() {
1693
+ return 'pages';
3028
1694
  };
3029
1695
 
3030
- REST["delete"] = function(options, callback) {
3031
- if (Object.isFunction(options)) {
3032
- callback = options;
3033
- options = {};
3034
- }
3035
- return this.__query(this.collectionPath(options), 'DELETE', options.params, callback);
1696
+ Page.prototype.__fixHeight = function() {
1697
+ return $('html').css('min-height', $(document).height());
3036
1698
  };
3037
1699
 
3038
- REST.prototype.get = function(options, callback) {
3039
- if (Object.isFunction(options)) {
3040
- callback = options;
3041
- options = {};
3042
- }
3043
- return this.constructor.__query(this.memberPath(options), 'GET', options.params, callback);
1700
+ Page.prototype.__releaseHeight = function() {
1701
+ return $('html').css('min-height', '');
3044
1702
  };
3045
1703
 
3046
- REST.prototype.post = function(options, callback) {
3047
- if (Object.isFunction(options)) {
3048
- callback = options;
3049
- options = {};
1704
+ Page.prototype.__load = function() {
1705
+ this.refreshElements();
1706
+ this.__delegateEvents();
1707
+ this.__setupWidgets();
1708
+ this.__runAfterLoads(this.params, this.previous);
1709
+ if (this.__scrollElement) {
1710
+ this.__performScrolling();
3050
1711
  }
3051
- return this.constructor.__query(this.memberPath(options), 'POST', options.params, callback);
1712
+ Joosy.Application.loading = false;
1713
+ Joosy.Router.trigger('loaded', this);
1714
+ this.trigger('loaded');
1715
+ return Joosy.Modules.Log.debugAs(this, "Page loaded");
3052
1716
  };
3053
1717
 
3054
- REST.prototype.put = function(options, callback) {
3055
- if (Object.isFunction(options)) {
3056
- callback = options;
3057
- options = {};
3058
- }
3059
- return this.constructor.__query(this.memberPath(options), 'PUT', options.params, callback);
1718
+ Page.prototype.__unload = function() {
1719
+ this.__clearTime();
1720
+ this.__unloadWidgets();
1721
+ this.__removeMetamorphs();
1722
+ this.__runAfterUnloads(this.params, this.previous);
1723
+ return delete this.previous;
3060
1724
  };
3061
1725
 
3062
- REST.prototype["delete"] = function(options, callback) {
3063
- if (Object.isFunction(options)) {
3064
- callback = options;
3065
- options = {};
1726
+ Page.prototype.__callSyncedThrough = function(entity, receiver, params, callback) {
1727
+ if ((entity != null ? entity[receiver] : void 0) != null) {
1728
+ return entity[receiver].apply(entity, params.clone().add(callback));
1729
+ } else {
1730
+ return callback();
3066
1731
  }
3067
- return this.constructor.__query(this.memberPath(options), 'DELETE', options.params, callback);
3068
1732
  };
3069
1733
 
3070
- REST.find = function(where, options, callback) {
3071
- var result,
1734
+ Page.prototype.__bootstrap = function() {
1735
+ var callbacksParams,
3072
1736
  _this = this;
3073
- if (options == null) {
3074
- options = {};
3075
- }
3076
- if (callback == null) {
3077
- callback = false;
3078
- }
3079
- if (Object.isFunction(options)) {
3080
- callback = options;
3081
- options = {};
1737
+ Joosy.Modules.Log.debugAs(this, "Boostraping page");
1738
+ this.layout = this.previous.layout;
1739
+ callbacksParams = [this.layout.content()];
1740
+ if (this.__scrollElement && this.__scrollSpeed !== 0) {
1741
+ this.__fixHeight();
3082
1742
  }
3083
- if (where === 'all') {
3084
- result = new (this.prototype.__collection())(this, options);
3085
- this.__query(this.collectionPath(options), 'GET', options.params, function(data) {
3086
- result.load(data);
3087
- return typeof callback === "function" ? callback(result, data) : void 0;
1743
+ this.wait("stageClear dataReceived", function() {
1744
+ var _ref;
1745
+ if ((_ref = _this.previous) != null) {
1746
+ if (typeof _ref.__afterPaint === "function") {
1747
+ _ref.__afterPaint(callbacksParams);
1748
+ }
1749
+ }
1750
+ return _this.__callSyncedThrough(_this, '__paint', callbacksParams, function() {
1751
+ _this.swapContainer(_this.layout.content(), _this.__renderer(_this.data || {}));
1752
+ _this.container = _this.layout.content();
1753
+ _this.__load();
1754
+ return _this.layout.content();
3088
1755
  });
3089
- } else {
3090
- result = this.build(where);
3091
- this.__query(this.memberPath(where, options), 'GET', options.params, function(data) {
3092
- result.load(data);
3093
- return typeof callback === "function" ? callback(result, data) : void 0;
1756
+ });
1757
+ this.__callSyncedThrough(this.previous, '__erase', callbacksParams, function() {
1758
+ var _ref;
1759
+ if ((_ref = _this.previous) != null) {
1760
+ _ref.__unload();
1761
+ }
1762
+ return _this.__callSyncedThrough(_this, '__beforePaint', callbacksParams, function() {
1763
+ return _this.trigger('stageClear');
3094
1764
  });
3095
- }
3096
- return result;
3097
- };
3098
-
3099
- REST.__query = function(path, method, params, callback) {
3100
- var options;
3101
- options = {
3102
- data: params,
3103
- type: method,
3104
- cache: false,
3105
- dataType: 'json'
3106
- };
3107
- if (Object.isFunction(callback)) {
3108
- options.success = callback;
3109
- } else {
3110
- Joosy.Module.merge(options, callback);
3111
- }
3112
- return $.ajax(path, options);
3113
- };
3114
-
3115
- REST.prototype.reload = function(options, callback) {
3116
- var _this = this;
3117
- if (options == null) {
3118
- options = {};
3119
- }
3120
- if (callback == null) {
3121
- callback = false;
3122
- }
3123
- if (Object.isFunction(options)) {
3124
- callback = options;
3125
- options = {};
3126
- }
3127
- return this.constructor.__query(this.memberPath(options), 'GET', options.params, function(data) {
3128
- _this.load(data);
3129
- return typeof callback === "function" ? callback(_this) : void 0;
1765
+ });
1766
+ return this.__callSyncedThrough(this, '__fetch', [], function() {
1767
+ Joosy.Modules.Log.debugAs(_this, "Fetch complete");
1768
+ return _this.trigger('dataReceived');
3130
1769
  });
3131
1770
  };
3132
1771
 
3133
- return REST;
3134
-
3135
- })(Joosy.Resource.Generic);
3136
-
3137
-
3138
- /*** src/joosy/core/resource/rest_collection ***/
3139
-
3140
- var _ref,
3141
- __hasProp = {}.hasOwnProperty,
3142
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
3143
-
3144
- Joosy.Resource.RESTCollection = (function(_super) {
3145
- __extends(RESTCollection, _super);
3146
-
3147
- function RESTCollection() {
3148
- _ref = RESTCollection.__super__.constructor.apply(this, arguments);
3149
- return _ref;
3150
- }
3151
-
3152
- RESTCollection.include(Joosy.Modules.Log);
3153
-
3154
- RESTCollection.include(Joosy.Modules.Events);
3155
-
3156
- RESTCollection.prototype.reload = function(options, callback) {
3157
- var _this = this;
3158
- if (options == null) {
3159
- options = {};
3160
- }
3161
- if (callback == null) {
3162
- callback = false;
3163
- }
3164
- if (Object.isFunction(options)) {
3165
- callback = options;
3166
- options = {};
1772
+ Page.prototype.__bootstrapLayout = function() {
1773
+ var callbacksParams, _ref,
1774
+ _this = this;
1775
+ Joosy.Modules.Log.debugAs(this, "Boostraping page with layout");
1776
+ this.layout = new this.__layoutClass(this.params);
1777
+ callbacksParams = [Joosy.Application.content(), this];
1778
+ if (this.__scrollElement && this.__scrollSpeed !== 0) {
1779
+ this.__fixHeight();
3167
1780
  }
3168
- return this.model.__query(this.model.collectionPath(options), 'GET', options.params, function(data) {
3169
- _this.load(data);
3170
- return typeof callback === "function" ? callback(data) : void 0;
1781
+ this.wait("stageClear dataReceived", function() {
1782
+ return _this.__callSyncedThrough(_this.layout, '__paint', callbacksParams, function() {
1783
+ var data;
1784
+ data = Joosy.Module.merge({}, _this.layout.data || {});
1785
+ data = Joosy.Module.merge(data, {
1786
+ "yield": function() {
1787
+ return _this.layout["yield"]();
1788
+ }
1789
+ });
1790
+ _this.swapContainer(Joosy.Application.content(), _this.layout.__renderer(data));
1791
+ _this.swapContainer(_this.layout.content(), _this.__renderer(_this.data || {}));
1792
+ _this.container = _this.layout.content();
1793
+ _this.layout.__load(Joosy.Application.content());
1794
+ _this.__load();
1795
+ return Joosy.Application.content();
1796
+ });
1797
+ });
1798
+ this.__callSyncedThrough((_ref = this.previous) != null ? _ref.layout : void 0, '__erase', callbacksParams, function() {
1799
+ var _ref1, _ref2, _ref3;
1800
+ if ((_ref1 = _this.previous) != null) {
1801
+ if ((_ref2 = _ref1.layout) != null) {
1802
+ if (typeof _ref2.__unload === "function") {
1803
+ _ref2.__unload();
1804
+ }
1805
+ }
1806
+ }
1807
+ if ((_ref3 = _this.previous) != null) {
1808
+ _ref3.__unload();
1809
+ }
1810
+ return _this.__callSyncedThrough(_this.layout, '__beforePaint', callbacksParams, function() {
1811
+ return _this.trigger('stageClear');
1812
+ });
1813
+ });
1814
+ return this.__callSyncedThrough(this.layout, '__fetch', [], function() {
1815
+ return _this.__callSyncedThrough(_this, '__fetch', [], function() {
1816
+ Joosy.Modules.Log.debugAs(_this, "Fetch complete");
1817
+ return _this.trigger('dataReceived');
1818
+ });
3171
1819
  });
3172
1820
  };
3173
1821
 
3174
- return RESTCollection;
1822
+ return Page;
3175
1823
 
3176
- })(Joosy.Resource.Collection);
1824
+ })(Joosy.Module);
3177
1825
 
3178
1826
 
3179
- /*** src/joosy/core/resource/watcher ***/
1827
+ /*** src/joosy/core/resources/watcher ***/
3180
1828
 
3181
1829
  var __hasProp = {}.hasOwnProperty,
3182
1830
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
3183
1831
 
3184
- Joosy.Resource.Watcher = (function(_super) {
1832
+ Joosy.Resources.Watcher = (function(_super) {
3185
1833
  __extends(Watcher, _super);
3186
1834
 
3187
1835
  Watcher.include(Joosy.Modules.Events);
@@ -3588,193 +2236,6 @@ Joosy.Widget = (function(_super) {
3588
2236
  })(Joosy.Module);
3589
2237
 
3590
2238
 
3591
- /*** src/joosy/preloaders/caching ***/
3592
-
3593
- this.CachingPreloader = {
3594
- force: false,
3595
- prefix: "cache:",
3596
- counter: 0,
3597
- load: function(libraries, options) {
3598
- var i, key, lib, val, _i, _len, _ref, _ref1;
3599
- if (options == null) {
3600
- options = {};
3601
- }
3602
- for (key in options) {
3603
- val = options[key];
3604
- this[key] = val;
3605
- }
3606
- this.libraries = libraries.slice();
3607
- _ref = this.libraries;
3608
- for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
3609
- lib = _ref[i];
3610
- this.libraries[i] = this.prefix + lib[0];
3611
- }
3612
- if (!this.force && this.check()) {
3613
- return this.restore();
3614
- } else {
3615
- if ((_ref1 = this.start) != null) {
3616
- _ref1.call(window);
3617
- }
3618
- this.clean();
3619
- return this.download(libraries);
3620
- }
3621
- },
3622
- check: function() {
3623
- var flag, i, name, _i, _len, _ref;
3624
- flag = true;
3625
- _ref = this.libraries;
3626
- for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
3627
- name = _ref[i];
3628
- flag && (flag = window.localStorage.getItem(name) != null);
3629
- }
3630
- return flag;
3631
- },
3632
- escapeStr: function(str) {
3633
- return str.replace(new RegExp("\u0001", 'g'), "\\u0001").replace(new RegExp("\u000B", 'g'), "\\u000B");
3634
- },
3635
- restore: function() {
3636
- var i, name, _i, _len, _ref, _ref1;
3637
- _ref = this.libraries;
3638
- for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
3639
- name = _ref[i];
3640
- window.evalGlobaly(window.localStorage.getItem(name));
3641
- }
3642
- return (_ref1 = this.complete) != null ? _ref1.call(window, true) : void 0;
3643
- },
3644
- download: function(libraries) {
3645
- var lib, size, url, _ref,
3646
- _this = this;
3647
- if (libraries.length > 0) {
3648
- this.counter += 1;
3649
- lib = libraries.shift();
3650
- url = lib[0];
3651
- size = lib[1];
3652
- return this.ajax(url, size, function(xhr) {
3653
- var code;
3654
- code = xhr.responseText;
3655
- if (window.navigator.appName === "Microsoft Internet Explorer") {
3656
- code = _this.escapeStr(code);
3657
- }
3658
- window.localStorage.setItem(_this.prefix + url, code);
3659
- window.evalGlobaly(xhr.responseText);
3660
- return _this.download(libraries);
3661
- });
3662
- } else {
3663
- return (_ref = this.complete) != null ? _ref.call(window) : void 0;
3664
- }
3665
- },
3666
- ajax: function(url, size, callback) {
3667
- var poller, x,
3668
- _this = this;
3669
- if (window.XMLHttpRequest) {
3670
- x = new XMLHttpRequest;
3671
- } else {
3672
- x = new ActiveXObject('Microsoft.XMLHTTP');
3673
- }
3674
- x.open('GET', url, 1);
3675
- x.onreadystatechange = function() {
3676
- if (x.readyState > 3) {
3677
- clearInterval(_this.interval);
3678
- return typeof callback === "function" ? callback(x) : void 0;
3679
- }
3680
- };
3681
- if (this.progress) {
3682
- poller = function() {
3683
- var e;
3684
- try {
3685
- return _this.progress.call(window, Math.round((x.responseText.length / size) * (_this.counter / _this.libraries.length) * 100));
3686
- } catch (_error) {
3687
- e = _error;
3688
- }
3689
- };
3690
- this.interval = setInterval(poller, 100);
3691
- }
3692
- return x.send();
3693
- },
3694
- clean: function() {
3695
- var find, i, key, _results;
3696
- i = 0;
3697
- find = function(arr, obj) {
3698
- var x, _i, _len;
3699
- for (_i = 0, _len = arr.length; _i < _len; _i++) {
3700
- x = arr[_i];
3701
- if (obj === x) {
3702
- return i;
3703
- }
3704
- }
3705
- return -1;
3706
- };
3707
- _results = [];
3708
- while (i < window.localStorage.length && (key = window.localStorage.key(i))) {
3709
- if (key.indexOf(this.prefix) === 0 && find(this.libraries, key) < 0) {
3710
- _results.push(window.localStorage.removeItem(key));
3711
- } else {
3712
- _results.push(i += 1);
3713
- }
3714
- }
3715
- return _results;
3716
- }
3717
- };
3718
-
3719
- window.evalGlobaly = function(src) {
3720
- if (src.length === 0) {
3721
- return;
3722
- }
3723
- if (window.execScript) {
3724
- return window.execScript(src);
3725
- } else {
3726
- return window["eval"](src);
3727
- }
3728
- };
3729
-
3730
- this.Preloader = this.CachingPreloader;
3731
-
3732
-
3733
- /*** src/joosy/preloaders/inline ***/
3734
-
3735
- this.InlinePreloader = {
3736
- load: function(libraries, options) {
3737
- var key, val,
3738
- _this = this;
3739
- for (key in options) {
3740
- val = options[key];
3741
- this[key] = val;
3742
- }
3743
- if (typeof this.start === "function") {
3744
- this.start();
3745
- }
3746
- if (libraries.length > 0) {
3747
- return this.receive(libraries.shift()[0], function() {
3748
- return _this.load(libraries);
3749
- });
3750
- } else {
3751
- return typeof this.complete === "function" ? this.complete() : void 0;
3752
- }
3753
- },
3754
- receive: function(url, callback) {
3755
- var done, head, proceed, script;
3756
- head = document.getElementsByTagName("head")[0];
3757
- script = document.createElement("script");
3758
- script.src = url;
3759
- done = false;
3760
- proceed = function() {
3761
- if (!done && ((this.readyState == null) || this.readyState === "loaded" || this.readyState === "complete")) {
3762
- done = true;
3763
- if (typeof callback === "function") {
3764
- callback();
3765
- }
3766
- return script.onload = script.onreadystatechange = null;
3767
- }
3768
- };
3769
- script.onload = script.onreadystatechange = proceed;
3770
- head.appendChild(script);
3771
- return void 0;
3772
- }
3773
- };
3774
-
3775
- this.Preloader = this.InlinePreloader;
3776
-
3777
-
3778
2239
  /*** src/joosy ***/
3779
2240
 
3780
2241