luca 0.9.6 → 0.9.7

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 (76) hide show
  1. data/CHANGELOG +37 -14
  2. data/lib/luca/rails/version.rb +1 -1
  3. data/spec/components/collection_view_spec.coffee +24 -2
  4. data/spec/components/pagination_control_spec.coffee +0 -0
  5. data/spec/concerns/dom_helpers_spec.coffee +16 -0
  6. data/spec/concerns/filterable_spec.coffee +25 -0
  7. data/spec/concerns/model_presenter_spec.coffee +31 -0
  8. data/spec/concerns/paginatable_spec.coffee +0 -0
  9. data/spec/concerns/state_model_spec.coffee +0 -0
  10. data/spec/concerns_spec.coffee +88 -0
  11. data/spec/core/container_spec.coffee +74 -12
  12. data/spec/core/model_spec.coffee +6 -1
  13. data/spec/define_spec.coffee +0 -6
  14. data/spec/util_spec.coffee +24 -0
  15. data/src/components/application.coffee +32 -30
  16. data/src/components/base_toolbar.coffee +6 -4
  17. data/src/components/collection_loader_view.coffee +3 -1
  18. data/src/components/collection_view.coffee +42 -21
  19. data/src/components/controller.coffee +3 -1
  20. data/src/components/fields/button_field.coffee +19 -12
  21. data/src/components/fields/checkbox_array.coffee +8 -2
  22. data/src/components/fields/checkbox_field.coffee +18 -9
  23. data/src/components/fields/file_upload_field.coffee +5 -1
  24. data/src/components/fields/hidden_field.coffee +3 -1
  25. data/src/components/fields/label_field.coffee +4 -3
  26. data/src/components/fields/select_field.coffee +7 -8
  27. data/src/components/fields/text_field.coffee +3 -1
  28. data/src/components/fields/type_ahead_field.coffee +4 -2
  29. data/src/components/form_button_toolbar.coffee +4 -1
  30. data/src/components/form_view.coffee +49 -44
  31. data/src/components/grid_view.coffee +1 -1
  32. data/src/components/multi_collection_view.coffee +49 -22
  33. data/src/components/pagination_control.coffee +17 -13
  34. data/src/{modules → concerns}/application_event_bindings.coffee +1 -1
  35. data/src/{modules → concerns}/collection_event_bindings.coffee +1 -1
  36. data/src/{modules → concerns}/deferrable.coffee +1 -1
  37. data/src/{modules → concerns}/dom_helpers.coffee +11 -2
  38. data/src/{modules → concerns}/enhanced_properties.coffee +1 -1
  39. data/src/concerns/filterable.coffee +82 -0
  40. data/src/{modules → concerns}/grid_layout.coffee +1 -1
  41. data/src/{modules → concerns}/loadmaskable.coffee +1 -1
  42. data/src/{modules → concerns}/local_storage.coffee +0 -0
  43. data/src/{modules → concerns}/modal_view.coffee +1 -1
  44. data/src/concerns/model_presenter.coffee +23 -0
  45. data/src/concerns/paginatable.coffee +87 -0
  46. data/src/{modules → concerns}/state_model.coffee +1 -1
  47. data/src/{modules → concerns}/templating.coffee +1 -1
  48. data/src/concerns.coffee +70 -0
  49. data/src/containers/tab_view.coffee +7 -10
  50. data/src/core/collection.coffee +17 -1
  51. data/src/core/container.coffee +56 -31
  52. data/src/core/field.coffee +39 -38
  53. data/src/core/meta_data.coffee +37 -0
  54. data/src/core/model.coffee +18 -1
  55. data/src/core/view.coffee +25 -29
  56. data/src/define.coffee +54 -66
  57. data/src/framework.coffee +23 -18
  58. data/src/index.coffee +3 -1
  59. data/src/stylesheets/components/checkbox_array.scss +1 -1
  60. data/src/stylesheets/components/form_view.scss +5 -5
  61. data/src/stylesheets/components/viewport.scss +2 -1
  62. data/src/stylesheets/containers/container.scss +0 -5
  63. data/src/stylesheets/containers/tab_view.scss +5 -5
  64. data/src/tools/console.coffee +5 -5
  65. data/src/util.coffee +47 -0
  66. data/vendor/assets/javascripts/luca-ui-development-tools.js +5 -5
  67. data/vendor/assets/javascripts/luca-ui-development-tools.min.js +1 -1
  68. data/vendor/assets/javascripts/luca-ui-full.js +905 -416
  69. data/vendor/assets/javascripts/luca-ui-full.min.js +5 -5
  70. data/vendor/assets/javascripts/luca-ui.js +905 -416
  71. data/vendor/assets/javascripts/luca-ui.min.js +5 -4
  72. data/vendor/assets/stylesheets/luca-ui.css +15 -15
  73. metadata +27 -17
  74. data/spec/mixin_spec.coffee +0 -49
  75. data/src/modules/filterable.coffee +0 -60
  76. data/src/modules/paginatable.coffee +0 -79
