luca 0.9.42 → 0.9.65

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. data/CHANGELOG +50 -9
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +2 -0
  4. data/README.md +5 -0
  5. data/assets/javascripts/dependencies/underscore-min.js +5 -31
  6. data/lib/generators/luca/application/application_generator.rb +71 -0
  7. data/lib/generators/luca/application/templates/controller.rb +6 -0
  8. data/lib/generators/luca/application/templates/index.html.erb +7 -0
  9. data/lib/generators/luca/application/templates/index.html.haml +6 -0
  10. data/lib/generators/luca/application/templates/javascripts/application.js +28 -0
  11. data/lib/generators/luca/application/templates/javascripts/application.js.coffee +20 -0
  12. data/lib/generators/luca/application/templates/javascripts/config.js +15 -0
  13. data/lib/generators/luca/application/templates/javascripts/config.js.coffee +9 -0
  14. data/lib/generators/luca/application/templates/javascripts/dependencies.js +5 -0
  15. data/lib/generators/luca/application/templates/javascripts/dependencies.js.coffee +5 -0
  16. data/lib/generators/luca/application/templates/javascripts/index.js +9 -0
  17. data/lib/generators/luca/application/templates/javascripts/index.js.coffee +9 -0
  18. data/lib/generators/luca/application/templates/javascripts/main.js +8 -0
  19. data/lib/generators/luca/application/templates/javascripts/main.js.coffee +3 -0
  20. data/lib/generators/luca/application/templates/javascripts/main.jst.ejs +1 -0
  21. data/lib/generators/luca/application/templates/javascripts/router.js +12 -0
  22. data/lib/generators/luca/application/templates/javascripts/router.js.coffee +7 -0
  23. data/lib/luca/rails/version.rb +1 -1
  24. data/spec/components/collection_view_spec.coffee +59 -0
  25. data/spec/components/multi_collection_view_spec.coffee +5 -0
  26. data/{src/templates/components/form_alert → spec/components/pagination_control_spec.coffee} +0 -0
  27. data/spec/components/table_view_spec.coffee +17 -0
  28. data/spec/core/container_spec.coffee +127 -5
  29. data/spec/core/model_spec.coffee +21 -3
  30. data/spec/define_spec.coffee +19 -0
  31. data/spec/mixin_spec.coffee +49 -0
  32. data/spec/modules/filterable_spec.coffee +25 -0
  33. data/spec/modules/paginatable_spec.coffee +0 -0
  34. data/spec/modules/state_model_spec.coffee +0 -0
  35. data/src/components/application.coffee +52 -38
  36. data/src/components/collection_view.coffee +118 -45
  37. data/src/components/fields/checkbox_field.coffee +2 -2
  38. data/src/components/fields/file_upload_field.coffee +0 -3
  39. data/src/components/fields/hidden_field.coffee +0 -3
  40. data/src/components/fields/label_field.coffee +1 -4
  41. data/src/components/fields/select_field.coffee +6 -6
  42. data/src/components/fields/text_area_field.coffee +1 -0
  43. data/src/components/fields/text_field.coffee +4 -0
  44. data/src/components/fields/type_ahead_field.coffee +5 -9
  45. data/src/components/form_view.coffee +28 -23
  46. data/src/components/multi_collection_view.coffee +121 -0
  47. data/src/components/pagination_control.coffee +106 -0
  48. data/src/components/table_view.coffee +22 -13
  49. data/src/containers/card_view.coffee +44 -11
  50. data/src/containers/panel_toolbar.coffee +88 -82
  51. data/src/containers/tab_view.coffee +3 -3
  52. data/src/core/collection.coffee +11 -4
  53. data/src/core/container.coffee +206 -122
  54. data/src/core/field.coffee +13 -10
  55. data/src/core/model.coffee +23 -27
  56. data/src/core/registry.coffee +42 -29
  57. data/src/core/view.coffee +63 -149
  58. data/src/define.coffee +91 -19
  59. data/src/framework.coffee +11 -9
  60. data/src/managers/collection_manager.coffee +24 -8
  61. data/src/modules/application_event_bindings.coffee +19 -0
  62. data/src/modules/collection_event_bindings.coffee +26 -0
  63. data/src/modules/deferrable.coffee +3 -1
  64. data/src/modules/dom_helpers.coffee +49 -0
  65. data/src/modules/enhanced_properties.coffee +23 -0
  66. data/src/modules/filterable.coffee +82 -0
  67. data/src/modules/grid_layout.coffee +13 -1
  68. data/src/modules/{load_mask.coffee → loadmaskable.coffee} +10 -4
  69. data/src/modules/modal_view.coffee +38 -0
  70. data/src/modules/paginatable.coffee +87 -0
  71. data/src/modules/state_model.coffee +16 -0
  72. data/src/modules/templating.coffee +8 -0
  73. data/src/plugins/events.coffee +30 -2
  74. data/src/templates/components/bootstrap_form_controls.jst.ejs +10 -0
  75. data/src/templates/components/collection_loader_view.jst.ejs +6 -0
  76. data/src/templates/components/form_alert.jst.ejs +4 -0
  77. data/src/templates/components/grid_view.jst.ejs +11 -0
  78. data/src/templates/components/grid_view_empty_text.jst.ejs +3 -0
  79. data/src/templates/components/load_mask.jst.ejs +5 -0
  80. data/src/templates/components/nav_bar.jst.ejs +4 -0
  81. data/src/templates/components/pagination.jst.ejs +10 -0
  82. data/src/templates/containers/basic.jst.ejs +1 -0
  83. data/src/templates/containers/tab_selector_container.jst.ejs +12 -0
  84. data/src/templates/containers/tab_view.jst.ejs +2 -0
  85. data/src/templates/containers/toolbar_wrapper.jst.ejs +1 -0
  86. data/src/templates/fields/button_field.jst.ejs +2 -0
  87. data/src/templates/fields/button_field_link.jst.ejs +6 -0
  88. data/src/templates/fields/checkbox_array.jst.ejs +4 -0
  89. data/src/templates/fields/checkbox_array_item.jst.ejs +3 -0
  90. data/src/templates/fields/checkbox_field.jst.ejs +10 -0
  91. data/src/templates/fields/file_upload_field.jst.ejs +10 -0
  92. data/src/templates/fields/hidden_field.jst.ejs +1 -0
  93. data/src/templates/fields/select_field.jst.ejs +11 -0
  94. data/src/templates/fields/text_area_field.jst.ejs +11 -0
  95. data/src/templates/fields/text_field.jst.ejs +16 -0
  96. data/src/templates/table_view.jst.ejs +4 -0
  97. data/src/tools/console.coffee +51 -21
  98. data/src/util.coffee +17 -4
  99. data/vendor/assets/javascripts/luca-ui-base.js +5304 -0
  100. data/vendor/assets/javascripts/luca-ui-bootstrap.js +9 -0
  101. data/vendor/assets/javascripts/luca-ui-development-tools.js +52 -24
  102. data/vendor/assets/javascripts/luca-ui-development-tools.min.js +1 -1
  103. data/vendor/assets/javascripts/luca-ui-full.js +1700 -595
  104. data/vendor/assets/javascripts/luca-ui-full.min.js +7 -6
  105. data/vendor/assets/javascripts/luca-ui-spec.js +6815 -0
  106. data/vendor/assets/javascripts/luca-ui-templates.js +92 -24
  107. data/vendor/assets/javascripts/luca-ui.js +1695 -564
  108. data/vendor/assets/javascripts/luca-ui.min.js +4 -4
  109. metadata +69 -28
  110. data/src/templates/components/bootstrap_form_controls.luca +0 -7
  111. data/src/templates/components/collection_loader_view.luca +0 -5
  112. data/src/templates/components/form_alert.luca +0 -3
  113. data/src/templates/components/grid_view.luca +0 -7
  114. data/src/templates/components/grid_view_empty_text.luca +0 -3
  115. data/src/templates/components/load_mask.luca +0 -3
  116. data/src/templates/components/nav_bar.luca +0 -2
  117. data/src/templates/containers/basic.luca +0 -1
  118. data/src/templates/containers/tab_selector_container.luca +0 -8
  119. data/src/templates/containers/tab_view.luca +0 -2
  120. data/src/templates/containers/toolbar_wrapper.luca +0 -1
  121. data/src/templates/fields/button_field.luca +0 -2
  122. data/src/templates/fields/button_field_link.luca +0 -5
  123. data/src/templates/fields/checkbox_array.luca +0 -4
  124. data/src/templates/fields/checkbox_array_item.luca +0 -4
  125. data/src/templates/fields/checkbox_field.luca +0 -9
  126. data/src/templates/fields/file_upload_field.luca +0 -8
  127. data/src/templates/fields/hidden_field.luca +0 -1
  128. data/src/templates/fields/select_field.luca +0 -8
  129. data/src/templates/fields/text_area_field.luca +0 -8
  130. data/src/templates/fields/text_field.luca +0 -17
  131. data/src/templates/sample/contents.luca +0 -1
  132. data/src/templates/sample/welcome.luca +0 -1
  133. data/src/templates/table_view.luca +0 -4
