luca 0.6.6

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 (233) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +77 -0
  4. data/Guardfile +22 -0
  5. data/README.md +291 -0
  6. data/Rakefile +28 -0
  7. data/app.rb +46 -0
  8. data/assets/images/glyphicons-halflings-white.png +0 -0
  9. data/assets/images/glyphicons-halflings.png +0 -0
  10. data/assets/javascripts/dependencies/backbone-min.js +37 -0
  11. data/assets/javascripts/dependencies/backbone-query.min.js +1 -0
  12. data/assets/javascripts/dependencies/bootstrap.min.js +1 -0
  13. data/assets/javascripts/dependencies/jasmine-html.js +190 -0
  14. data/assets/javascripts/dependencies/jasmine.js +2476 -0
  15. data/assets/javascripts/dependencies/jquery.js +4 -0
  16. data/assets/javascripts/dependencies/modal.js +698 -0
  17. data/assets/javascripts/dependencies/modernizr.min.js +30 -0
  18. data/assets/javascripts/dependencies/prettify.js +28 -0
  19. data/assets/javascripts/dependencies/sinon.js +3469 -0
  20. data/assets/javascripts/dependencies/spin-min.js +2 -0
  21. data/assets/javascripts/dependencies/underscore-min.js +31 -0
  22. data/assets/javascripts/dependencies/underscore-string.min.js +14 -0
  23. data/assets/javascripts/dependencies.coffee +7 -0
  24. data/assets/javascripts/luca-ui-base.coffee +12 -0
  25. data/assets/javascripts/luca-ui-spec.coffee +2 -0
  26. data/assets/javascripts/luca-ui.coffee +3 -0
  27. data/assets/javascripts/sandbox/collections/sample.coffee +0 -0
  28. data/assets/javascripts/sandbox/config.coffee +7 -0
  29. data/assets/javascripts/sandbox/sandbox.coffee +16 -0
  30. data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +33 -0
  31. data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +48 -0
  32. data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +24 -0
  33. data/assets/javascripts/sandbox/templates/features/introduction.luca +11 -0
  34. data/assets/javascripts/sandbox/templates/features/view_helpers.luca +43 -0
  35. data/assets/javascripts/sandbox/templates/navigation.luca +8 -0
  36. data/assets/javascripts/sandbox/views/form_demo.coffee +47 -0
  37. data/assets/javascripts/sandbox/views/grid_demo.coffee +23 -0
  38. data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +1 -0
  39. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +28 -0
  40. data/assets/javascripts/sandbox.coffee +4 -0
  41. data/assets/javascripts/spec-dependencies.coffee +4 -0
  42. data/assets/stylesheets/bootstrap-responsive.min.css +3 -0
  43. data/assets/stylesheets/bootstrap.min.css +610 -0
  44. data/assets/stylesheets/jasmine.css +166 -0
  45. data/assets/stylesheets/luca-ui-bootstrap.css +5 -0
  46. data/assets/stylesheets/luca-ui-spec.css +3 -0
  47. data/assets/stylesheets/luca-ui.css +3 -0
  48. data/assets/stylesheets/prettify.css +40 -0
  49. data/assets/stylesheets/sandbox/sandbox.scss +4 -0
  50. data/assets/stylesheets/sandbox.css +3 -0
  51. data/config.ru +11 -0
  52. data/lib/luca/command_line.rb +69 -0
  53. data/lib/luca/rails/engine.rb +12 -0
  54. data/lib/luca/rails/version.rb +6 -0
  55. data/lib/luca/rails.rb +9 -0
  56. data/lib/luca/template.rb +51 -0
  57. data/lib/luca/test_harness.rb +106 -0
  58. data/lib/luca.rb +1 -0
  59. data/lib/sprockets/luca_template.rb +49 -0
  60. data/lib/templates/spec_manifest_javascripts.erb +7 -0
  61. data/lib/templates/spec_manifest_stylesheets.erb +11 -0
  62. data/luca.gemspec +26 -0
  63. data/public/jasmine/index.html +26 -0
  64. data/public/sandbox/api.js +1 -0
  65. data/spec/components/application_spec.coffee +0 -0
  66. data/spec/components/collection_loader_view_spec.coffee +0 -0
  67. data/spec/components/controller_spec.coffee +0 -0
  68. data/spec/components/form_view_spec.coffee +13 -0
  69. data/spec/components/grid_view_spec.coffee +0 -0
  70. data/spec/components/record_manager_spec.coffee +0 -0
  71. data/spec/components/template_spec.coffee +0 -0
  72. data/spec/containers/card_view_spec.coffee +1 -0
  73. data/spec/containers/column_view_spec.coffee +0 -0
  74. data/spec/containers/modal_view_spec.coffee +0 -0
  75. data/spec/containers/panel_view_spec.coffee +0 -0
  76. data/spec/containers/split_view_spec.coffee +0 -0
  77. data/spec/containers/tab_view_spec.coffee +0 -0
  78. data/spec/containers/viewport_spec.coffee +0 -0
  79. data/spec/core/collection_spec.coffee +215 -0
  80. data/spec/core/container_spec.coffee +0 -0
  81. data/spec/core/field_spec.coffee +0 -0
  82. data/spec/core/observer_spec.coffee +0 -0
  83. data/spec/core/view_spec.coffee +87 -0
  84. data/spec/framework_spec.coffee +48 -0
  85. data/spec/helper.coffee +120 -0
  86. data/spec/managers/collection_manager_spec.coffee +95 -0
  87. data/spec/managers/socket_manager_spec.coffee +0 -0
  88. data/src/components/application.coffee +83 -0
  89. data/src/components/base_toolbar.coffee +16 -0
  90. data/src/components/collection_loader_view.coffee +37 -0
  91. data/src/components/controller.coffee +41 -0
  92. data/src/components/fields/button_field.coffee +40 -0
  93. data/src/components/fields/checkbox_field.coffee +41 -0
  94. data/src/components/fields/file_upload_field.coffee +15 -0
  95. data/src/components/fields/hidden_field.coffee +18 -0
  96. data/src/components/fields/select_field.coffee +100 -0
  97. data/src/components/fields/text_area_field.coffee +43 -0
  98. data/src/components/fields/text_field.coffee +42 -0
  99. data/src/components/fields/type_ahead_field.coffee +10 -0
  100. data/src/components/form_button_toolbar.coffee +26 -0
  101. data/src/components/form_view.coffee +205 -0
  102. data/src/components/grid_view.coffee +208 -0
  103. data/src/components/record_manager.coffee +215 -0
  104. data/src/components/router.coffee +34 -0
  105. data/src/components/template.coffee +19 -0
  106. data/src/containers/card_view.coffee +89 -0
  107. data/src/containers/column_view.coffee +48 -0
  108. data/src/containers/modal_view.coffee +85 -0
  109. data/src/containers/panel_view.coffee +24 -0
  110. data/src/containers/split_view.coffee +12 -0
  111. data/src/containers/tab_view.coffee +77 -0
  112. data/src/containers/viewport.coffee +16 -0
  113. data/src/core/collection.coffee +319 -0
  114. data/src/core/container.coffee +256 -0
  115. data/src/core/field.coffee +68 -0
  116. data/src/core/observer.coffee +17 -0
  117. data/src/core/view.coffee +190 -0
  118. data/src/framework.coffee +110 -0
  119. data/src/index.coffee +255 -0
  120. data/src/managers/collection_manager.coffee +168 -0
  121. data/src/managers/socket_manager.coffee +54 -0
  122. data/src/modules/deferrable.coffee +18 -0
  123. data/src/modules/local_storage.coffee +50 -0
  124. data/src/stylesheets/base.scss +78 -0
  125. data/src/stylesheets/components/form_view.scss +54 -0
  126. data/src/stylesheets/components/grid_view.scss +111 -0
  127. data/src/stylesheets/components/toolbar.scss +15 -0
  128. data/src/stylesheets/containers/container.scss +7 -0
  129. data/src/stylesheets/containers/modal_view.scss +0 -0
  130. data/src/stylesheets/containers/tab_view.scss +33 -0
  131. data/src/stylesheets/normalize.scss +430 -0
  132. data/src/templates/components/bootstrap_form_controls.luca +7 -0
  133. data/src/templates/components/collection_loader_view.luca +5 -0
  134. data/src/templates/components/form_view.luca +15 -0
  135. data/src/templates/components/grid_view.luca +9 -0
  136. data/src/templates/components/grid_view_empty_text.luca +3 -0
  137. data/src/templates/containers/basic.luca +1 -0
  138. data/src/templates/containers/tab_selector_container.luca +8 -0
  139. data/src/templates/containers/tab_view.luca +1 -0
  140. data/src/templates/containers/toolbar_wrapper.luca +1 -0
  141. data/src/templates/fields/button_field.luca +2 -0
  142. data/src/templates/fields/button_field_link.luca +5 -0
  143. data/src/templates/fields/checkbox_field.luca +9 -0
  144. data/src/templates/fields/file_upload_field.luca +8 -0
  145. data/src/templates/fields/hidden_field.luca +1 -0
  146. data/src/templates/fields/select_field.luca +7 -0
  147. data/src/templates/fields/text_area_field.luca +8 -0
  148. data/src/templates/fields/text_field.luca +13 -0
  149. data/src/templates/sample/contents.luca +1 -0
  150. data/src/templates/sample/welcome.luca +1 -0
  151. data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
  152. data/vendor/assets/images/glyphicons-halflings.png +0 -0
  153. data/vendor/assets/javascripts/luca-spec-dependencies.js +6135 -0
  154. data/vendor/assets/javascripts/luca-ui-base.js +1527 -0
  155. data/vendor/assets/javascripts/luca-ui-spec.js +3654 -0
  156. data/vendor/assets/javascripts/luca-ui.js +2763 -0
  157. data/vendor/assets/luca-ui/base.css +85 -0
  158. data/vendor/assets/luca-ui/components/application.js +91 -0
  159. data/vendor/assets/luca-ui/components/base_toolbar.js +23 -0
  160. data/vendor/assets/luca-ui/components/controller.js +38 -0
  161. data/vendor/assets/luca-ui/components/fields/button_field.js +45 -0
  162. data/vendor/assets/luca-ui/components/fields/checkbox_field.js +43 -0
  163. data/vendor/assets/luca-ui/components/fields/file_upload_field.js +20 -0
  164. data/vendor/assets/luca-ui/components/fields/hidden_field.js +20 -0
  165. data/vendor/assets/luca-ui/components/fields/select_field.js +97 -0
  166. data/vendor/assets/luca-ui/components/fields/text_area_field.js +48 -0
  167. data/vendor/assets/luca-ui/components/fields/text_field.js +46 -0
  168. data/vendor/assets/luca-ui/components/fields/type_ahead_field.js +13 -0
  169. data/vendor/assets/luca-ui/components/form_button_toolbar.js +32 -0
  170. data/vendor/assets/luca-ui/components/form_view.css +32 -0
  171. data/vendor/assets/luca-ui/components/form_view.js +207 -0
  172. data/vendor/assets/luca-ui/components/grid_view.css +76 -0
  173. data/vendor/assets/luca-ui/components/grid_view.js +202 -0
  174. data/vendor/assets/luca-ui/components/record_manager.js +207 -0
  175. data/vendor/assets/luca-ui/components/router.js +36 -0
  176. data/vendor/assets/luca-ui/components/template.js +26 -0
  177. data/vendor/assets/luca-ui/components/toolbar.css +11 -0
  178. data/vendor/assets/luca-ui/containers/card_view.js +98 -0
  179. data/vendor/assets/luca-ui/containers/column_view.js +52 -0
  180. data/vendor/assets/luca-ui/containers/container.css +3 -0
  181. data/vendor/assets/luca-ui/containers/modal_view.css +0 -0
  182. data/vendor/assets/luca-ui/containers/modal_view.js +87 -0
  183. data/vendor/assets/luca-ui/containers/panel_view.js +34 -0
  184. data/vendor/assets/luca-ui/containers/split_view.js +13 -0
  185. data/vendor/assets/luca-ui/containers/tab_view.css +16 -0
  186. data/vendor/assets/luca-ui/containers/tab_view.js +80 -0
  187. data/vendor/assets/luca-ui/containers/viewport.js +18 -0
  188. data/vendor/assets/luca-ui/core/collection.js +221 -0
  189. data/vendor/assets/luca-ui/core/container.js +205 -0
  190. data/vendor/assets/luca-ui/core/field.js +59 -0
  191. data/vendor/assets/luca-ui/core/observer.js +42 -0
  192. data/vendor/assets/luca-ui/core/view.js +127 -0
  193. data/vendor/assets/luca-ui/framework.js +110 -0
  194. data/vendor/assets/luca-ui/index.js +5 -0
  195. data/vendor/assets/luca-ui/managers/collection_manager.js +98 -0
  196. data/vendor/assets/luca-ui/managers/socket_manager.js +52 -0
  197. data/vendor/assets/luca-ui/modules/deferrable.js +21 -0
  198. data/vendor/assets/luca-ui/modules/local_storage.js +81 -0
  199. data/vendor/assets/luca-ui/normalize.css +359 -0
  200. data/vendor/assets/luca-ui/stylesheets/base.css +85 -0
  201. data/vendor/assets/luca-ui/stylesheets/components/form_view.css +32 -0
  202. data/vendor/assets/luca-ui/stylesheets/components/grid_view.css +76 -0
  203. data/vendor/assets/luca-ui/stylesheets/components/toolbar.css +11 -0
  204. data/vendor/assets/luca-ui/stylesheets/containers/container.css +3 -0
  205. data/vendor/assets/luca-ui/stylesheets/containers/modal_view.css +0 -0
  206. data/vendor/assets/luca-ui/stylesheets/containers/tab_view.css +16 -0
  207. data/vendor/assets/luca-ui/stylesheets/normalize.css +359 -0
  208. data/vendor/assets/luca-ui/templates/components/bootstrap_form_controls.js +4 -0
  209. data/vendor/assets/luca-ui/templates/components/form_view.js +4 -0
  210. data/vendor/assets/luca-ui/templates/components/grid_view.js +4 -0
  211. data/vendor/assets/luca-ui/templates/components/grid_view_empty_text.js +4 -0
  212. data/vendor/assets/luca-ui/templates/containers/basic.js +4 -0
  213. data/vendor/assets/luca-ui/templates/containers/tab_selector_container.js +4 -0
  214. data/vendor/assets/luca-ui/templates/containers/tab_view.js +4 -0
  215. data/vendor/assets/luca-ui/templates/containers/toolbar_wrapper.js +4 -0
  216. data/vendor/assets/luca-ui/templates/fields/button_field.js +4 -0
  217. data/vendor/assets/luca-ui/templates/fields/button_field_link.js +4 -0
  218. data/vendor/assets/luca-ui/templates/fields/checkbox_field.js +4 -0
  219. data/vendor/assets/luca-ui/templates/fields/file_upload_field.js +4 -0
  220. data/vendor/assets/luca-ui/templates/fields/hidden_field.js +4 -0
  221. data/vendor/assets/luca-ui/templates/fields/select_field.js +4 -0
  222. data/vendor/assets/luca-ui/templates/fields/text_area_field.js +4 -0
  223. data/vendor/assets/luca-ui/templates/fields/text_field.js +4 -0
  224. data/vendor/assets/luca-ui/templates/sample/contents.js +4 -0
  225. data/vendor/assets/luca-ui/templates/sample/welcome.js +4 -0
  226. data/vendor/assets/stylesheets/luca-spec-dependencies.css +166 -0
  227. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +1201 -0
  228. data/vendor/assets/stylesheets/luca-ui-spec.css +586 -0
  229. data/vendor/assets/stylesheets/luca-ui.css +586 -0
  230. data/views/index.erb +20 -0
  231. data/views/jasmine.erb +22 -0
  232. data/views/spec_harness.erb +29 -0
  233. metadata +361 -0
