luca 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/CHANGELOG +9 -0
  2. data/ROADMAP +15 -3
  3. data/Rakefile +33 -7
  4. data/app.rb +0 -1
  5. data/assets/javascripts/dependencies.coffee +0 -1
  6. data/assets/javascripts/sandbox/application.coffee +1 -1
  7. data/assets/javascripts/sandbox/templates/main.luca +52 -34
  8. data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +3 -1
  9. data/assets/stylesheets/bootstrap-responsive.min.css +0 -1
  10. data/assets/stylesheets/bootstrap.min.css +48 -29
  11. data/assets/stylesheets/sandbox/sandbox.scss +11 -28
  12. data/lib/luca/rails/version.rb +1 -1
  13. data/site/assets/dependencies.js +94 -0
  14. data/site/assets/glyphicons-halflings-white.png +0 -0
  15. data/site/assets/glyphicons-halflings.png +0 -0
  16. data/site/assets/luca-ui-bootstrap.css +1313 -0
  17. data/site/assets/luca-ui-bootstrap.js +9 -0
  18. data/site/assets/luca-ui-development-tools.css +224 -0
  19. data/site/assets/luca-ui-development-tools.js +18561 -0
  20. data/site/assets/sandbox.css +14 -0
  21. data/site/assets/sandbox.js +131 -0
  22. data/site/index.html +20 -0
  23. data/spec/core/collection_spec.coffee +6 -6
  24. data/spec/core/view_spec.coffee +1 -0
  25. data/spec/framework_spec.coffee +7 -0
  26. data/spec/managers/collection_manager_spec.coffee +2 -1
  27. data/src/components/application.coffee +8 -4
  28. data/src/components/collection_view.coffee +8 -2
  29. data/src/components/fields/checkbox_array.coffee +3 -1
  30. data/src/components/form_view.coffee +46 -21
  31. data/src/components/grid_view.coffee +2 -4
  32. data/src/components/nav_bar.coffee +3 -7
  33. data/src/containers/tab_view.coffee +15 -2
  34. data/src/containers/viewport.coffee +13 -4
  35. data/src/core/collection.coffee +68 -53
  36. data/src/core/core.coffee +7 -2
  37. data/src/core/panel.coffee +32 -17
  38. data/src/core/registry.coffee +11 -3
  39. data/src/core/util.coffee +17 -1
  40. data/src/core/view.coffee +6 -5
  41. data/src/framework.coffee +46 -2
  42. data/src/managers/collection_manager.coffee +22 -81
  43. data/src/stylesheets/components/checkbox_array.scss +5 -0
  44. data/src/templates/components/form_alert +0 -0
  45. data/src/templates/components/form_alert.luca +3 -0
  46. data/src/templates/containers/tab_view.luca +1 -1
  47. data/src/tools/console.coffee +3 -0
  48. data/vendor/assets/javascripts/luca-ui-base.js +266 -128
  49. data/vendor/assets/javascripts/luca-ui-development-tools.js +3 -161
  50. data/vendor/assets/javascripts/luca-ui-development-tools.min.js +15 -0
  51. data/vendor/assets/javascripts/luca-ui-spec.js +380 -176
  52. data/vendor/assets/javascripts/luca-ui.js +348 -166
  53. data/vendor/assets/javascripts/luca-ui.min.js +4 -3
  54. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +50 -29
  55. data/vendor/assets/stylesheets/luca-ui-spec.css +2 -0
  56. data/vendor/assets/stylesheets/luca-ui.css +2 -0
  57. metadata +16 -4
  58. data/src/templates/components/form_view.luca +0 -4
  59. data/src/tools/development_console.coffee +0 -147
@@ -18,7 +18,7 @@
18
18
  };
19
19
 