@@ -1,42 +1,28 @@
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
- _.def("Luca.components.FormView").extends('Luca.core.Container').with
19
-
1
+ #_.def("Luca.components.FormView").extends('Luca.core.Container').with
2
+
3
+ formView = Luca.register "Luca.components.FormView"
4
+ formView.extends "Luca.core.Container"
5
+
6
+ formView.triggers "before:submit",
7
+ "before:reset",
8
+ "before:load",
9
+ "before:load:new",
10
+ "before:load:existing",
11
+ "after:submit",
12
+ "after:reset",
13
+ "after:load",
14
+ "after:load:new",
15
+ "after:load:existing",
16
+ "after:submit:success",
17
+ "after:submit:fatal_error",
18
+ "after:submit:error"
19
+
20
+
21
+ formView.defines
20
22
  tagName: 'form'
21
23
 
22
24
  className: 'luca-ui-form-view'
23
25
 
24
- hooks:[
25
- "before:submit"
26
- "before:reset"
27
- "before:load"
28
- "before:load:new"
29
- "before:load:existing"
30
- "after:submit"
31
- "after:reset"
32
- "after:load"
33
- "after:load:new"
34
- "after:load:existing"
35
- "after:submit:success"
36
- "after:submit:fatal_error"
37
- "after:submit:error"
38
- ]
39
-
40
26
  events:
41
27
  "click .submit-button" : "submitHandler"
42
28
  "click .reset-button" : "resetHandler"
@@ -47,7 +33,7 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
47
33
 
48
34
  bodyClassName: "form-view-body"
49
35
 
50
- version: "0.9.33333333"
36
+ version: 1
51
37
 
52
38
  initialize: (@options={})->
53
39
  @loadMask = Luca.enableBootstrap unless @loadMask?
@@ -56,8 +42,7 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
56
42
 
57
43
  @components ||= @fields
58
44
 
59
- _.bindAll @, "submitHandler", "resetHandler", "renderToolbars", "applyLoadMask"
60
-
45
+ _.bindAll @, "submitHandler", "resetHandler", "renderToolbars"
61
46
  @state ||= new Backbone.Model
62
47
 
63
48
  @setupHooks( @hooks )
@@ -69,7 +54,7 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
69
54
  @bottomToolbar = @getDefaultToolbar() unless @toolbar is "top"
70
55
 
71
56
  getDefaultToolbar: ()->
72
- defaultToolbar
57
+ Luca.components.FormView.defaultFormViewToolbar
73
58
 
74
59
  applyStyleClasses: ()->
75
60
  if Luca.enableBootstrap
@@ -112,7 +97,7 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
112
97
  passOne = _( @getFields('name', name) ).first()
113
98
  return passOne if passOne?
114
99
 
115
- _( @getFields('input_name', name) ).first()
100
+ _( @getFields('input_name', name) ).first()
116
101
 
117
102
  getFields: (attr,value)->
118
103
  fields = @selectByAttribute("isField", true, true)
@@ -201,17 +186,17 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
201
186
  if options.skip_buttons and field.ctype is "button_field"
202
187
  skip = true
203
188
  else
204
- if valueIsBlank and allowBlankValues is false
205
- skip = true
189
+ if valueIsBlank and allowBlankValues is false
190
+ skip = true
206
191
 
207
192
  if field.input_name is "id" and valueIsBlank is true
208
193
  skip = true
209
194
 
210
195
  if options.debug
211
196
  console.log "Skip is true on #{ key }"
212
-
197
+
213
198
  if skip isnt true
214
- memo[ key ] = value
199
+ memo[ key ] = value
215
200
 
216
201
  memo
217
202
 
@@ -275,3 +260,23 @@ _.def("Luca.components.FormView").extends('Luca.core.Container').with
275
260
  errorMessage: (message)->
276
261
  @$('.alert.alert-error').remove()
277
262
  @flash Luca.template("components/form_alert", className:"alert alert-error", message: message)