@@ -1,15 +1,33 @@
1
- # Public: The CollectionView renders a collection of models into a list of items.
1
+ collectionView = Luca.define "Luca.components.CollectionView"
2
+ # The CollectionView facilitates the rendering of a Collection
3
+ # of models into a group of many rendered templates
2
4
  #
3
- # Examples
5
+ # Example:
4
6
  #
5
- # _.def('App.ListView').extends('Luca.components.CollectionView').with
6
- # collection: new App.SampleCollection()
7
- # itemTemplate: "list_view_item"
8
- # loadMask: true
7
+ # new Luca.components.CollectionView
8
+ # itemTemplate: "template_name"
9
+ # collection: "collection_class_name"
10
+ # pagination:
11
+ # page: 1
12
+ # limit: 15
13
+ # filterable:
14
+ # query:
15
+ # default: 'value'
9
16
  #
17
+ collectionView.extends "Luca.components.Panel"
10
18
 
11
- _.def("Luca.components.CollectionView").extends("Luca.components.Panel").with
12
- tagName: "div"
19
+ collectionView.behavesAs "LoadMaskable",
20
+ "Filterable",
21
+ "Paginatable"
22
+
23
+ collectionView.triggers "before:refresh",
24
+ "after:refresh",
25
+ "refresh",
26
+ "empty:results"
27
+
28
+ collectionView.defaults
29
+
30
+ tagName: "ol"
13
31
 
