luca 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +37 -14
- data/lib/luca/rails/version.rb +1 -1
- data/spec/components/collection_view_spec.coffee +24 -2
- data/spec/components/pagination_control_spec.coffee +0 -0
- data/spec/concerns/dom_helpers_spec.coffee +16 -0
- data/spec/concerns/filterable_spec.coffee +25 -0
- data/spec/concerns/model_presenter_spec.coffee +31 -0
- data/spec/concerns/paginatable_spec.coffee +0 -0
- data/spec/concerns/state_model_spec.coffee +0 -0
- data/spec/concerns_spec.coffee +88 -0
- data/spec/core/container_spec.coffee +74 -12
- data/spec/core/model_spec.coffee +6 -1
- data/spec/define_spec.coffee +0 -6
- data/spec/util_spec.coffee +24 -0
- data/src/components/application.coffee +32 -30
- data/src/components/base_toolbar.coffee +6 -4
- data/src/components/collection_loader_view.coffee +3 -1
- data/src/components/collection_view.coffee +42 -21
- data/src/components/controller.coffee +3 -1
- data/src/components/fields/button_field.coffee +19 -12
- data/src/components/fields/checkbox_array.coffee +8 -2
- data/src/components/fields/checkbox_field.coffee +18 -9
- data/src/components/fields/file_upload_field.coffee +5 -1
- data/src/components/fields/hidden_field.coffee +3 -1
- data/src/components/fields/label_field.coffee +4 -3
- data/src/components/fields/select_field.coffee +7 -8
- data/src/components/fields/text_field.coffee +3 -1
- data/src/components/fields/type_ahead_field.coffee +4 -2
- data/src/components/form_button_toolbar.coffee +4 -1
- data/src/components/form_view.coffee +49 -44
- data/src/components/grid_view.coffee +1 -1
- data/src/components/multi_collection_view.coffee +49 -22
- data/src/components/pagination_control.coffee +17 -13
- data/src/{modules → concerns}/application_event_bindings.coffee +1 -1
- data/src/{modules → concerns}/collection_event_bindings.coffee +1 -1
- data/src/{modules → concerns}/deferrable.coffee +1 -1
- data/src/{modules → concerns}/dom_helpers.coffee +11 -2
- data/src/{modules → concerns}/enhanced_properties.coffee +1 -1
- data/src/concerns/filterable.coffee +82 -0
- data/src/{modules → concerns}/grid_layout.coffee +1 -1
- data/src/{modules → concerns}/loadmaskable.coffee +1 -1
- data/src/{modules → concerns}/local_storage.coffee +0 -0
- data/src/{modules → concerns}/modal_view.coffee +1 -1
- data/src/concerns/model_presenter.coffee +23 -0
- data/src/concerns/paginatable.coffee +87 -0
- data/src/{modules → concerns}/state_model.coffee +1 -1
- data/src/{modules → concerns}/templating.coffee +1 -1
- data/src/concerns.coffee +70 -0
- data/src/containers/tab_view.coffee +7 -10
- data/src/core/collection.coffee +17 -1
- data/src/core/container.coffee +56 -31
- data/src/core/field.coffee +39 -38
- data/src/core/meta_data.coffee +37 -0
- data/src/core/model.coffee +18 -1
- data/src/core/view.coffee +25 -29
- data/src/define.coffee +54 -66
- data/src/framework.coffee +23 -18
- data/src/index.coffee +3 -1
- data/src/stylesheets/components/checkbox_array.scss +1 -1
- data/src/stylesheets/components/form_view.scss +5 -5
- data/src/stylesheets/components/viewport.scss +2 -1
- data/src/stylesheets/containers/container.scss +0 -5
- data/src/stylesheets/containers/tab_view.scss +5 -5
- data/src/tools/console.coffee +5 -5
- data/src/util.coffee +47 -0
- data/vendor/assets/javascripts/luca-ui-development-tools.js +5 -5
- data/vendor/assets/javascripts/luca-ui-development-tools.min.js +1 -1
- data/vendor/assets/javascripts/luca-ui-full.js +905 -416
- data/vendor/assets/javascripts/luca-ui-full.min.js +5 -5
- data/vendor/assets/javascripts/luca-ui.js +905 -416
- data/vendor/assets/javascripts/luca-ui.min.js +5 -4
- data/vendor/assets/stylesheets/luca-ui.css +15 -15
- metadata +27 -17
- data/spec/mixin_spec.coffee +0 -49
- data/src/modules/filterable.coffee +0 -60
- data/src/modules/paginatable.coffee +0 -79
@@ -1,42 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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:
|
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"
|
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
|
-
|
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.
|
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.
|
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.
|
28
|
-
|
29
|
-
|
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 "
|
51
|
+
@on "refresh", @refresh, @
|
52
52
|
@on "after:card:switch", @refresh, @
|
53
|
-
@on "
|
54
|
-
|
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
|
-
|
62
|
-
|
63
|
-
getCollection: Luca.components.CollectionView::getCollection
|
64
|
-
|
65
|
-
#### Private Helpers
|
65
|
+
getCollection: ()->
|
66
|
+
@collection
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
83
|
-
|
84
|
-
|
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 @, "
|
18
|
+
_.bindAll @, "updateWithPageCount"
|
19
19
|
|
20
|
-
@state
|
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
|
-
|
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
|
-
|
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.
|
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
|
|
@@ -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 )
|
File without changes
|
@@ -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
|
+
|