20
20
  _.extend(Luca, {
21
- VERSION: "0.9.1",
21
+ VERSION: "0.9.2",
22
22
  core: {},
23
23
  containers: {},
24
24
  components: {},
@@ -30,6 +30,8 @@
30
30
 
31
31
  _.extend(Luca, Backbone.Events);
32
32
 
33
+ Luca.autoRegister = true;
34
+
33
35
  Luca.developmentMode = false;
34
36
 
35
37
  Luca.enableGlobalObserver = false;
@@ -64,6 +66,10 @@
64
66
  return Luca.isBackboneModel(obj) || Luca.isBackboneView(obj) || Luca.isBackboneCollection(obj);
65
67
  };
66
68
 
69
+ Luca.isComponentPrototype = function(obj) {
70
+ return Luca.isViewPrototype(obj) || Luca.isModelPrototype(obj) || Luca.isCollectionPrototype(obj);
71
+ };
72
+
67
73
  Luca.isBackboneModel = function(obj) {
68
74
  return _.isFunction(obj != null ? obj.set : void 0) && _.isFunction(obj != null ? obj.get : void 0) && _.isObject(obj != null ? obj.attributes : void 0);
69
75
  };
@@ -76,6 +82,52 @@
76
82
  return _.isFunction(obj != null ? obj.fetch : void 0) && _.isFunction(obj != null ? obj.reset : void 0);
77
83
  };
78
84
 
85
+ Luca.isViewPrototype = function(obj) {
86
+ return (obj != null) && (obj.prototype != null) && (obj.prototype.make != null) && (obj.prototype.$ != null) && (obj.prototype.render != null);
87
+ };
88
+
89
+ Luca.isModelPrototype = function(obj) {
90
+ return (obj != null) && (typeof obj.prototype === "function" ? obj.prototype((obj.prototype.save != null) && (obj.prototype.changedAttributes != null)) : void 0);
91
+ };
92
+
93
+ Luca.isCollectionPrototype = function(obj) {
94
+ return (obj != null) && (obj.prototype != null) && !Luca.isModelPrototype(obj) && (obj.prototype.reset != null) && (obj.prototype.select != null) && (obj.prototype.reject != null);
95
+ };
96
+
97
+ Luca.inheritanceChain = function(obj) {
98
+ return _(Luca.parentClasses(obj)).map(function(className) {
99
+ return Luca.util.resolve(className);
100
+ });
101
+ };
102
+
103
+ Luca.parentClasses = function(obj) {
104
+ var classes, list, _ref;
105
+ list = [];
106
+ if (_.isString(obj)) obj = Luca.util.resolve(obj);
107
+ list.push(obj.displayName || ((_ref = obj.prototype) != null ? _ref.displayName : void 0) || Luca.parentClass(obj));
108
+ classes = (function() {
109
+ var _results;
110
+ _results = [];
111
+ while (!!(Luca.parentClass(obj) != null)) {
112
+ _results.push(obj = Luca.parentClass(obj));
113
+ }
114
+ return _results;
115
+ })();
116
+ list = list.concat(classes);
117
+ return _.uniq(list);
118
+ };
119
+
120
+ Luca.parentClass = function(obj) {
121
+ var list, _base, _ref;
122
+ list = [];
123
+ if (_.isString(obj)) obj = Luca.util.resolve(obj);
124
+ if (Luca.isComponent(obj)) {
125
+ return obj.displayName;
126
+ } else if (Luca.isComponentPrototype(obj)) {
127
+ return typeof (_base = obj.prototype)._superClass === "function" ? (_ref = _base._superClass()) != null ? _ref.displayName : void 0 : void 0;
128
+ }
129
+ };
130
+
79
131
  Luca.template = function(template_name, variables) {
80
132
  var jst, luca, needle, template, _ref;
81
133
  window.JST || (window.JST = {});
@@ -252,6 +304,30 @@
252
304
  return document.body.appendChild(script);
253
305
  };
254
306
 
307
+ Luca.util.make = Backbone.View.prototype.make;
308
+
309
+ Luca.util.label = function(contents, type, baseClass) {
310
+ var cssClass;
311
+ if (contents == null) contents = "";
312
+ if (baseClass == null) baseClass = "label";
313
+ cssClass = baseClass;
314
+ if (type != null) cssClass += " " + baseClass + "-" + type;
315
+ return Luca.util.make("span", {
316
+ "class": cssClass
317
+ }, contents);
318
+ };
319
+
320
+ Luca.util.badge = function(contents, type, baseClass) {
321
+ var cssClass;
322
+ if (contents == null) contents = "";
323
+ if (baseClass == null) baseClass = "badge";
324
+ cssClass = baseClass;
325
+ if (type != null) cssClass += " " + baseClass + "-" + type;
326
+ return Luca.util.make("span", {
327
+ "class": cssClass
328
+ }, contents);
329
+ };
330
+
255
331
  }).call(this);