14
32
  className: "luca-ui-collection-view"
15
33
 
@@ -25,89 +43,147 @@ _.def("Luca.components.CollectionView").extends("Luca.components.Panel").with
25
43
 
26
44
  itemClassName: 'collection-item'
27
45
 
28
- hooks:[
29
- "empty:results"
30
- ]
31
-
46
+
32
47
  initialize: (@options={})->
33
48
  _.extend(@, @options)
34
49
 
35
50
  _.bindAll @, "refresh"
36
51
 
52
+
37
53
  unless @collection? or @options.collection
54
+ console.log "Error on initialize of collection view", @
38
55
  throw "Collection Views must specify a collection"
39
56
 
40
57
  unless @itemTemplate? || @itemRenderer? || @itemProperty?
41
58
  throw "Collection Views must specify an item template or item renderer function"
42
59
 
43
- Luca.components.Panel::initialize.apply(@, arguments)
60
+ if _.isString(@collection)
61
+ if Luca.CollectionManager.get()
62
+ @collection = Luca.CollectionManager.get().getOrCreate(@collection)
63
+ else
64
+ console.log "String Collection but no collection manager"
44
65
 
45
- if _.isString(@collection) and Luca.CollectionManager.get()
46
- @collection = Luca.CollectionManager.get().getOrCreate(@collection)
66
+ unless Luca.isBackboneCollection(@collection)
67
+ console.log "Missing Collection on #{ @name || @cid }", @, @collection
68
+ throw "Collection Views must have a valid backbone collection"
47
69
 
48
- if Luca.isBackboneCollection(@collection)
49
70
  @collection.on "before:fetch", ()=>
50
- @trigger "enable:loadmask" if @loadMask is true
71
+ @trigger "enable:loadmask"
51
72
 
52
73
  @collection.bind "reset", ()=>
53
- @trigger "disable:loadmask" if @loadMask is true
74
+ @refresh()
75
+ @trigger "disable:loadmask"
76
+
77
+ @collection.bind "remove", ()=>
54
78
  @refresh()
55
79
 
56
- @collection.bind "add", @refresh
57
- @collection.bind "remove", @refresh
80
+ @collection.bind "add", ()=>
81
+ @refresh()
58
82
 
59
83
  if @observeChanges is true
60
- setupChangeObserver.call(@)
84
+ @collection.on "change", @refreshModel, @
61
85
 