263
+
264
+
265
+ Luca.components.FormView.defaultFormViewToolbar =
266
+ buttons:[
267
+ icon:"remove-sign"
268
+ label: "Reset"
269
+ eventId: "click:reset"
270
+ className:"reset-button"
271
+ align: 'right'
272
+ ,
273
+ icon:"ok-sign"
274
+ white: true
275
+ label: "Save Changes"
276
+ eventId: "click:submit"
277
+ color: "success"
278
+ className: 'submit-button'
279
+ align: 'right'
280
+ ]
281
+
282
+
@@ -57,7 +57,7 @@ _.def('Luca.components.GridView').extend('Luca.components.Panel').with
57
57
 
58
58
  initialize: (@options={})->
59
59
  _.extend @, @options
60
- _.extend @, Luca.modules.Deferrable
60
+ _.extend @, Luca.concerns.Deferrable
61
61
 
62
62
  @loadMask = Luca.enableBootstrap unless @loadMask?
63
63
  @loadMaskEl ||= ".luca-ui-g-view-body" if @loadMask is true
@@ -1,4 +1,4 @@
1
- multiView = Luca.define "Luca.components.MultiCollectionView"
1
+ multiView = Luca.register "Luca.components.MultiCollectionView"
2
2
 
3
3
  # The CollectionMultiView is a collection view with multiple renderings
4
4
  # of the list. ( e.g. Icons, Table, List ). It works by maintaining
@@ -24,9 +24,9 @@ multiView = Luca.define "Luca.components.MultiCollectionView"
24
24
  # ]
25
25
  multiView.extends "Luca.containers.CardView"
26
26
 
27
- multiView.behavesAs "LoadMaskable",
28
- "Filterable",
29
- "Paginatable"
27
+ multiView.mixesIn "LoadMaskable",
28
+ "Filterable",
29
+ "Paginatable"
30
30
 
31
31
  multiView.triggers "before:refresh",
32
32
  "after:refresh",
@@ -48,29 +48,47 @@ multiView.defaultsTo
48
48
 
49
49
  validateComponent( view ) for view in @components
50
50
 
51
- @on "collection:change", @refresh, @
51
+ @on "refresh", @refresh, @
52
52
  @on "after:card:switch", @refresh, @
53
- @on "before:components", propagateCollectionComponents, @
54
- @on "after:components", bubbleCollectionEvents, @
53
+ @on "after:components", propagateCollectionComponents, @
54
+
55
+ @debug("multi collection , proto initialize")
55
56
 
56
57
  Luca.containers.CardView::initialize.apply(@, arguments)
57
58
 
59
+ relayAfterRefresh: (models,query,options)->
60
+ @trigger "after:refresh", models, query, options
61
+
58
62
  refresh: ()->
59
63
  @activeComponent()?.trigger("refresh")
60
64
 
61
- getQuery: Luca.components.CollectionView::getQuery
62
- getQueryOptions: Luca.components.CollectionView::getQueryOptions
63
- getCollection: Luca.components.CollectionView::getCollection
64
-
65
- #### Private Helpers
65
+ getCollection: ()->
66
+ @collection
66
67
 
67
- bubbleCollectionEvents = ()->
68
- container = @
69
- container.eachComponent (component)->
70
- for eventId in ['refresh','before:refresh','after:refresh','empty:results']
71
- component.on eventId, ()->
72
- if component is container.activeComponent()
73
- container.trigger(eventId)
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
74
92
 
75
93
  propagateCollectionComponents = ()->
76
94
  container = @
@@ -78,10 +96,19 @@ propagateCollectionComponents = ()->
78
96
  # in the multi view will share the same
79
97
  # collection, filter state, pagination options, etc
80
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
+
81
104
  _.extend component,
82
- collection: container.getCollection?() || @collection
83
- getQuery: container.getQuery
84
- getQueryOptions: container.getQueryOptions
105
+ collection: container.getCollection()
106
+
107
+ getQuery: ()->
108
+ container.getQuery.call(container)
109
+
110
+ getQueryOptions: ()->
111
+ container.getQueryOptions.call(container)
85
112
 
86
113
  validateComponent = (component)->
87
114
  type = (component.type || component.ctype)
@@ -9,15 +9,16 @@ paginationControl.defines
9
9
 
10
10
  autoBindEventHandlers: true
11
11
 
12
- events:
12
+ events:
13
13
  "click a[data-page-number]" : "selectPage"
14
14
  "click a.next" : "nextPage"