256
332
  (function() {
257
333
  var DeferredBindingProxy, DefineProxy;
@@ -303,14 +379,21 @@
303
379
  };
304
380
 
305
381
  DefineProxy.prototype["with"] = function(properties) {
306
- var at;
382
+ var at, componentType;
307
383
  at = this.namespaced ? Luca.util.resolve(this.namespace, window || global) : window || global;
308
384
  if (this.namespaced && !(at != null)) {
309
385
  eval("(window||global)." + this.namespace + " = {}");
310
386
  at = Luca.util.resolve(this.namespace, window || global);
311
387
  }
312
388
  at[this.componentId] = Luca.extend(this.superClassName, this.componentName, properties);
313
- Luca.register(_.string.underscored(this.componentId), this.componentName);
389
+ if (Luca.autoRegister === true) {
390
+ if (Luca.isViewPrototype(at[this.componentId])) componentType = "view";
391
+ if (Luca.isCollectionPrototype(at[this.componentId])) {
392
+ componentType = "collection";
393
+ }
394
+ if (Luca.isModelPrototype(at[this.componentId])) componentType = "model";
395
+ Luca.register(_.string.underscored(this.componentId), this.componentName, componentType);
396
+ }
314
397
  return at[this.componentId];
315
398
  };
316
399
 
@@ -448,6 +531,8 @@
448
531
 
449
532
  registry = {
450
533
  classes: {},
534
+ model_classes: {},
535
+ collection_classes: {},
451
536
  namespaces: ['Luca.containers', 'Luca.components']
452
537
  };
453
538
 
@@ -458,9 +543,17 @@
458
543
 
459
544
  Luca.defaultComponentType = 'view';
460
545
 
461
- Luca.register = function(component, prototypeName) {
546
+ Luca.register = function(component, prototypeName, componentType) {
547
+ if (componentType == null) componentType = "view";
462
548
  Luca.trigger("component:registered", component, prototypeName);
463
- return registry.classes[component] = prototypeName;
549
+ switch (componentType) {
550
+ case "model":
551
+ return registry.model_classes[component] = prototypeName;
552
+ case "collection":
553
+ return registry.model_classes[component] = prototypeName;
554
+ default:
555
+ return registry.classes[component] = prototypeName;
556
+ }
464
557
  };
465
558
 
466
559
  Luca.development_mode_register = function(component, prototypeName) {
@@ -599,7 +692,7 @@
599
692
  return this.delegateEvents();
600
693
  },
601
694
  $wrap: function(wrapper) {
602
- if (!wrapper.match(/[<>]/)) {
695
+ if (_.isString(wrapper) && !wrapper.match(/[<>]/)) {
603
696
  wrapper = this.make("div", {
604
697
  "class": wrapper
605
698
  });
@@ -639,8 +732,8 @@
639
732
  });
640
733
  },
641
734
  getCollectionManager: function() {
642
- var _ref;
643
- return this.collectionManager || ((_ref = Luca.CollectionManager.get) != null ? _ref.call() : void 0);
735
+ var _base;
736
+ return this.collectionManager || (typeof (_base = Luca.CollectionManager).get === "function" ? _base.get() : void 0);
644
737
  },
645
738
  registerCollectionEvents: function() {
646
739
  var manager,
@@ -722,7 +815,7 @@
722
815
  _base = definition.render;
723
816
  _base || (_base = Luca.View.prototype.$attach);
724
817
  definition.render = function() {
725
- var autoTrigger, fn, target, trigger, view,
818
+ var autoTrigger, deferred, fn, target, trigger, view,
726
819
  _this = this;
727
820
  view = this;
728
821
  if (this.deferrable) {
@@ -732,10 +825,11 @@
732
825
  }
733
826
  target || (target = this.deferrable);
734
827
  trigger = this.deferrable_event ? this.deferrable_event : "reset";
735
- view.defer(function() {
828
+ deferred = function() {
736
829
  _base.call(view);
737
830
  return view.trigger("after:render", view);
738
- }).until(target, trigger);
831
+ };
832
+ view.defer(deferred).until(target, trigger);
739
833
  view.trigger("before:render", this);
740
834
  autoTrigger = this.deferrable_trigger || this.deferUntil;
741
835
  if (!(autoTrigger != null)) {
@@ -809,72 +903,7 @@
809
903
 
810
904
  _.def("Luca.Collection")["extends"](source)["with"]({
811
905
  cachedMethods: [],
812
- restoreMethodCache: function() {
813
- var config, name, _ref, _results;
814
- _ref = this._methodCache;
815
- _results = [];
816
- for (name in _ref) {
817
- config = _ref[name];
818
- if (config.original != null) {
819
- config.args = void 0;
820
- _results.push(this[name] = config.original);
821
- } else {
822
- _results.push(void 0);
823
- }
824
- }
825
- return _results;
826
- },
827
- clearMethodCache: function(method) {
828
- return this._methodCache[method].value = void 0;
829
- },
830
- clearAllMethodsCache: function() {
831
- var config, name, _ref, _results;
832
- _ref = this._methodCache;
833
- _results = [];
834
- for (name in _ref) {
835
- config = _ref[name];
836
- _results.push(this.clearMethodCache(name));
837
- }
838
- return _results;
839
- },
840
- setupMethodCaching: function() {
841
- var cache, collection, membershipEvents;
842
- collection = this;
843
- membershipEvents = ["reset", "add", "remove"];
844
- cache = this._methodCache = {};
845
- return _(this.cachedMethods).each(function(method) {
846
- var dependencies, dependency, membershipEvent, _i, _j, _len, _len2, _ref, _results;
847
- cache[method] = {
848
- name: method,
849
- original: collection[method],
850
- value: void 0
851
- };
852
- collection[method] = function() {
853
- var _base;
854
- return (_base = cache[method]).value || (_base.value = cache[method].original.apply(collection, arguments));
855
- };
856
- for (_i = 0, _len = membershipEvents.length; _i < _len; _i++) {
857
- membershipEvent = membershipEvents[_i];
858
- collection.bind(membershipEvent, function() {
859
- return collection.clearAllMethodsCache();
860
- });
861
- }
862
- dependencies = method.split(':')[1];
863
- if (dependencies) {
864
- _ref = dependencies.split(",");
865
- _results = [];
866
- for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
867
- dependency = _ref[_j];
868
- _results.push(collection.bind("change:" + dependency, function() {
869
- return collection.clearMethodCache({
870
- method: method
871
- });
872
- }));
873
- }
874
- return _results;
875
- }
876
- });
877
- },
906
+ remoteFilter: false,
878
907
  initialize: function(models, options) {
879
908
  var table,
880
909
  _this = this;
@@ -894,6 +923,7 @@
894
923
  }
895
924
  this.name || (this.name = this.registerAs);
896
925
  this.manager || (this.manager = this.registerWith);
926
+ this.manager = _.isFunction(this.manager) ? this.manager() : this.manager;
897
927
  if (this.name && !this.manager) this.manager = Luca.CollectionManager.get();
898
928
  if (this.manager) {
899
929
  this.name || (this.name = this.cache_key());
@@ -957,14 +987,13 @@
957
987
  return _.uniq(parts).join("&");
958
988
  },
959
989
  resetFilter: function() {
960
- this.base_params = Luca.Collection.baseParams();
990
+ this.base_params = _(Luca.Collection.baseParams()).clone();
961
991
  return this;
962
992
  },
963
- remoteFilter: true,
964
993
  applyFilter: function(filter, options) {
965
994
  if (filter == null) filter = {};
966
995
  if (options == null) options = {};
967
- if ((options.remote != null) === true) {
996
+ if ((options.remote != null) === true || this.remoteFilter === true) {
968
997
  this.applyParams(filter);
969
998
  return this.fetch(_.extend(options, {
970
999
  refresh: true
@@ -974,8 +1003,9 @@
974
1003
  }
975
1004
  },
976
1005
  applyParams: function(params) {
977
- this.base_params || (this.base_params = _(Luca.Collection.baseParams()).clone());
978
- return _.extend(this.base_params, params);
1006
+ this.base_params = _(Luca.Collection.baseParams()).clone();
1007
+ _.extend(this.base_params, params);
1008
+ return this;
979
1009
  },
980
1010
  register: function(collectionManager, key, collection) {
981
1011
  if (collectionManager == null) {
@@ -1059,7 +1089,7 @@
1059
1089
  scope = options.scope || this;
1060
1090
  if (this.length > 0 && !this.fetching) fn.apply(scope, [this]);
1061
1091
  this.bind("reset", function(collection) {
1062
- return fn.apply(scope, [collection]);
1092
+ return fn.call(scope, collection);
1063
1093
  });
1064
1094
  if (!(this.fetching === true || !options.autoFetch || this.length > 0)) {
1065
1095
  return this.fetch();
@@ -1074,6 +1104,81 @@
1074
1104
  Luca.Collection.cache(this.bootstrap_cache_key, models);
1075
1105
  }
1076
1106
  return models;
1107
+ },
1108
+ restoreMethodCache: function() {
1109
+ var config, name, _ref, _results;
1110
+ _ref = this._methodCache;
1111
+ _results = [];
1112
+ for (name in _ref) {
1113
+ config = _ref[name];
1114
+ if (config.original != null) {
1115
+ config.args = void 0;
1116
+ _results.push(this[name] = config.original);
1117
+ } else {
1118
+ _results.push(void 0);
1119
+ }
1120
+ }
1121
+ return _results;
1122
+ },
1123
+ clearMethodCache: function(method) {
1124
+ return this._methodCache[method].value = void 0;
1125
+ },
1126
+ clearAllMethodsCache: function() {
1127
+ var config, name, _ref, _results;
1128
+ _ref = this._methodCache;
1129
+ _results = [];
1130
+ for (name in _ref) {
1131
+ config = _ref[name];
1132
+ _results.push(this.clearMethodCache(name));
1133
+ }
1134
+ return _results;
1135
+ },
1136
+ setupMethodCaching: function() {
1137
+ var cache, collection, membershipEvents;
1138
+ collection = this;
1139
+ membershipEvents = ["reset", "add", "remove"];
1140
+ cache = this._methodCache = {};
1141
+ return _(this.cachedMethods).each(function(method) {
1142
+ var dependencies, dependency, membershipEvent, _i, _j, _len, _len2, _ref, _results;
1143
+ cache[method] = {
1144
+ name: method,
1145
+ original: collection[method],
1146
+ value: void 0
1147
+ };
1148
+ collection[method] = function() {
1149
+ var _base;
1150
+ return (_base = cache[method]).value || (_base.value = cache[method].original.apply(collection, arguments));
1151
+ };
1152
+ for (_i = 0, _len = membershipEvents.length; _i < _len; _i++) {
1153
+ membershipEvent = membershipEvents[_i];
1154
+ collection.bind(membershipEvent, function() {
1155
+ return collection.clearAllMethodsCache();
1156
+ });
1157
+ }
1158
+ dependencies = method.split(':')[1];
1159
+ if (dependencies) {
1160
+ _ref = dependencies.split(",");
1161
+ _results = [];
1162
+ for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
1163
+ dependency = _ref[_j];
1164
+ _results.push(collection.bind("change:" + dependency, function() {
1165
+ return collection.clearMethodCache({
1166
+ method: method
1167
+ });
1168
+ }));
1169
+ }
1170
+ return _results;
1171
+ }
1172
+ });
1173
+ },
1174
+ query: function(filter, options) {
1175
+ if (filter == null) filter = {};
1176
+ if (options == null) options = {};
1177
+ if (Backbone.QueryCollection != null) {
1178
+ return Backbone.QueryCollection.prototype.query.apply(this, arguments);
1179
+ } else {
1180
+ return this.models;
1181
+ }
1077
1182
  }
1078
1183
  });
1079
1184
 
@@ -1092,7 +1197,7 @@
1092
1197
  Luca.Collection.baseParams = function(obj) {
1093
1198
  if (obj) return Luca.Collection._baseParams = obj;
1094
1199
  if (_.isFunction(Luca.Collection._baseParams)) {
1095
- return Luca.Collection._baseParams.call();
1200
+ return Luca.Collection._baseParams();
1096
1201
  }
1097
1202
  if (_.isObject(Luca.Collection._baseParams)) {
1098
1203
  return Luca.Collection._baseParams;
@@ -1114,7 +1219,7 @@
1114
1219
  (function() {
1115
1220
  var attachToolbar;
1116
1221
 
1117
- attachToolbar = function(config) {
1222
+ attachToolbar = function(config, targetEl) {
1118
1223
  var action, container, hasBody, id, toolbar;
1119
1224
  if (config == null) config = {};
1120
1225
  config.orientation || (config.orientation = "top");
@@ -1145,7 +1250,7 @@
1145
1250
  }
1146
1251
  }
1147
1252
  })();
1148
- return this.$bodyEl()[action](container);
1253
+ return (targetEl || this.$bodyEl())[action](container);
1149
1254
  };
1150
1255
 
1151
1256
  _.def("Luca.components.Panel")["extends"]("Luca.View")["with"]({
@@ -1153,10 +1258,12 @@
1153
1258
  bottomToolbar: void 0,
1154
1259
  loadMask: false,
1155
1260
  loadMaskTemplate: ["components/load_mask"],
1261
+ loadMaskTimeout: 3000,
1156
1262
  initialize: function(options) {
1157
1263
  var _this = this;
1158
1264
  this.options = options != null ? options : {};
1159
1265
  Luca.View.prototype.initialize.apply(this, arguments);
1266
+ _.bindAll(this, "applyLoadMask", "disableLoadMask");
1160
1267
  if (this.loadMask === true) {
1161
1268
  this.defer(function() {
1162
1269
  _this.$el.addClass('with-mask');
@@ -1176,25 +1283,35 @@
1176
1283
  return this.$bodyEl();
1177
1284
  }
1178
1285
  },
1179
- applyLoadMask: function() {
1286
+ disableLoadMask: function() {
1287
+ this.$('.load-mask .bar').css("width", "100%");
1288
+ this.$('.load-mask').hide();
1289
+ return clearInterval(this.loadMaskInterval);
1290
+ },
1291
+ enableLoadMask: function() {
1180
1292
  var maxWidth,
1181
1293
  _this = this;
1294
+ this.$('.load-mask').show().find('.bar').css("width", "0%");
1295
+ maxWidth = this.$('.load-mask .progress').width();
1296
+ if (maxWidth < 20 && (maxWidth = this.$el.width()) < 20) {
1297
+ maxWidth = this.$el.parent().width();
1298
+ }
1299
+ this.loadMaskInterval = setInterval(function() {
1300
+ var currentWidth, newWidth;
1301
+ currentWidth = _this.$('.load-mask .bar').width();
1302
+ newWidth = currentWidth + 12;
1303
+ return _this.$('.load-mask .bar').css('width', newWidth);
1304
+ }, 200);
1305
+ if (this.loadMaskTimeout == null) return;
1306
+ return _.delay(function() {
1307
+ return _this.disableLoadMask();
1308
+ }, this.loadMaskTimeout);
1309
+ },
1310
+ applyLoadMask: function() {
1182
1311
  if (this.$('.load-mask').is(":visible")) {
1183
- this.$('.load-mask .bar').css("width", "100%");
1184
- this.$('.load-mask').hide();
1185
- return clearInterval(this.loadMaskInterval);
1312
+ return this.disableLoadMask();
1186
1313
  } else {
1187
- this.$('.load-mask').show().find('.bar').css("width", "0%");
1188
- maxWidth = this.$('.load-mask .progress').width();
1189
- if (maxWidth < 20 && (maxWidth = this.$el.width()) < 20) {
1190
- maxWidth = this.$el.parent().width();
1191
- }
1192
- return this.loadMaskInterval = setInterval(function() {
1193
- var currentWidth, newWidth;
1194
- currentWidth = _this.$('.load-mask .bar').width();
1195
- newWidth = currentWidth + 12;
1196
- return _this.$('.load-mask .bar').css('width', newWidth);
1197
- }, 200);
1314
+ return this.enableLoadMask();
1198
1315
  }
1199
1316
  },
1200
1317
  applyStyles: function(styles, body) {
@@ -1235,7 +1352,7 @@
1235
1352
  return $(this.el);
1236
1353
  },
1237
1354
  $wrap: function(wrapper) {
1238
- if (!wrapper.match(/[<>]/)) {
1355
+ if (_.isString(wrapper) && !wrapper.match(/[<>]/)) {
1239
1356
  wrapper = this.make("div", {
1240
1357
  "class": wrapper
1241
1358
  });
@@ -1266,7 +1383,7 @@
1266
1383
  if (config == null) config = {};
1267
1384
  config.parent = this;
1268
1385
  config.orientation = orientation;
1269
- return attachToolbar.call(this, config);
1386
+ return attachToolbar.call(this, config, config.targetEl);
1270
1387
  }
1271
1388
  });
1272
1389
 
@@ -1383,7 +1500,7 @@
1383
1500
  }).call(this);
1384
1501
  (function() {
1385
1502
  Luca.templates || (Luca.templates = {});
1386
- Luca.templates["components/form_view"] = function(obj){var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('<div class=\'form-view-panel\'>\n <ul class=\'form-view-flash-container\'></ul>\n <div class=\'form-view-body\'></div>\n</div>\n');}return __p.join('');};
1503
+ Luca.templates["components/form_alert"] = function(obj){var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('<div class=\'', className ,'\'>\n <a class=\'close\' data-dismiss=\'alert\' href=\'#\'>x</a>\n ', message ,'\n</div>\n');}return __p.join('');};
1387
1504
  }).call(this);
1388
1505
  (function() {
1389
1506
  Luca.templates || (Luca.templates = {});
@@ -1411,7 +1528,7 @@
1411
1528
  }).call(this);
1412
1529
  (function() {
1413
1530
  Luca.templates || (Luca.templates = {});
1414
- Luca.templates["containers/tab_view"] = function(obj){var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('<ul class=\'nav nav-tabs\' id=\'', cid ,'-tabs-selector\'></ul>\n<div class=\'tab-content\' id=\'', cid ,'-tab-view-content\'></div>\n');}return __p.join('');};
1531
+ Luca.templates["containers/tab_view"] = function(obj){var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('<ul class=\'nav ', navClass ,'\' id=\'', cid ,'-tabs-selector\'></ul>\n<div class=\'tab-content\' id=\'', cid ,'-tab-view-content\'></div>\n');}return __p.join('');};
1415
1532
  }).call(this);
1416
1533
  (function() {
1417
1534
  Luca.templates || (Luca.templates = {});
@@ -1816,20 +1933,30 @@
1816
1933
 
1817
1934
  }).call(this);
1818
1935
  (function() {
1819
- var instances;
1820
-
1821
- instances = [];
1822
1936
 
1823
1937
  Luca.CollectionManager = (function() {
1824
1938
 
1939
+ CollectionManager.prototype.name = "primary";
1940
+
1825
1941
  CollectionManager.prototype.__collections = {};
1826
1942
 
1827
1943
  function CollectionManager(options) {
1944
+ var existing, manager, _base, _base2;
1828
1945
  this.options = options != null ? options : {};
1829
1946
  _.extend(this, this.options);
1947
+ manager = this;
1948
+ if (existing = typeof (_base = Luca.CollectionManager).get === "function" ? _base.get(this.name) : void 0) {
1949
+ throw 'Attempt to create a collection manager with a name which already exists';
1950
+ }
1951
+ (_base2 = Luca.CollectionManager).instances || (_base2.instances = {});
1830
1952
  _.extend(this, Backbone.Events);
1831
- instances.push(this);
1832
- this.state = new Backbone.Model;
1953
+ _.extend(this, Luca.Events);
1954
+ Luca.CollectionManager.instances[this.name] = manager;
1955
+ Luca.CollectionManager.get = function(name) {
1956
+ if (name == null) return manager;
1957
+ return Luca.CollectionManager.instances[name];
1958
+ };
1959
+ this.state = new Luca.Model();
1833
1960
  if (this.initialCollections) {
1834
1961
  this.state.set({
1835
1962
  loaded_collections_count: 0,
@@ -1947,15 +2074,7 @@
1947
2074
  })();
1948
2075
 
1949
2076
  Luca.CollectionManager.destroyAll = function() {
1950
- return instances = [];
1951
- };
1952
-
1953
- Luca.CollectionManager.instances = function() {
1954
- return instances;
1955
- };
1956
-
1957
- Luca.CollectionManager.get = function() {
1958
- return _(instances).last();
2077
+ return Luca.CollectionManager.instances = {};
1959
2078
  };
1960
2079
 
1961
2080
  }).call(this);
@@ -2371,10 +2490,12 @@
2371
2490
  className: 'luca-ui-tab-view tabbable',
2372
2491
  tab_position: 'top',
2373
2492
  tabVerticalOffset: '50px',
2493
+ navClass: "nav-tabs",
2374
2494
  bodyTemplate: "containers/tab_view",
2375
2495
  bodyEl: "div.tab-content",
2376
2496
  initialize: function(options) {
2377
2497
  this.options = options != null ? options : {};
2498
+ if (this.navStyle === "list") this.navClass = "nav-list";
2378
2499
  Luca.containers.CardView.prototype.initialize.apply(this, arguments);
2379
2500
  _.bindAll(this, "select", "highlightSelectedTab");
2380
2501
  this.setupHooks(this.hooks);
@@ -2405,12 +2526,21 @@
2405
2526
  var tabView;
2406
2527
  tabView = this;
2407
2528
  return this.each(function(component, index) {
2408
- var selector;
2529
+ var icon, link, selector, _ref;
2530
+ if (component.tabIcon) icon = "<i class='icon-" + component.tabIcon;
2531
+ link = "<a href='#'>" + (icon || '') + " " + component.title + "</a>";
2409
2532
  selector = tabView.make("li", {
2410
2533
  "class": "tab-selector",
2411
2534
  "data-target": index
2412
- }, "<a>" + component.title + "</a>");
2413
- return tabView.tabContainer().append(selector);
2535
+ }, link);
2536
+ tabView.tabContainer().append(selector);
2537
+ if ((component.navHeading != null) && !((_ref = tabView.navHeadings) != null ? _ref[component.navHeading] : void 0)) {
2538
+ $(selector).before(tabView.make('li', {
2539
+ "class": "nav-header"
2540
+ }, component.navHeading));
2541
+ tabView.navHeadings || (tabView.navHeadings = {});
2542
+ return tabView.navHeadings[component.navHeading] = true;
2543
+ }
2414
2544
  });
2415
2545
  },
2416
2546
  highlightSelectedTab: function() {
@@ -2419,6 +2549,7 @@
2419
2549
  },
2420
2550
  select: function(e) {
2421
2551
  var me, my;
2552
+ e.preventDefault();
2422
2553
  me = my = $(e.target);
2423
2554
  this.trigger("before:select", this);
2424
2555
  this.activate(my.parent().data('target'));
@@ -2434,7 +2565,7 @@
2434
2565
  return $("#" + this.cid + "-tabs-selector");
2435
2566
  },
2436
2567
  tabContainer: function() {
2437
- return this.$('ul.nav-tabs', this.tabContainerWrapper());
2568
+ return this.$("ul." + this.navClass, this.tabContainerWrapper());
2438
2569
  },
2439
2570
  tabSelectors: function() {
2440
2571
  return this.$('li.tab-selector', this.tabContainer());
@@ -2452,11 +2583,12 @@
2452
2583
  wrapperClass: 'row',
2453
2584
  initialize: function(options) {
2454
2585
  this.options = options != null ? options : {};
2455
- Luca.core.Container.prototype.initialize.apply(this, arguments);
2586
+ _.extend(this, this.options);
2456
2587
  if (Luca.enableBootstrap === true) {
2457
2588
  if (this.fluid === true) this.wrapperClass = "row-fluid";
2458
- this.$el.wrap("<div class='" + this.wrapperClass + "' />").addClass('span12');
2589
+ this.$wrap(this.wrapperClass);
2459
2590
  }
2591
+ Luca.core.Container.prototype.initialize.apply(this, arguments);
2460
2592
  if (this.fullscreen) return $('html,body').addClass('luca-ui-fullscreen');
2461
2593
  },
2462
2594
  beforeRender: function() {
@@ -2464,12 +2596,18 @@
2464
2596
  if ((_ref = Luca.containers.CardView.prototype.beforeRender) != null) {
2465
2597
  _ref.apply(this, arguments);
2466
2598
  }
2467
- if (Luca.enableBootstrap && this.topNav && this.fullscreen) {
2468
- $('body').css('padding', '40px');
2469
- }
2470
2599
  if (this.topNav != null) this.renderTopNavigation();
2471
2600
  if (this.bottomNav != null) return this.renderBottomNavigation();
2472
2601
  },
2602
+ afterRender: function() {
2603
+ var _ref;
2604
+ if ((_ref = Luca.containers.CardView.prototype.after) != null) {
2605
+ _ref.apply(this, arguments);
2606
+ }
2607
+ if (Luca.enableBootstrap === true) {
2608
+ return this.$el.children().wrap('<div class="container" />');
2609
+ }
2610
+ },
2473
2611
  renderTopNavigation: function() {
2474
2612
  var _base;
2475
2613
  if (this.topNav == null) return;