62
- else
63
- throw "Collection Views must have a valid backbone collection"
86
+ Luca.components.Panel::initialize.apply(@, arguments)
87
+
88
+ unless @autoRefreshOnModelsPresent is false
89
+ @defer ()=>
90
+ @refresh() if @collection.length > 0
91
+ .until("after:render")
64
92
 
65
- if @collection.length > 0
66
- @refresh()
93
+ @on "refresh", @refresh, @
67
94
 
68
95
  attributesForItem: (item, model)->
69
96
  _.extend {}, class: @itemClassName, "data-index": item.index, "data-model-id": item.model.get('id')
70
97
 
71
98
  contentForItem: (item={})->
72
99
  if @itemTemplate? and templateFn = Luca.template(@itemTemplate)
73
- # this is the model
74
- content = templateFn.call(@, item)
100
+ return content = templateFn.call(@, item)
75
101
 
76
102
  if @itemRenderer? and _.isFunction( @itemRenderer )
77
- content = @itemRenderer.call(@, item, item.model, item.index)
103
+ return content = @itemRenderer.call(@, item, item.model, item.index)
78
104
 
79
- if @itemProperty
80
- content = item.model.get(@itemProperty) || item.model[ @itemProperty ]
81
- content = content() if _.isFunction(content)
105
+ if @itemProperty and item.model?
106
+ return content = item.model.read( @itemProperty )
82
107
 
83
- content
108
+ ""
84
109
 
85
110
  makeItem: (model, index)->
86
111
  item = if @prepareItem? then @prepareItem.call(@, model, index) else (model:model, index: index)
87
- make(@itemTagName, @attributesForItem(item, model), @contentForItem(item))
112
+ attributes = @attributesForItem(item, model)
113
+ content = @contentForItem(item)
114
+ # TEMP
115
+ # Figure out why calls to make are failing with an unexpected string error
116
+ try
117
+ make(@itemTagName, attributes, content)
118
+ catch e
119
+ console.log "Error generating DOM element for CollectionView", @, model, index
120
+ #no op
121
+
122
+ getCollection: ()->
123
+ @collection
124
+
125
+ applyQuery: (query={},queryOptions={})->
126
+ @query = query
127
+ @queryOptions = queryOptions
128
+ @refresh()
129
+ @
88
130
 
89
- getModels: ()->
90
- if @collection?.query and (@filter || @filterOptions)
91
- @collection.query(@filter, @filterOptions)
131
+ # Private: returns the query that is applied to the underlying collection.
132
+ # accepts the same options as Luca.Collection.query's initial query option.
133
+ getQuery: ()->
134
+ query = @query ||= {}
135
+ for querySource in _( @querySources || [] ).compact()
136
+ query = _.extend(query, (querySource()||{}) )
137
+ query
138
+
139
+ # Private: returns the query that is applied to the underlying collection.
140
+ # accepts the same options as Luca.Collection.query's initial query option.
141
+ getQueryOptions: ()->
142
+ options = @queryOptions ||= {}
143
+
144
+ for optionSource in _( @optionsSources || [] ).compact()
145
+ options = _.extend(options, (optionSource()||{}) )
146
+
147
+ options
148
+
149
+ # Private: returns the models to be rendered. If the underlying collection
150
+ # responds to @query() then it will use that interface.
151
+ getModels: (query,options)->
152
+ if @collection?.query
153
+ query ||= @getQuery()
154
+ options ||= @getQueryOptions()
155
+
156
+ @collection.query(query, options)
92
157
  else
93
158
  @collection.models
94
159
 
95
-
96
160
  locateItemElement: (id)->
97
161
  @$(".#{ @itemClassName }[data-model-id='#{ id }']")
98
162
 
99
163
  refreshModel: (model)->
100
164
  index = @collection.indexOf( model )
101
165
  @locateItemElement(model.get('id')).empty().append( @contentForItem({model,index}, model) )
166
+ @trigger("model:refreshed", index, model)
167
+
168
+ refresh: (query,options,models)->
169
+ query ||= @getQuery()
170
+ options ||= @getQueryOptions()
171
+ models ||= @getModels(query, options)
102
172
 
103
- refresh: ()->
104
173
  @$bodyEl().empty()
105
174
 