15
- "click a.prev" : "previousPage"
15
+ "click a.prev" : "previousPage"
16
16
 
17
17
  afterInitialize: ()->
18
- _.bindAll @, "refresh"
18
+ _.bindAll @, "updateWithPageCount"
19
19
 
20
- @state.on("change", @refresh, @)
20
+ @state?.on "change", (state, numberOfPages)=>
21
+ @updateWithPageCount( state.get('numberOfPages') )
21
22
 
22
23
  limit: ()->
23
24
  parseInt (@state.get('limit') || @collection?.length)
@@ -35,7 +36,7 @@ paginationControl.defines
35
36
 
36
37
  selectPage: (e)->
37
38
  me = my = @$( e.target )
38
- me = my = my.closest('a.page') unless me.is('a.page')
39
+ me = my = my.closest('a.page') unless me.is('a.page')
39
40
 
40
41
  my.siblings().removeClass('is-selected')
41
42
  me.addClass('is-selected')
@@ -50,9 +51,9 @@ paginationControl.defines
50
51
 
51
52
  pageButtonContainer: ()->
52
53
  @$ '.group'
53
-
54
+
54
55
  previousEnabled: ()->
55
- @page() > 1
56
+ @page() > 1
56
57
 
57
58
  nextEnabled: ()->
58
59
  @page() < @totalPages()
@@ -64,14 +65,17 @@ paginationControl.defines
64
65
  @$ 'a.page.next'
65
66
 
66
67
  pageButtons: ()->
67
- @$ 'a[data-page-number]', @pageButtonContainer()
68
+ @$ 'a[data-page-number]', @pageButtonContainer()
69
+
70
+ updateWithPageCount: (@pageCount, models=[])->
71
+ modelCount = models.length
68
72
 
69
- refresh: ()->
70
73
  @pageButtonContainer().empty()
71
74
 
72
- for page in [1..@totalPages()]
75
+ _( @pageCount ).times (index)=>
76
+ page = index + 1
73
77
  button = @make("a","data-page-number":page, class:"page", page )
74
- @pageButtonContainer().append(button)
78
+ @pageButtonContainer().append(button)
75
79
 
76
80
  @toggleNavigationButtons()
77
81
  @selectActivePageButton()
@@ -90,11 +94,11 @@ paginationControl.defines
90
94
  @pageButtons().filter("[data-page-number='#{ @page() }']")
91
95
 
92
96
  totalPages: ()->
93
- parseInt( Math.ceil(@totalItems() / @itemsPerPage()) )
97
+ @pageCount
94
98
 
95
99
  totalItems: ()->
96
100
  parseInt @collection?.length || 0
97
101
 
98
- itemsPerPage: (value, options={})->
102
+ itemsPerPage: (value, options={})->
99
103
  @state.set("limit", value, options) if value?
100
104
  parseInt @state.get("limit")
@@ -1,4 +1,4 @@
1
- Luca.modules.ApplicationEventBindings =
1
+ Luca.concerns.ApplicationEventBindings =
2
2
  __initializer: ()->
3
3
  return if _.isEmpty(@applicationEvents)
4
4
 
@@ -1,4 +1,4 @@
1
- Luca.modules.CollectionEventBindings =
1
+ Luca.concerns.CollectionEventBindings =
2
2
  __initializer: ()->
3
3
  return if _.isEmpty( @collectionEvents )
4
4
 
@@ -1,7 +1,7 @@
1
1
  # TODO
2
2
  #
3
3
  # This is horrendous code. I need to replace it ASAP
4
- Luca.modules.Deferrable =
4
+ Luca.concerns.Deferrable =
5
5
  configure_collection: (setAsDeferrable=true)->
6
6
  return unless @collection
7
7
 
@@ -1,4 +1,4 @@
1
- Luca.modules.DomHelpers =
1
+ Luca.concerns.DomHelpers =
2
2
  __initializer: ()->
3
3
  additionalClasses = _( @additionalClassNames || [] ).clone()
4
4
 
@@ -24,12 +24,21 @@ Luca.modules.DomHelpers =
24
24
  for additional in additionalClasses
25
25
  @$el.addClass( additional )
26
26
 
27
+ if Luca.config.autoApplyClassHierarchyAsCssClasses is true
28
+ classes = @componentMetaData?()?.styleHierarchy() || []
29
+
30
+ for cssClass in classes when (cssClass isnt "luca-view" and cssClass isnt "backbone-view")
31
+ @$el.addClass(cssClass)
32
+
27
33
  $wrap: (wrapper)->