@@ -0,0 +1,207 @@
1
+ (function() {
2
+
3
+ Luca.components.FormView = Luca.core.Container.extend({
4
+ tagName: 'form',
5
+ className: 'luca-ui-form-view',
6
+ hooks: ["before:submit", "before:reset", "before:load", "before:load:new", "before:load:existing", "after:submit", "after:reset", "after:load", "after:load:new", "after:load:existing", "after:submit:success", "after:submit:fatal_error", "after:submit:error"],
7
+ events: {
8
+ "click .submit-button": "submitHandler",
9
+ "click .reset-button": "resetHandler"
10
+ },
11
+ toolbar: true,
12
+ initialize: function(options) {
13
+ this.options = options != null ? options : {};
14
+ Luca.core.Container.prototype.initialize.apply(this, arguments);
15
+ _.bindAll(this, "submitHandler", "resetHandler", "renderToolbars");
16
+ this.state || (this.state = new Backbone.Model);
17
+ this.setupHooks(this.hooks);
18
+ this.legend || (this.legend = "");
19
+ this.configureToolbars();
20
+ return this.applyStyles();
21
+ },
22
+ addBootstrapFormControls: function() {
23
+ var _this = this;
24
+ return this.bind("after:render", function() {
25
+ var el;
26
+ el = _this.$('.toolbar-container.bottom');
27
+ el.addClass('form-controls');
28
+ return el.html(_this.formControlsTemplate || Luca.templates["components/bootstrap_form_controls"](_this));
29
+ });
30
+ },
31
+ applyStyles: function() {
32
+ if (Luca.enableBootstrap) this.applyBootstrapStyles();
33
+ if (this.labelAlign) this.$el.addClass("label-align-" + this.labelAlign);
34
+ if (this.fieldLayoutClass) return this.$el.addClass(this.fieldLayoutClass);
35
+ },
36
+ applyBootstrapStyles: function() {
37
+ if (this.labelAlign === "left") this.inlineForm = true;
38
+ if (this.well) this.$el.addClass('well');
39
+ if (this.searchForm) this.$el.addClass('form-search');
40
+ if (this.horizontalForm) this.$el.addClass('form-horizontal');
41
+ if (this.inlineForm) return this.$el.addClass('form-inline');
42
+ },
43
+ configureToolbars: function() {
44
+ if (Luca.enableBootstrap && this.toolbar === true) {
45
+ return this.addBootstrapFormControls();
46
+ }
47
+ if (this.toolbar === true) {
48
+ this.toolbars = [
49
+ {
50
+ ctype: 'form_button_toolbar',
51
+ includeReset: true,
52
+ position: 'bottom'
53
+ }
54
+ ];
55
+ }
56
+ if (this.toolbars && this.toolbars.length) {
57
+ return this.bind("after:render", _.once(this.renderToolbars));
58
+ }
59
+ },
60
+ resetHandler: function(e) {
61
+ var me, my;
62
+ me = my = $(e.currentTarget);
63
+ this.trigger("before:reset", this);
64
+ this.reset();
65
+ return this.trigger("after:reset", this);
66
+ },
67
+ submitHandler: function(e) {
68
+ var me, my;
69
+ me = my = $(e.currentTarget);
70
+ this.trigger("before:submit", this);
71
+ return this.submit();
72
+ },
73
+ beforeLayout: function() {
74
+ var _ref;
75
+ if ((_ref = Luca.core.Container.prototype.beforeLayout) != null) {
76
+ _ref.apply(this, arguments);
77
+ }
78
+ return this.$el.html(Luca.templates["components/form_view"](this));
79
+ },
80
+ prepareComponents: function() {
81
+ var container;
82
+ container = $('.form-view-body', this.el);
83
+ return _(this.components).each(function(component) {
84
+ return component.container = container;
85
+ });
86
+ },
87
+ render: function() {
88
+ return $(this.container).append(this.$el);
89
+ },
90
+ wrapper: function() {
91
+ return this.$el.parents('.luca-ui-form-view-wrapper');
92
+ },
93
+ toolbarContainers: function(position) {
94
+ if (position == null) position = "bottom";
95
+ return $(".toolbar-container." + position, this.wrapper()).first();
96
+ },
97
+ renderToolbars: function() {
98
+ var _this = this;
99
+ return _(this.toolbars).each(function(toolbar) {
100
+ toolbar.container = $("#" + _this.cid + "-" + toolbar.position + "-toolbar-container");
101
+ toolbar = Luca.util.lazyComponent(toolbar);
102
+ return toolbar.render();
103
+ });
104
+ },
105
+ getField: function(name) {
106
+ return _(this.getFields('name', name)).first();
107
+ },
108
+ getFields: function(attr, value) {
109
+ var fields;
110
+ fields = this.select("isField", true, true);
111
+ if (fields.length > 0 && attr && value) {
112
+ fields = _(fields).select(function(field) {
113
+ var property, propvalue;
114
+ property = field[attr];
115
+ if (property == null) return false;
116
+ propvalue = _.isFunction(property) ? property() : property;
117
+ return value === propvalue;
118
+ });
119
+ }
120
+ return fields;
121
+ },
122
+ loadModel: function(current_model) {
123
+ var event, fields, form,
124
+ _this = this;
125
+ this.current_model = current_model;
126
+ form = this;
127
+ fields = this.getFields();
128
+ this.trigger("before:load", this, this.current_model);
129
+ if (this.current_model) {
130
+ event = "before:load:" + (this.current_model.isNew() ? "new" : "existing");
131
+ this.trigger(event, this, this.current_model);
132
+ }
133
+ _(fields).each(function(field) {
134
+ var field_name, value;
135
+ field_name = field.input_name || field.name;
136
+ value = _.isFunction(_this.current_model[field_name]) ? _this.current_model[field_name].apply(_this, form) : _this.current_model.get(field_name);
137
+ if (field.readOnly !== true) {
138
+ return field != null ? field.setValue(value) : void 0;
139
+ }
140
+ });
141
+ this.trigger("after:load", this, this.current_model);
142
+ if (this.current_model) {
143
+ return this.trigger("after:load:" + (this.current_model.isNew() ? "new" : "existing"), this, this.current_model);
144
+ }
145
+ },
146
+ reset: function() {
147
+ return this.loadModel(this.current_model);
148
+ },
149
+ clear: function() {
150
+ var _this = this;
151
+ this.current_model = this.defaultModel != null ? this.defaultModel() : void 0;
152
+ return _(this.getFields()).each(function(field) {
153
+ try {
154
+ return field.setValue('');
155
+ } catch (e) {
156
+ return console.log("Error Clearing", _this, field);
157
+ }
158
+ });
159
+ },
160
+ getValues: function(reject_blank, skip_buttons) {
161
+ if (reject_blank == null) reject_blank = false;
162
+ if (skip_buttons == null) skip_buttons = true;
163
+ return _(this.getFields()).inject(function(memo, field) {
164
+ var skip, value;
165
+ value = field.getValue();
166
+ skip = false;
167
+ if (skip_buttons && field.ctype === "button_field") skip = true;
168
+ if (reject_blank && _.isBlank(value)) skip = true;
169
+ if (field.input_name === "id" && _.isBlank(value)) skip = true;
170
+ if (!skip) memo[field.input_name || name] = value;
171
+ return memo;
172
+ }, {});
173
+ },
174
+ submit_success_handler: function(model, response, xhr) {
175
+ this.trigger("after:submit", this, model, response);
176
+ if (response && response.success) {
177
+ return this.trigger("after:submit:success", this, model, response);
178
+ } else {
179
+ return this.trigger("after:submit:error", this, model, response);
180
+ }
181
+ },
182
+ submit_fatal_error_handler: function() {
183
+ this.trigger.apply(["after:submit", this].concat(arguments));
184
+ return this.trigger.apply(["after:submit:fatal_error", this].concat(arguments));
185
+ },
186
+ submit: function(save, saveOptions) {
187
+ if (save == null) save = true;
188
+ if (saveOptions == null) saveOptions = {};
189
+ _.bindAll(this, "submit_success_handler", "submit_fatal_error_handler");
190
+ saveOptions.success || (saveOptions.success = this.submit_success_handler);
191
+ saveOptions.error || (saveOptions.error = this.submit_fatal_error_handler);
192
+ this.current_model.set(this.getValues());
193
+ if (!save) return;
194
+ return this.current_model.save(this.current_model.toJSON(), saveOptions);
195
+ },
196
+ currentModel: function() {
197
+ return this.current_model;
198
+ },
199
+ setLegend: function(legend) {
200
+ this.legend = legend;
201
+ return $('fieldset legend', this.el).first().html(this.legend);
202
+ }
203
+ });
204
+
205
+ Luca.register('form_view', 'Luca.components.FormView');
206
+
207
+ }).call(this);
@@ -0,0 +1,76 @@
1
+ .scrollable-grid-view {
2
+ /* define height and width of scrollable area. Add 16px to width for scrollbar */
3
+ /* Reset overflow value to hidden for all non-IE browsers. */
4
+ /* define width of table. IE browsers only */
5
+ /* define width of table. Add 16px to width for scrollbar. */
6
+ /* All other non-IE browsers. */
7
+ /* set table header to a fixed position. WinIE 6.x only */
8
+ /* In WinIE 6.x, any element with a position property set to relative and is a child of */
9
+ /* an element that has an overflow property set, the relative value translates into fixed. */
10
+ /* Ex: parent element DIV with a class of tableContainer has an overflow property set to auto */
11
+ /* set THEAD element to have block level attributes. All other non-IE browsers */
12
+ /* this enables overflow to work on TBODY element. All other non-IE, non-Mozilla browsers */
13
+ /* make the TH elements pretty */
14
+ /* make the A elements pretty. makes for nice clickable headers */
15
+ /* make the A elements pretty. makes for nice clickable headers */
16
+ /* WARNING: swapping the background on hover may cause problems in WinIE 6.x */
17
+ /* define the table content to be scrollable */
18
+ /* set TBODY element to have block level attributes. All other non-IE browsers */
19
+ /* this enables overflow to work on TBODY element. All other non-IE, non-Mozilla browsers */
20
+ /* induced side effect is that child TDs no longer accept width: auto */
21
+ /* define width of TH elements: 1st, 2nd, and 3rd respectively. */
22
+ /* Add 16px to last TH for scrollbar padding. All other non-IE browsers. */
23
+ /* http://www.w3.org/TR/REC-CSS2/selector.html#adjacent-selectors */
24
+ /* define width of TD elements: 1st, 2nd, and 3rd respectively. */
25
+ /* All other non-IE browsers. */
26
+ /* http://www.w3.org/TR/REC-CSS2/selector.html#adjacent-selectors */ }
27
+ .scrollable-grid-view .grid-view-body {
28
+ clear: both;
29
+ overflow: auto; }
30
+ .scrollable-grid-view .grid-view-body {
31
+ overflow: hidden; }
32
+ .scrollable-grid-view .grid-view-body .empty-text-wrapper {
33
+ display: block;
34
+ margin: 10px auto;
35
+ width: 30%;
36
+ padding: 50px;
37
+ text-align: center; }
38
+ .scrollable-grid-view .grid-view-body .empty-text-wrapper p {
39
+ color: #aaa; }
40
+ .scrollable-grid-view thead.fixed tr {
41
+ position: relative; }
42
+ .scrollable-grid-view thead.fixed tr {
43
+ display: block; }
44
+ .scrollable-grid-view thead.fixed th {
45
+ font-weight: bold;
46
+ text-align: left; }
47
+ .scrollable-grid-view thead.fixed a, .scrollable-grid-view thead.fixed a:link, .scrollable-grid-view thead.fixed a:visited {
48
+ color: #FFF;
49
+ display: block;
50
+ text-decoration: none;
51
+ width: 100%; }
52
+ .scrollable-grid-view thead.fixed a:hover {
53
+ color: #FFF;
54
+ display: block;
55
+ text-decoration: underline;
56
+ width: 100%; }
57
+ .scrollable-grid-view tbody.scrollable {
58
+ display: block;
59
+ overflow: auto;
60
+ width: 100%; }
61
+ .scrollable-grid-view thead.fixed th {
62
+ padding: 5px; }
63
+ .scrollable-grid-view tbody.scrollable td {
64
+ padding: 5px; }
65
+
66
+ .grid-view-footer .toolbar-container {
67
+ float: left;
68
+ width: 100%;
69
+ clear: both;
70
+ display: block; }
71
+ .grid-view-footer .toolbar-container .luca-ui-toolbar {
72
+ display: block;
73
+ float: right;
74
+ clear: right; }
75
+ .grid-view-footer .toolbar-container .luca-ui-toolbar .luca-ui-field {
76
+ float: left; }
@@ -0,0 +1,202 @@
1
+ (function() {
2
+
3
+ Luca.components.GridView = Luca.View.extend({
4
+ events: {
5
+ "dblclick .grid-view-row": "double_click_handler",
6
+ "click .grid-view-row": "click_handler"
7
+ },
8
+ className: 'luca-ui-grid-view',
9
+ scrollable: true,
10
+ emptyText: 'No Results To display',
11
+ tableStyle: 'striped',
12
+ hooks: ["before:grid:render", "before:render:header", "before:render:row", "after:grid:render", "row:double:click", "row:click", "after:collection:load"],
13
+ initialize: function(options) {
14
+ var _this = this;
15
+ this.options = options != null ? options : {};
16
+ _.extend(this, this.options);
17
+ _.extend(this, Luca.modules.Deferrable);
18
+ Luca.View.prototype.initialize.apply(this, arguments);
19
+ _.bindAll(this, "double_click_handler", "click_handler");
20
+ this.configure_collection();
21
+ return this.collection.bind("reset", function(collection) {
22
+ _this.refresh();
23
+ return _this.trigger("after:collection:load", collection);
24
+ });
25
+ },
26
+ beforeRender: function() {
27
+ var _ref,
28
+ _this = this;
29
+ this.trigger("before:grid:render", this);
30
+ if (this.scrollable) this.$el.addClass('scrollable-grid-view');
31
+ this.$el.html(Luca.templates["components/grid_view"]());
32
+ this.table = $('table.luca-ui-grid-view', this.el);
33
+ this.header = $("thead", this.table);
34
+ this.body = $("tbody", this.table);
35
+ this.footer = $("tfoot", this.table);
36
+ if (Luca.enableBootstrap) this.table.addClass('table');
37
+ _((_ref = this.tableStyle) != null ? _ref.split(" ") : void 0).each(function(style) {
38
+ return _this.table.addClass("table-" + style);
39
+ });
40
+ if (this.scrollable) this.setDimensions();
41
+ this.renderHeader();
42
+ this.emptyMessage();
43
+ this.renderToolbars();
44
+ return $(this.container).append(this.$el);
45
+ },
46
+ toolbarContainers: function(position) {
47
+ if (position == null) position = "bottom";
48
+ return $(".toolbar-container." + position, this.el);
49
+ },
50
+ renderToolbars: function() {
51
+ var _this = this;
52
+ return _(this.toolbars).each(function(toolbar) {
53
+ toolbar = Luca.util.lazyComponent(toolbar);
54
+ toolbar.container = _this.toolbarContainers(toolbar.position);
55
+ return toolbar.render();
56
+ });
57
+ },
58
+ setDimensions: function(offset) {
59
+ var _this = this;
60
+ this.height || (this.height = 285);
61
+ $('.grid-view-body', this.el).height(this.height);
62
+ $('tbody.scrollable', this.el).height(this.height - 23);
63
+ this.container_width = (function() {
64
+ return $(_this.container).width();
65
+ })();
66
+ this.width = this.container_width > 0 ? this.container_width : 756;
67
+ $('.grid-view-body', this.el).width(this.width);
68
+ $('.grid-view-body table', this.el).width(this.width);
69
+ return this.setDefaultColumnWidths();
70
+ },
71
+ resize: function(newWidth) {
72
+ var difference, distribution,
73
+ _this = this;
74
+ difference = newWidth - this.width;
75
+ this.width = newWidth;
76
+ $('.grid-view-body', this.el).width(this.width);
77
+ $('.grid-view-body table', this.el).width(this.width);
78
+ if (this.columns.length > 0) {
79
+ distribution = difference / this.columns.length;
80
+ return _(this.columns).each(function(col, index) {
81
+ var column;
82
+ column = $(".column-" + index, _this.el);
83
+ return column.width(col.width = col.width + distribution);
84
+ });
85
+ }
86
+ },
87
+ padLastColumn: function() {
88
+ var configured_column_widths, unused_width;
89
+ configured_column_widths = _(this.columns).inject(function(sum, column) {
90
+ return sum = column.width + sum;
91
+ }, 0);
92
+ unused_width = this.width - configured_column_widths;
93
+ if (unused_width > 0) return this.lastColumn().width += unused_width;
94
+ },
95
+ setDefaultColumnWidths: function() {
96
+ var default_column_width;
97
+ default_column_width = this.columns.length > 0 ? this.width / this.columns.length : 200;
98
+ _(this.columns).each(function(column) {
99
+ return parseInt(column.width || (column.width = default_column_width));
100
+ });
101
+ return this.padLastColumn();
102
+ },
103
+ lastColumn: function() {
104
+ return this.columns[this.columns.length - 1];
105
+ },
106
+ afterRender: function() {
107
+ this.refresh();
108
+ return this.trigger("after:grid:render", this);
109
+ },
110
+ emptyMessage: function(text) {
111
+ if (text == null) text = "";
112
+ text || (text = this.emptyText);
113
+ this.body.html('');
114
+ return this.body.append(Luca.templates["components/grid_view_empty_text"]({
115
+ colspan: this.columns.length,
116
+ text: text
117
+ }));
118
+ },
119
+ refresh: function() {
120
+ var _this = this;
121
+ this.body.html('');
122
+ this.collection.each(function(model, index) {
123
+ return _this.render_row.apply(_this, [model, index]);
124
+ });
125
+ if (this.collection.models.length === 0) return this.emptyMessage();
126
+ },
127
+ ifLoaded: function(fn, scope) {
128
+ scope || (scope = this);
129
+ fn || (fn = function() {
130
+ return true;
131
+ });
132
+ return this.collection.ifLoaded(fn, scope);
133
+ },
134
+ applyFilter: function(values, options) {
135
+ if (options == null) {
136
+ options = {
137
+ auto: true,
138
+ refresh: true
139
+ };
140
+ }
141
+ return this.collection.applyFilter(values, options);
142
+ },
143
+ renderHeader: function() {
144
+ var headers,
145
+ _this = this;
146
+ this.trigger("before:render:header");
147
+ headers = _(this.columns).map(function(column, column_index) {
148
+ var style;
149
+ style = column.width ? "width:" + column.width + "px;" : "";
150
+ return "<th style='" + style + "' class='column-" + column_index + "'>" + column.header + "</th>";
151
+ });
152
+ return this.header.append("<tr>" + headers + "</tr>");
153
+ },
154
+ render_row: function(row, row_index) {
155
+ var alt_class, cells, model_id, _ref,
156
+ _this = this;
157
+ model_id = (row != null ? row.get : void 0) && (row != null ? row.attributes : void 0) ? row.get('id') : '';
158
+ this.trigger("before:render:row", row, row_index);
159
+ cells = _(this.columns).map(function(column, col_index) {
160
+ var display, style, value;
161
+ value = _this.cell_renderer(row, column, col_index);
162
+ style = column.width ? "width:" + column.width + "px;" : "";
163
+ display = _.isUndefined(value) ? "" : value;
164
+ return "<td style='" + style + "' class='column-" + col_index + "'>" + display + "</td>";
165
+ });
166
+ if (this.alternateRowClasses) {
167
+ alt_class = row_index % 2 === 0 ? "even" : "odd";
168
+ }
169
+ return (_ref = this.body) != null ? _ref.append("<tr data-record-id='" + model_id + "' data-row-index='" + row_index + "' class='grid-view-row " + alt_class + "' id='row-" + row_index + "'>" + cells + "</tr>") : void 0;
170
+ },
171
+ cell_renderer: function(row, column, columnIndex) {
172
+ var source;
173
+ if (_.isFunction(column.renderer)) {
174
+ return column.renderer.apply(this, [row, column, columnIndex]);
175
+ } else if (column.data.match(/\w+\.\w+/)) {
176
+ source = row.attributes || row;
177
+ return Luca.util.nestedValue(column.data, source);
178
+ } else {
179
+ return (typeof row.get === "function" ? row.get(column.data) : void 0) || row[column.data];
180
+ }
181
+ },
182
+ double_click_handler: function(e) {
183
+ var me, my, record, rowIndex;
184
+ me = my = $(e.currentTarget);
185
+ rowIndex = my.data('row-index');
186
+ record = this.collection.at(rowIndex);
187
+ return this.trigger("row:double:click", this, record, rowIndex);
188
+ },
189
+ click_handler: function(e) {
190
+ var me, my, record, rowIndex;
191
+ me = my = $(e.currentTarget);
192
+ rowIndex = my.data('row-index');
193
+ record = this.collection.at(rowIndex);
194
+ this.trigger("row:click", this, record, rowIndex);
195
+ $('.grid-view-row', this.body).removeClass('selected-row');
196
+ return me.addClass('selected-row');
197
+ }
198
+ });
199
+
200
+ Luca.register("grid_view", "Luca.components.GridView");
201
+
202
+ }).call(this);
@@ -0,0 +1,207 @@
1
+ (function() {
2
+
3
+ Luca.components.RecordManager = Luca.containers.CardView.extend({
4
+ events: {
5
+ "click .record-manager-grid .edit-link": "edit_handler",
6
+ "click .record-manager-filter .filter-button": "filter_handler",
7
+ "click .record-manager-filter .reset-button": "reset_filter_handler",
8
+ "click .add-button": "add_handler",
9
+ "click .refresh-button": "filter_handler",
10
+ "click .back-to-search-button": "back_to_search_handler"
11
+ },
12
+ record_manager: true,
13
+ initialize: function(options) {
14
+ var _this = this;
15
+ this.options = options != null ? options : {};
16
+ Luca.containers.CardView.prototype.initialize.apply(this, arguments);
17
+ if (!this.name) throw "Record Managers must specify a name";
18
+ _.bindAll(this, "add_handler", "edit_handler", "filter_handler", "reset_filter_handler");
19
+ if (this.filterConfig) _.extend(this.components[0][0], this.filterConfig);
20
+ if (this.gridConfig) _.extend(this.components[0][1], this.gridConfig);
21
+ if (this.editorConfig) _.extend(this.components[1][0], this.editorConfig);
22
+ return this.bind("after:card:switch", function() {
23
+ if (_this.activeCard === 0) _this.trigger("activation:search", _this);
24
+ if (_this.activeCard === 1) {
25
+ return _this.trigger("activation:editor", _this);
26
+ }
27
+ });
28
+ },
29
+ components: [
30
+ {
31
+ ctype: 'split_view',
32
+ relayFirstActivation: true,
33
+ components: [
34
+ {
35
+ ctype: 'form_view'
36
+ }, {
37
+ ctype: 'grid_view'
38
+ }
39
+ ]
40
+ }, {
41
+ ctype: 'form_view'
42
+ }
43
+ ],
44
+ getSearch: function(activate, reset) {
45
+ if (activate == null) activate = false;
46
+ if (reset == null) reset = true;
47
+ if (activate === true) this.activate(0);
48
+ if (reset === true) this.getEditor().clear();
49
+ return _.first(this.components);
50
+ },
51
+ getFilter: function() {
52
+ return _.first(this.getSearch().components);
53
+ },
54
+ getGrid: function() {
55
+ return _.last(this.getSearch().components);
56
+ },
57
+ getCollection: function() {
58
+ return this.getGrid().collection;
59
+ },
60
+ getEditor: function(activate, reset) {
61
+ var _this = this;
62
+ if (activate == null) activate = false;
63
+ if (reset == null) reset = false;
64
+ if (activate === true) {
65
+ this.activate(1, function(activator, previous, current) {
66
+ return current.reset();
67
+ });
68
+ }
69
+ return _.last(this.components);
70
+ },
71
+ beforeRender: function() {
72
+ var _ref;
73
+ this.$el.addClass("" + this.resource + "-manager");
74
+ if ((_ref = Luca.containers.CardView.prototype.beforeRender) != null) {
75
+ _ref.apply(this, arguments);
76
+ }
77
+ this.$el.addClass("" + this.resource + " record-manager");
78
+ this.$el.data('resource', this.resource);
79
+ $(this.getGrid().el).addClass("" + this.resource + " record-manager-grid");
80
+ $(this.getFilter().el).addClass("" + this.resource + " record-manager-filter");
81
+ return $(this.getEditor().el).addClass("" + this.resource + " record-manager-editor");
82
+ },
83
+ afterRender: function() {
84
+ var collection, editor, filter, grid, manager, _ref,
85
+ _this = this;
86
+ if ((_ref = Luca.containers.CardView.prototype.afterRender) != null) {
87
+ _ref.apply(this, arguments);
88
+ }
89
+ manager = this;
90
+ grid = this.getGrid();
91
+ filter = this.getFilter();
92
+ editor = this.getEditor();
93
+ collection = this.getCollection();
94
+ grid.bind("row:double:click", function(grid, model, index) {
95
+ manager.getEditor(true);
96
+ return editor.loadModel(model);
97
+ });
98
+ editor.bind("before:submit", function() {
99
+ $('.form-view-flash-container', _this.el).html('');
100
+ return $('.form-view-body', _this.el).spin("large");
101
+ });
102
+ editor.bind("after:submit", function() {
103
+ return $('.form-view-body', _this.el).spin(false);
104
+ });
105
+ editor.bind("after:submit:fatal_error", function() {
106
+ $('.form-view-flash-container', _this.el).append("<li class='error'>There was an internal server error saving this record. Please contact developers@benchprep.com to report this error.</li>");
107
+ return $('.form-view-body', _this.el).spin(false);
108
+ });
109
+ editor.bind("after:submit:error", function(form, model, response) {
110
+ return _(response.errors).each(function(error) {
111
+ return $('.form-view-flash-container', _this.el).append("<li class='error'>" + error + "</li>");
112
+ });
113
+ });
114
+ editor.bind("after:submit:success", function(form, model, response) {
115
+ $('.form-view-flash-container', _this.el).append("<li class='success'>Successfully Saved Record</li>");
116
+ model.set(response.result);
117
+ form.loadModel(model);
118
+ grid.refresh();
119
+ return _.delay(function() {
120
+ $('.form-view-flash-container li.success', _this.el).fadeOut(1000);
121
+ return $('.form-view-flash-container', _this.el).html('');
122
+ }, 4000);
123
+ });
124
+ return filter.eachComponent(function(component) {
125
+ try {
126
+ return component.bind("on:change", _this.filter_handler);
127
+ } catch (e) {
128
+ return;
129
+ }
130
+ });
131
+ },
132
+ firstActivation: function() {
133
+ this.getGrid().trigger("first:activation", this, this.getGrid());
134
+ return this.getFilter().trigger("first:activation", this, this.getGrid());
135
+ },
136
+ reload: function() {
137
+ var editor, filter, grid, manager;
138
+ manager = this;
139
+ grid = this.getGrid();
140
+ filter = this.getFilter();
141
+ editor = this.getEditor();
142
+ filter.clear();
143
+ return grid.applyFilter();
144
+ },
145
+ manageRecord: function(record_id) {
146
+ var model,
147
+ _this = this;
148
+ model = this.getCollection().get(record_id);
149
+ if (model) return this.loadModel(model);
150
+ console.log("Could Not Find Model, building and fetching");
151
+ model = this.buildModel();
152
+ model.set({
153
+ id: record_id
154
+ }, {
155
+ silent: true
156
+ });
157
+ return model.fetch({
158
+ success: function(model, response) {
159
+ return _this.loadModel(model);
160
+ }
161
+ });
162
+ },
163
+ loadModel: function(current_model) {
164
+ this.current_model = current_model;
165
+ this.getEditor(true).loadModel(this.current_model);
166
+ return this.trigger("model:loaded", this.current_model);
167
+ },
168
+ currentModel: function() {
169
+ return this.getEditor(false).currentModel();
170
+ },
171
+ buildModel: function() {
172
+ var collection, editor, model;
173
+ editor = this.getEditor(false);
174
+ collection = this.getCollection();
175
+ collection.add([{}], {
176
+ silent: true,
177
+ at: 0
178
+ });
179
+ return model = collection.at(0);
180
+ },
181
+ createModel: function() {
182
+ return this.loadModel(this.buildModel());
183
+ },
184
+ reset_filter_handler: function(e) {
185
+ this.getFilter().clear();
186
+ return this.getGrid().applyFilter(this.getFilter().getValues());
187
+ },
188
+ filter_handler: function(e) {
189
+ return this.getGrid().applyFilter(this.getFilter().getValues());
190
+ },
191
+ edit_handler: function(e) {
192
+ var me, model, my, record_id;
193
+ me = my = $(e.currentTarget);
194
+ record_id = my.parents('tr').data('record-id');
195
+ if (record_id) model = this.getGrid().collection.get(record_id);
196
+ return model || (model = this.getGrid().collection.at(row_index));
197
+ },
198
+ add_handler: function(e) {
199
+ var me, my, resource;
200
+ me = my = $(e.currentTarget);
201
+ return resource = my.parents('.record-manager').eq(0).data('resource');
202
+ },
203
+ destroy_handler: function(e) {},
204
+ back_to_search_handler: function() {}
205
+ });
206
+
207
+ }).call(this);