106
- if @getModels().length is 0
175
+ @trigger("before:refresh", models, query, options)
176
+
177
+ if models.length is 0
107
178
  @trigger("empty:results")
108
179
 
109
- _( @getModels() ).each (model, index)=>
110
- @$append( @makeItem(model, index) )
180
+ index = 0
181
+ for model in models
182
+ @$append @makeItem(model, index++)
183
+
184
+ @trigger("after:refresh", models, query, options)
185
+
186
+ @
111
187
 
112
188
  registerEvent: (domEvent, selector, handler)->
113
189
  if !handler? and _.isFunction(selector)
@@ -124,8 +200,5 @@ _.def("Luca.components.CollectionView").extends("Luca.components.Panel").with
124
200
 
125
201
  # Private Helpers
126
202
 
127
- make = Luca.View::make
128
203
 
129
- setupChangeObserver = ()->
130
- @collection.on "change", (model)=>
131
- @refreshModel(model)
204
+ make = Luca.View::make
@@ -31,7 +31,7 @@ _.def('Luca.fields.CheckboxField').extends('Luca.core.Field').with
31
31
  @label ||= @name
32
32
 
33
33
  setValue: (checked)->
34
- @input.attr('checked', checked)
34
+ @getInputElement().attr('checked', checked)
35
35
 
36
36
  getValue:()->
37
- @input.is(":checked")
37
+ @getInputElement().is(":checked")
@@ -2,9 +2,6 @@ _.def('Luca.fields.FileUploadField').extends('Luca.core.Field').with
2
2
 
3
3
  template: 'fields/file_upload_field'
4
4
 
5
- initialize: (@options={})->
6
- Luca.core.Field::initialize.apply @, arguments
7
-
8
5
  afterInitialize: ()->
9
6
  @input_id ||= _.uniqueId('field')
10
7
  @input_name ||= @name
@@ -2,9 +2,6 @@ _.def('Luca.fields.HiddenField').extends('Luca.core.Field').with
2
2
 
3
3
  template: 'fields/hidden_field'
4
4
 
5
- initialize: (@options={})->
6
- Luca.core.Field::initialize.apply @, arguments
7
-
8
5
  afterInitialize: ()->
9
6
  @input_id ||= _.uniqueId('field')
10
7
  @input_name ||= @name
@@ -1,14 +1,11 @@
1
1
  _.def("Luca.components.LabelField").extends("Luca.core.Field").with
2
2
  className: "luca-ui-field luca-ui-label-field"
3
3
 
4
- getValue: ()->
5
- @$('input').attr('value')
6
-
7
4
  formatter: (value)->
8
5
  value ||= @getValue()
9
6
  _.str.titleize( value )
10
7
 
11
8
  setValue: (value)->
12
9
  @trigger("change", value, @getValue())
13
- @$('input').attr('value', value)
10
+ @getInputElement().attr('value', value)
14
11
  @$('.value').html( @formatter(value) )
@@ -57,9 +57,10 @@ _.def('Luca.fields.SelectField').extends('Luca.core.Field').with
57
57
 
58
58
  hash
59
59
 
60
- afterRender: ()->
61
- @input = $('select', @el)
60
+ getInputElement: ()->
61
+ @input ||= @$('select').eq(0)
62
62
 
63
+ afterRender: ()->
63
64
  if @collection?.models?.length > 0
64
65
  @populateOptions()
65
66
  else
@@ -76,11 +77,10 @@ _.def('Luca.fields.SelectField').extends('Luca.core.Field').with
76
77
  @trigger "on:change", @, e
77
78
 
78
79
  resetOptions: ()->
79
- @input.html('')
80
+ @getInputElement().html('')
80
81
 
81
82
  if @includeBlank
82
- @input.append("<option value='#{ @blankValue }'>#{ @blankText }</option>")
83
-
83
+ @getInputElement().append("<option value='#{ @blankValue }'>#{ @blankText }</option>")
84
84
 
85
85
  populateOptions: ()->
86
86
  @resetOptions()
@@ -91,7 +91,7 @@ _.def('Luca.fields.SelectField').extends('Luca.core.Field').with
91
91
  display = model.get( @displayField )
92
92
  selected = "selected" if @selected and value is @selected
93
93
  option = "<option #{ selected } value='#{ value }'>#{ display }</option>"
94
- @input.append( option )
94
+ @getInputElement().append( option )
95
95
 