28
34
  if _.isString(wrapper) and not wrapper.match(/[<>]/)
29
- wrapper = @make("div",class:wrapper)
35
+ wrapper = @make("div",class:wrapper,"data-wrapper":true)
30
36
 
31
37
  @$el.wrap( wrapper )
32
38
 
39
+ $wrapper: ()->
40
+ @$el.parent('[data-wrapper="true"]')
41
+
33
42
  $template: (template, variables={})->
34
43
  @$el.html( Luca.template(template,variables) )
35
44
 
@@ -1,4 +1,4 @@
1
- Luca.modules.EnhancedProperties =
1
+ Luca.concerns.EnhancedProperties =
2
2
  __initializer: ()->
3
3
  return unless Luca.config.enhancedViewProperties is true
4
4
 
@@ -0,0 +1,82 @@
1
+ Luca.concerns.Filterable =
2
+ __included: (component, module)->
3
+ _.extend(Luca.Collection::, __filters:{})
4
+
5
+ __initializer: (component, module)->
6
+ if @filterable is false
7
+ return
8
+
9
+ # TEMP HACK
10
+ unless Luca.isBackboneCollection(@collection)
11
+ @collection = Luca.CollectionManager.get?()?.getOrCreate(@collection)
12
+
13
+ unless Luca.isBackboneCollection(@collection)
14
+ @debug "Skipping Filterable due to no collection being present on #{ @name || @cid }"
15
+ @debug "Collection", @collection
16
+ return
17
+
18
+ @getCollection ||= ()-> @collection
19
+
20
+ filter = @getFilterState()
21
+
22
+ @querySources ||= []
23
+ @optionsSources ||= []
24
+ @query ||= {}
25
+ @queryOptions ||= {}
26
+
27
+ @querySources.push (()=> filter.toQuery())
28
+ @optionsSources.push (()=> filter.toOptions())
29
+
30
+ if @debugMode is true
31
+ console.log "Filterable"
32
+ console.log @querySources
33
+ console.log @optionsSources
34
+
35
+ filter.on "change", ()=>
36
+ if @isRemote()
37
+ merged = _.extend(@getQuery(), @getQueryOptions())
38
+ @collection.applyFilter(merged, @getQueryOptions())
39
+ else
40
+ @trigger "refresh"
41
+
42
+ module
43
+
44
+ isRemote: ()->
45
+ @getQueryOptions().remote is true
46
+
47
+ getFilterState: ()->
48
+ @collection.__filters[ @cid ] ||= new FilterModel(@filterable)
49
+
50
+ setSortBy: (sortBy, options={})->
51
+ @getFilterState().setOption('sortBy', sortBy, options)
52
+
53
+ applyFilter: (query={}, options={})->
54
+ options = _.defaults(options, @getQueryOptions())
55
+ query = _.defaults(query, @getQuery())
56
+
57
+ @getFilterState().set({query,options}, options)
58
+
59
+ class FilterModel extends Backbone.Model
60
+ defaults:
61
+ options: {}
62
+ query: {}
63
+
64
+ setOption: (option, value, options)->
65
+ payload = {}
66
+ payload[option] = value
67
+ @set 'options', _.extend(@toOptions(), payload), options
68
+
69
+ setQueryOption: (option, value, options)->
70
+ payload = {}
71
+ payload[option] = value
72
+ @set 'query', _.extend(@toQuery(), payload), options
73
+
74
+ toOptions: ()->
75
+ @toJSON().options
76
+
77
+ toQuery: ()->
78
+ @toJSON().query
79
+
80
+ toRemote: ()->
81
+ options = @toOptions()
82
+ _.extend( @toQuery(), limit: options.limit, page: options.page, sortBy: options.sortBy )
@@ -1,4 +1,4 @@
1
- Luca.modules.GridLayout =
1
+ Luca.concerns.GridLayout =
2
2
  _initializer: ()->
3
3
  if @gridSpan
4
4
  @$el.addClass "span#{ @gridSpan }"
@@ -1,4 +1,4 @@
1
- Luca.modules.LoadMaskable =
1
+ Luca.concerns.LoadMaskable =
2
2
  __initializer: ()->
3
3
  return unless @loadMask is true
4
4
 
File without changes
@@ -1,4 +1,4 @@
1
- Luca.modules.ModalView =
1
+ Luca.concerns.ModalView =
2
2
  closeOnEscape: true
3
3
 
4
4
  showOnInitialize: false
