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

Sign up to get free protection for your applications and to get access to all the features.
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