96
96
  @trigger "after:populate:options", @
97
97
  @setValue( @currentValue )
@@ -19,6 +19,7 @@ _.def('Luca.fields.TextAreaField').extends('Luca.core.Field').with
19
19
  @input_name ||= @name
20
20
  @label ||= @name
21
21
  @input_class ||= @class
22
+ @input_value ||= ""
22
23
  @inputStyles ||= "height:#{ @height };width:#{ @width }"
23
24
 
24
25
  setValue: (value)->
@@ -21,7 +21,11 @@ _.def('Luca.fields.TextField').extends('Luca.core.Field').with
21
21
  @input_name ||= @name
22
22
  @label ||= @name
23
23
  @input_class ||= @class
24
+ @input_value ||= @value || ""
24
25
 
26
+ # TODO
27
+ # Placeholder?
28
+
25
29
  if @prepend
26
30
  @$el.addClass('input-prepend')
27
31
  @addOn = @prepend
@@ -2,21 +2,17 @@ _.def('Luca.fields.TypeAheadField').extends('Luca.fields.TextField').with
2
2
  className: 'luca-ui-field'
3
3
 
4
4
  getSource: ()->
5
- return @source.call(@) if _.isFunction(@source)
6
- @source || []
5
+ Luca.util.read(@source) || []
7
6
 
8
7
  matcher: (item)->
9
- # IMPLEMENT
10
- # return true where item matches @query
11
8
  true
12
9
 
13
10
  beforeRender: ()->
14
- @_super("beforeRender", @, arguments)
15
- @$('input').attr('data-provide','typeahead')
11
+ Luca.fields.TextField::beforeRender.apply(@, arguments)
12
+ @getInputElement().attr('data-provide','typeahead')
16
13
 
17
14
  afterRender: ()->
18
- @_super("afterRender", @, arguments)
19
-
20
- @$('input').typeahead
15
+ Luca.fields.TextField::afterRender.apply(@, arguments)
16
+ @getInputElement().typeahead
21
17
  matcher: @matcher
22
18
  source: @getSource()
@@ -1,20 +1,3 @@
1
- defaultToolbar =
2
- buttons:[
3
- icon:"remove-sign"
4
- label: "Reset"
5
- eventId: "click:reset"
6
- className:"reset-button"
7
- align: 'right'
8
- ,
9
- icon:"ok-sign"
10
- white: true
11
- label: "Save Changes"
12
- eventId: "click:submit"
13
- color: "success"
14
- className: 'submit-button'
15
- align: 'right'
16
- ]
17
-
18
1
  _.def("Luca.components.FormView").extends('Luca.core.Container').with
19
2
 
20
3
  tagName: 'form'
@@ -54,6 +37,8 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
54
37
 
55
38
  Luca.core.Container::initialize.apply @, arguments
56
39
 
40
+ @components ||= @fields
41
+
57
42
  _.bindAll @, "submitHandler", "resetHandler", "renderToolbars", "applyLoadMask"
58
43
 
59
44
  @state ||= new Backbone.Model
@@ -67,7 +52,7 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
67
52
  @bottomToolbar = @getDefaultToolbar() unless @toolbar is "top"
68
53
 
69
54
  getDefaultToolbar: ()->
70
- defaultToolbar
55
+ Luca.components.FormView.defaultFormViewToolbar
71
56
 
72
57
  applyStyleClasses: ()->
73
58
  if Luca.enableBootstrap
@@ -110,7 +95,7 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
110
95
  passOne = _( @getFields('name', name) ).first()
111
96
  return passOne if passOne?
112
97
 
113
- _( @getFields('input_name', name) ).first()
98
+ _( @getFields('input_name', name) ).first()
114
99
 
115
100
  getFields: (attr,value)->
116
101
  fields = @selectByAttribute("isField", true, true)
@@ -199,17 +184,17 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
199
184
  if options.skip_buttons and field.ctype is "button_field"
200
185
  skip = true
201
186
  else
202
- if valueIsBlank and allowBlankValues is false
203
- skip = true
187
+ if valueIsBlank and allowBlankValues is false
188
+ skip = true
204
189
 
205
190
  if field.input_name is "id" and valueIsBlank is true
206
191
  skip = true
207
192
 
208
193
  if options.debug
209
194
  console.log "Skip is true on #{ key }"
210
-
195
+
211
196
  if skip isnt true