@@ -0,0 +1,23 @@
1
+ Luca.concerns.ModelPresenter =
2
+ classMethods:
3
+ getPresenter: (format)->
4
+ @presenters?[format]
5
+
6
+ registerPresenter: (format, config)->
7
+ @presenters ||= {}
8
+ @presenters[ format ] = config
9
+
10
+ presentAs: (format)->
11
+ try
12
+ attributeList = @componentMetaData().componentDefinition().getPresenter(format)
13
+
14
+ return @toJSON() unless attributeList?
15
+
16
+ _( attributeList ).reduce (memo, attribute)=>
17
+ memo[ attribute ] = @read(attribute)
18
+ memo
19
+ , {}
20
+
21
+ catch e
22
+ console.log "Error presentAs", e.stack, e.message
23
+ return @toJSON()
@@ -0,0 +1,87 @@
1
+ Luca.concerns.Paginatable =
2
+ paginatorViewClass: 'Luca.components.PaginationControl'
3
+ paginationSelector: ".toolbar.bottom"
4
+
5
+ __included: ()->
6
+ _.extend(Luca.Collection::, __paginators: {})
7
+
8
+ __initializer:()->
9
+ if @paginatable is false
10
+ return
11
+
12
+ # TEMP HACK
13
+ unless Luca.isBackboneCollection(@collection)
14
+ @collection = Luca.CollectionManager.get?()?.getOrCreate(@collection)
15
+
16
+ unless Luca.isBackboneCollection(@collection)
17
+ @debug "Skipping Paginatable due to no collection being present on #{ @name || @cid }"
18
+ @debug "collection", @collection
19
+ return
20
+
21
+ _.bindAll @, "paginationControl", "pager"
22
+
23
+ @getCollection ||= ()->
24
+ @collection
25
+
26
+ collection = @getCollection()
27
+
28
+ paginationState = @getPaginationState()
29
+
30
+ @optionsSources ||= []
31
+ @queryOptions ||= {}
32
+
33
+ @optionsSources.push ()=>
34
+ options = _( paginationState.toJSON() ).pick('limit','page','sortBy')
35
+ _.extend(options, pager: @pager)
36
+
37
+ paginationState.on "change:page", (state)=>
38
+ if @isRemote()
39
+ filter = _.extend(@toQuery(), @toQueryOptions())
40
+ @collection.applyFilter(filter, remote: true)
41
+ else
42
+ @trigger "refresh"
43
+
44
+ @on "before:render", @renderPaginationControl, @
45
+
46
+ pager: (numberOfPages, models)->
47
+ @getPaginationState().set(numberOfPages: numberOfPages, itemCount: models.length)
48
+ @paginationControl().updateWithPageCount( numberOfPages, models )
49
+
50
+ isRemote: ()->
51
+ @getQueryOptions().remote is true
52
+
53
+ getPaginationState: ()->
54
+ @collection.__paginators[ @cid ] ||= @paginationControl().state
55
+
56
+ paginationContainer: ()->
57
+ @$(">#{ @paginationSelector }")
58
+
59
+ setCurrentPage: (page=1, options={})->
60
+ @getPaginationState().set('page', page, options)
61
+
62
+ setPage: (page=1, options={})->
63
+ @getPaginationState().set('page', page, options)
64
+
65
+ setLimit: (limit=0,options={})->
66
+ @getPaginationState().set('limit', limit, options)
67
+
68
+ paginationControl: ()->
69
+ return @paginator if @paginator?
70
+
71
+ _.defaults(@paginatable ||= {}, page: 1, limit: 20)
72
+
73
+ @paginator = Luca.util.lazyComponent
74
+ type: "pagination_control"
75
+ collection: @getCollection()
76
+ defaultState: @paginatable
77
+ parent: (@name || @cid)
78
+ debugMode: @debugMode
79
+
80
+ @paginator
81
+
82
+ renderPaginationControl: ()->
83
+ control = @paginationControl()
84
+ @paginationContainer().append( control.render().$el )
85
+ control
86
+
87
+
@@ -1,4 +1,4 @@
1
- Luca.modules.StateModel =
1
+ Luca.concerns.StateModel =
2
2
  __initializer: ()->
3
3
  return unless @stateful is true
4
4
  return if @state? and not Luca.isBackboneModel(@state)
@@ -1,4 +1,4 @@
1
- Luca.modules.Templating =
1
+ Luca.concerns.Templating =
2
2
  __initializer: ()->
3
3
  templateVars = Luca.util.read.call(@, @bodyTemplateVars) || {}
4
4