212
- memo[ key ] = value
197
+ memo[ key ] = value
213
198
 
214
199
  memo
215
200
 
@@ -273,3 +258,23 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
273
258
  errorMessage: (message)->
274
259
  @$('.alert.alert-error').remove()
275
260
  @flash Luca.template("components/form_alert", className:"alert alert-error", message: message)
261
+
262
+
263
+ Luca.components.FormView.defaultFormViewToolbar =
264
+ buttons:[
265
+ icon:"remove-sign"
266
+ label: "Reset"
267
+ eventId: "click:reset"
268
+ className:"reset-button"
269
+ align: 'right'
270
+ ,
271
+ icon:"ok-sign"
272
+ white: true
273
+ label: "Save Changes"
274
+ eventId: "click:submit"
275
+ color: "success"
276
+ className: 'submit-button'
277
+ align: 'right'
278
+ ]
279
+
280
+
@@ -0,0 +1,121 @@
1
+ multiView = Luca.define "Luca.components.MultiCollectionView"
2
+
3
+ # The CollectionMultiView is a collection view with multiple renderings
4
+ # of the list. ( e.g. Icons, Table, List ). It works by maintaining
5
+ # a current view, and rendering that view. It refreshes the views
6
+ # whenever they are activated.
7
+ #
8
+ # The MultiView allows you to share one collection, filter, pagination setup
9
+ # but render multiple versions of a model. To do this, you are expected to
10
+ # define one or more objects in the @views property of the component.
11
+
12
+ # Example:
13
+ # multiView = new Luca.components.MultiCollectionView
14
+ # collection: "my_collection"
15
+ # paginatable:
16
+ # page: 1
17
+ # limit: 20
18
+ # views:[
19
+ # type: "table"
20
+ # columns:[
21
+ # header: "Header"
22
+ # reader: "attribute"
23
+ # ]
24
+ # ]
25
+ multiView.extends "Luca.containers.CardView"
26
+
27
+ multiView.behavesAs "LoadMaskable",
28
+ "Filterable",
29
+ "Paginatable"
30
+
31
+ multiView.triggers "before:refresh",
32
+ "after:refresh",
33
+ "refresh",
34
+ "empty:results"
35
+
36
+ multiView.defaultsTo
37
+ version: 1
38
+
39
+ stateful: true
40
+
41
+ defaultState:
42
+ activeView: 0
43
+
44
+ viewContainerClass: "luca-ui-multi-view-container"
45
+
46
+ initialize: (@options={})->
47
+ @components ||= @views
48
+
49
+ validateComponent( view ) for view in @components
50
+
51
+ @on "refresh", @refresh, @
52
+ @on "after:card:switch", @refresh, @
53
+ @on "after:components", propagateCollectionComponents, @
54
+
55
+ @debug("multi collection , proto initialize")
56
+
57
+ Luca.containers.CardView::initialize.apply(@, arguments)
58
+
59
+ relayAfterRefresh: (models,query,options)->
60
+ @trigger "after:refresh", models, query, options
61
+
62
+ refresh: ()->
63
+ @activeComponent()?.trigger("refresh")
64
+
65
+ getCollection: ()->
66
+ @collection
67
+
68
+ applyQuery: (query={},queryOptions={})->
69
+ @query = query
70
+ @queryOptions = queryOptions
71
+ @
72
+
73
+ # Private: returns the query that is applied to the underlying collection.
74
+ # accepts the same options as Luca.Collection.query's initial query option.
75
+ getQuery: ()->
76
+ @debug("Get Query")
77
+ query = @query ||= {}
78
+ for querySource in @querySources
79
+ query = _.extend(query, (querySource()||{}) )
80
+ query
81
+
82
+ # Private: returns the query that is applied to the underlying collection.
83
+ # accepts the same options as Luca.Collection.query's initial query option.
84
+ getQueryOptions: ()->
85
+ @debug("Get Query Options")
86
+ options = @queryOptions ||= {}
87
+
88
+ for optionSource in @optionsSources
89
+ options = _.extend(options, (optionSource()||{}) )
90
+
91
+ options
92
+
93
+ propagateCollectionComponents = ()->
94
+ container = @
95
+
96
+ # in the multi view will share the same
97
+ # collection, filter state, pagination options, etc
98
+ for component in @components
99
+
100
+ component.on "after:refresh", (models,query,options)=>
101
+ @debug "collection member after refresh"
102
+ @trigger("after:refresh",models,query,options)
103
+
104
+ _.extend component,
105
+ collection: container.getCollection()
106
+
107
+ getQuery: ()->
108
+ container.getQuery.call(container)
109
+
110
+ getQueryOptions: ()->
111
+ container.getQueryOptions.call(container)
112
+
113
+ validateComponent = (component)->
114
+ type = (component.type || component.ctype)
115
+
116
+ return if type is "collection" or
117
+ type is "collection_view" or
118
+ type is "table" or
119
+ type is "table_view"
120
+
121
+ throw "The MultiCollectionView expects to contain multiple collection views"
@@ -0,0 +1,106 @@
1
+ paginationControl = Luca.register "Luca.components.PaginationControl"
2
+
3
+ paginationControl.extends "Luca.View"
4
+
5
+ paginationControl.defines
6
+ template: "components/pagination"
7
+
8
+ stateful: true
9
+
10
+ autoBindEventHandlers: true
11
+
12
+ events:
13
+ "click a[data-page-number]" : "selectPage"
14
+ "click a.next" : "nextPage"
15
+ "click a.prev" : "previousPage"
16
+
17
+ afterInitialize: ()->
18
+ _.bindAll @, "updateWithPageCount"
19
+
20
+ @state.on "change", (state, numberOfPages)=>
21
+ @updateWithPageCount( state.get('numberOfPages') )
22
+
23
+ limit: ()->
24
+ parseInt (@state.get('limit') || @collection?.length)
25
+
26
+ page: ()->
27
+ parseInt (@state.get('page') || 1)
28
+
29
+ nextPage: ()->
30
+ return unless @nextEnabled()
31
+ @state.set('page', @page() + 1 )
32
+
33
+ previousPage: ()->
34
+ return unless @previousEnabled()
35
+ @state.set('page', @page() - 1 )
36
+
37
+ selectPage: (e)->
38
+ me = my = @$( e.target )
39
+ me = my = my.closest('a.page') unless me.is('a.page')
40
+
41
+ my.siblings().removeClass('is-selected')
42
+ me.addClass('is-selected')
43
+
44
+ @setPage( my.data('page-number') )
45
+
46
+ setPage: (page=1,options={})->
47
+ @state.set('page', page, options)
48
+
49
+ setLimit: (limit=1,options={})->
50
+ @state.set('limit', limit, options)
51
+
52
+ pageButtonContainer: ()->
53
+ @$ '.group'
54
+
55
+ previousEnabled: ()->
56
+ @page() > 1
57
+
58
+ nextEnabled: ()->
59
+ @page() < @totalPages()
60
+
61
+ previousButton: ()->
62
+ @$ 'a.page.prev'
63
+
64
+ nextButton: ()->
65
+ @$ 'a.page.next'
66
+
67
+ pageButtons: ()->
68
+ @$ 'a[data-page-number]', @pageButtonContainer()
69
+
70
+ updateWithPageCount: (@pageCount, models=[])->
71
+ modelCount = models.length
72
+
73
+ console.log "Update With Page Count", @pageCount, modelCount
74
+
75
+ @pageButtonContainer().empty()
76
+
77
+ _( @pageCount ).times (index)=>
78
+ page = index + 1
79
+ button = @make("a","data-page-number":page, class:"page", page )
80
+ @pageButtonContainer().append(button)
81
+
82
+ @toggleNavigationButtons()
83
+ @selectActivePageButton()
84
+
85
+ @
86
+
87
+ toggleNavigationButtons: ()->
88
+ @$('a.next, a.prev').addClass('disabled')
89
+ @nextButton().removeClass('disabled') if @nextEnabled()
90
+ @previousButton().removeClass('disabled') if @previousEnabled()
91
+
92
+ selectActivePageButton: ()->
93
+ @activePageButton().addClass('is-selected')
94
+
95
+ activePageButton: ()->
96
+ @pageButtons().filter("[data-page-number='#{ @page() }']")
97
+
98
+ totalPages: ()->
99
+ @pageCount
100
+
101
+ totalItems: ()->
102
+ parseInt @collection?.length || 0
103
+
104
+ itemsPerPage: (value, options={})->
105
+ @state.set("limit", value, options) if value?
106
+ parseInt @state.get("limit")