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.
- data/.gitignore +5 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +77 -0
- data/Guardfile +22 -0
- data/README.md +291 -0
- data/Rakefile +28 -0
- data/app.rb +46 -0
- data/assets/images/glyphicons-halflings-white.png +0 -0
- data/assets/images/glyphicons-halflings.png +0 -0
- data/assets/javascripts/dependencies/backbone-min.js +37 -0
- data/assets/javascripts/dependencies/backbone-query.min.js +1 -0
- data/assets/javascripts/dependencies/bootstrap.min.js +1 -0
- data/assets/javascripts/dependencies/jasmine-html.js +190 -0
- data/assets/javascripts/dependencies/jasmine.js +2476 -0
- data/assets/javascripts/dependencies/jquery.js +4 -0
- data/assets/javascripts/dependencies/modal.js +698 -0
- data/assets/javascripts/dependencies/modernizr.min.js +30 -0
- data/assets/javascripts/dependencies/prettify.js +28 -0
- data/assets/javascripts/dependencies/sinon.js +3469 -0
- data/assets/javascripts/dependencies/spin-min.js +2 -0
- data/assets/javascripts/dependencies/underscore-min.js +31 -0
- data/assets/javascripts/dependencies/underscore-string.min.js +14 -0
- data/assets/javascripts/dependencies.coffee +7 -0
- data/assets/javascripts/luca-ui-base.coffee +12 -0
- data/assets/javascripts/luca-ui-spec.coffee +2 -0
- data/assets/javascripts/luca-ui.coffee +3 -0
- data/assets/javascripts/sandbox/collections/sample.coffee +0 -0
- data/assets/javascripts/sandbox/config.coffee +7 -0
- data/assets/javascripts/sandbox/sandbox.coffee +16 -0
- data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +33 -0
- data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +48 -0
- data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +24 -0
- data/assets/javascripts/sandbox/templates/features/introduction.luca +11 -0
- data/assets/javascripts/sandbox/templates/features/view_helpers.luca +43 -0
- data/assets/javascripts/sandbox/templates/navigation.luca +8 -0
- data/assets/javascripts/sandbox/views/form_demo.coffee +47 -0
- data/assets/javascripts/sandbox/views/grid_demo.coffee +23 -0
- data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +1 -0
- data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +28 -0
- data/assets/javascripts/sandbox.coffee +4 -0
- data/assets/javascripts/spec-dependencies.coffee +4 -0
- data/assets/stylesheets/bootstrap-responsive.min.css +3 -0
- data/assets/stylesheets/bootstrap.min.css +610 -0
- data/assets/stylesheets/jasmine.css +166 -0
- data/assets/stylesheets/luca-ui-bootstrap.css +5 -0
- data/assets/stylesheets/luca-ui-spec.css +3 -0
- data/assets/stylesheets/luca-ui.css +3 -0
- data/assets/stylesheets/prettify.css +40 -0
- data/assets/stylesheets/sandbox/sandbox.scss +4 -0
- data/assets/stylesheets/sandbox.css +3 -0
- data/config.ru +11 -0
- data/lib/luca/command_line.rb +69 -0
- data/lib/luca/rails/engine.rb +12 -0
- data/lib/luca/rails/version.rb +6 -0
- data/lib/luca/rails.rb +9 -0
- data/lib/luca/template.rb +51 -0
- data/lib/luca/test_harness.rb +106 -0
- data/lib/luca.rb +1 -0
- data/lib/sprockets/luca_template.rb +49 -0
- data/lib/templates/spec_manifest_javascripts.erb +7 -0
- data/lib/templates/spec_manifest_stylesheets.erb +11 -0
- data/luca.gemspec +26 -0
- data/public/jasmine/index.html +26 -0
- data/public/sandbox/api.js +1 -0
- data/spec/components/application_spec.coffee +0 -0
- data/spec/components/collection_loader_view_spec.coffee +0 -0
- data/spec/components/controller_spec.coffee +0 -0
- data/spec/components/form_view_spec.coffee +13 -0
- data/spec/components/grid_view_spec.coffee +0 -0
- data/spec/components/record_manager_spec.coffee +0 -0
- data/spec/components/template_spec.coffee +0 -0
- data/spec/containers/card_view_spec.coffee +1 -0
- data/spec/containers/column_view_spec.coffee +0 -0
- data/spec/containers/modal_view_spec.coffee +0 -0
- data/spec/containers/panel_view_spec.coffee +0 -0
- data/spec/containers/split_view_spec.coffee +0 -0
- data/spec/containers/tab_view_spec.coffee +0 -0
- data/spec/containers/viewport_spec.coffee +0 -0
- data/spec/core/collection_spec.coffee +215 -0
- data/spec/core/container_spec.coffee +0 -0
- data/spec/core/field_spec.coffee +0 -0
- data/spec/core/observer_spec.coffee +0 -0
- data/spec/core/view_spec.coffee +87 -0
- data/spec/framework_spec.coffee +48 -0
- data/spec/helper.coffee +120 -0
- data/spec/managers/collection_manager_spec.coffee +95 -0
- data/spec/managers/socket_manager_spec.coffee +0 -0
- data/src/components/application.coffee +83 -0
- data/src/components/base_toolbar.coffee +16 -0
- data/src/components/collection_loader_view.coffee +37 -0
- data/src/components/controller.coffee +41 -0
- data/src/components/fields/button_field.coffee +40 -0
- data/src/components/fields/checkbox_field.coffee +41 -0
- data/src/components/fields/file_upload_field.coffee +15 -0
- data/src/components/fields/hidden_field.coffee +18 -0
- data/src/components/fields/select_field.coffee +100 -0
- data/src/components/fields/text_area_field.coffee +43 -0
- data/src/components/fields/text_field.coffee +42 -0
- data/src/components/fields/type_ahead_field.coffee +10 -0
- data/src/components/form_button_toolbar.coffee +26 -0
- data/src/components/form_view.coffee +205 -0
- data/src/components/grid_view.coffee +208 -0
- data/src/components/record_manager.coffee +215 -0
- data/src/components/router.coffee +34 -0
- data/src/components/template.coffee +19 -0
- data/src/containers/card_view.coffee +89 -0
- data/src/containers/column_view.coffee +48 -0
- data/src/containers/modal_view.coffee +85 -0
- data/src/containers/panel_view.coffee +24 -0
- data/src/containers/split_view.coffee +12 -0
- data/src/containers/tab_view.coffee +77 -0
- data/src/containers/viewport.coffee +16 -0
- data/src/core/collection.coffee +319 -0
- data/src/core/container.coffee +256 -0
- data/src/core/field.coffee +68 -0
- data/src/core/observer.coffee +17 -0
- data/src/core/view.coffee +190 -0
- data/src/framework.coffee +110 -0
- data/src/index.coffee +255 -0
- data/src/managers/collection_manager.coffee +168 -0
- data/src/managers/socket_manager.coffee +54 -0
- data/src/modules/deferrable.coffee +18 -0
- data/src/modules/local_storage.coffee +50 -0
- data/src/stylesheets/base.scss +78 -0
- data/src/stylesheets/components/form_view.scss +54 -0
- data/src/stylesheets/components/grid_view.scss +111 -0
- data/src/stylesheets/components/toolbar.scss +15 -0
- data/src/stylesheets/containers/container.scss +7 -0
- data/src/stylesheets/containers/modal_view.scss +0 -0
- data/src/stylesheets/containers/tab_view.scss +33 -0
- data/src/stylesheets/normalize.scss +430 -0
- data/src/templates/components/bootstrap_form_controls.luca +7 -0
- data/src/templates/components/collection_loader_view.luca +5 -0
- data/src/templates/components/form_view.luca +15 -0
- data/src/templates/components/grid_view.luca +9 -0
- data/src/templates/components/grid_view_empty_text.luca +3 -0
- data/src/templates/containers/basic.luca +1 -0
- data/src/templates/containers/tab_selector_container.luca +8 -0
- data/src/templates/containers/tab_view.luca +1 -0
- data/src/templates/containers/toolbar_wrapper.luca +1 -0
- data/src/templates/fields/button_field.luca +2 -0
- data/src/templates/fields/button_field_link.luca +5 -0
- data/src/templates/fields/checkbox_field.luca +9 -0
- data/src/templates/fields/file_upload_field.luca +8 -0
- data/src/templates/fields/hidden_field.luca +1 -0
- data/src/templates/fields/select_field.luca +7 -0
- data/src/templates/fields/text_area_field.luca +8 -0
- data/src/templates/fields/text_field.luca +13 -0
- data/src/templates/sample/contents.luca +1 -0
- data/src/templates/sample/welcome.luca +1 -0
- data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
- data/vendor/assets/images/glyphicons-halflings.png +0 -0
- data/vendor/assets/javascripts/luca-spec-dependencies.js +6135 -0
- data/vendor/assets/javascripts/luca-ui-base.js +1527 -0
- data/vendor/assets/javascripts/luca-ui-spec.js +3654 -0
- data/vendor/assets/javascripts/luca-ui.js +2763 -0
- data/vendor/assets/luca-ui/base.css +85 -0
- data/vendor/assets/luca-ui/components/application.js +91 -0
- data/vendor/assets/luca-ui/components/base_toolbar.js +23 -0
- data/vendor/assets/luca-ui/components/controller.js +38 -0
- data/vendor/assets/luca-ui/components/fields/button_field.js +45 -0
- data/vendor/assets/luca-ui/components/fields/checkbox_field.js +43 -0
- data/vendor/assets/luca-ui/components/fields/file_upload_field.js +20 -0
- data/vendor/assets/luca-ui/components/fields/hidden_field.js +20 -0
- data/vendor/assets/luca-ui/components/fields/select_field.js +97 -0
- data/vendor/assets/luca-ui/components/fields/text_area_field.js +48 -0
- data/vendor/assets/luca-ui/components/fields/text_field.js +46 -0
- data/vendor/assets/luca-ui/components/fields/type_ahead_field.js +13 -0
- data/vendor/assets/luca-ui/components/form_button_toolbar.js +32 -0
- data/vendor/assets/luca-ui/components/form_view.css +32 -0
- data/vendor/assets/luca-ui/components/form_view.js +207 -0
- data/vendor/assets/luca-ui/components/grid_view.css +76 -0
- data/vendor/assets/luca-ui/components/grid_view.js +202 -0
- data/vendor/assets/luca-ui/components/record_manager.js +207 -0
- data/vendor/assets/luca-ui/components/router.js +36 -0
- data/vendor/assets/luca-ui/components/template.js +26 -0
- data/vendor/assets/luca-ui/components/toolbar.css +11 -0
- data/vendor/assets/luca-ui/containers/card_view.js +98 -0
- data/vendor/assets/luca-ui/containers/column_view.js +52 -0
- data/vendor/assets/luca-ui/containers/container.css +3 -0
- data/vendor/assets/luca-ui/containers/modal_view.css +0 -0
- data/vendor/assets/luca-ui/containers/modal_view.js +87 -0
- data/vendor/assets/luca-ui/containers/panel_view.js +34 -0
- data/vendor/assets/luca-ui/containers/split_view.js +13 -0
- data/vendor/assets/luca-ui/containers/tab_view.css +16 -0
- data/vendor/assets/luca-ui/containers/tab_view.js +80 -0
- data/vendor/assets/luca-ui/containers/viewport.js +18 -0
- data/vendor/assets/luca-ui/core/collection.js +221 -0
- data/vendor/assets/luca-ui/core/container.js +205 -0
- data/vendor/assets/luca-ui/core/field.js +59 -0
- data/vendor/assets/luca-ui/core/observer.js +42 -0
- data/vendor/assets/luca-ui/core/view.js +127 -0
- data/vendor/assets/luca-ui/framework.js +110 -0
- data/vendor/assets/luca-ui/index.js +5 -0
- data/vendor/assets/luca-ui/managers/collection_manager.js +98 -0
- data/vendor/assets/luca-ui/managers/socket_manager.js +52 -0
- data/vendor/assets/luca-ui/modules/deferrable.js +21 -0
- data/vendor/assets/luca-ui/modules/local_storage.js +81 -0
- data/vendor/assets/luca-ui/normalize.css +359 -0
- data/vendor/assets/luca-ui/stylesheets/base.css +85 -0
- data/vendor/assets/luca-ui/stylesheets/components/form_view.css +32 -0
- data/vendor/assets/luca-ui/stylesheets/components/grid_view.css +76 -0
- data/vendor/assets/luca-ui/stylesheets/components/toolbar.css +11 -0
- data/vendor/assets/luca-ui/stylesheets/containers/container.css +3 -0
- data/vendor/assets/luca-ui/stylesheets/containers/modal_view.css +0 -0
- data/vendor/assets/luca-ui/stylesheets/containers/tab_view.css +16 -0
- data/vendor/assets/luca-ui/stylesheets/normalize.css +359 -0
- data/vendor/assets/luca-ui/templates/components/bootstrap_form_controls.js +4 -0
- data/vendor/assets/luca-ui/templates/components/form_view.js +4 -0
- data/vendor/assets/luca-ui/templates/components/grid_view.js +4 -0
- data/vendor/assets/luca-ui/templates/components/grid_view_empty_text.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/basic.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/tab_selector_container.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/tab_view.js +4 -0
- data/vendor/assets/luca-ui/templates/containers/toolbar_wrapper.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/button_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/button_field_link.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/checkbox_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/file_upload_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/hidden_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/select_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/text_area_field.js +4 -0
- data/vendor/assets/luca-ui/templates/fields/text_field.js +4 -0
- data/vendor/assets/luca-ui/templates/sample/contents.js +4 -0
- data/vendor/assets/luca-ui/templates/sample/welcome.js +4 -0
- data/vendor/assets/stylesheets/luca-spec-dependencies.css +166 -0
- data/vendor/assets/stylesheets/luca-ui-bootstrap.css +1201 -0
- data/vendor/assets/stylesheets/luca-ui-spec.css +586 -0
- data/vendor/assets/stylesheets/luca-ui.css +586 -0
- data/views/index.erb +20 -0
- data/views/jasmine.erb +22 -0
- data/views/spec_harness.erb +29 -0
- metadata +361 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Luca.containers.CardView = Luca.core.Container.extend
|
|
2
|
+
componentType: 'card_view'
|
|
3
|
+
|
|
4
|
+
className: 'luca-ui-card-view-wrapper'
|
|
5
|
+
|
|
6
|
+
activeCard: 0
|
|
7
|
+
|
|
8
|
+
components: []
|
|
9
|
+
|
|
10
|
+
hooks:[
|
|
11
|
+
'before:card:switch',
|
|
12
|
+
'after:card:switch'
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
initialize: (@options)->
|
|
16
|
+
Luca.core.Container::initialize.apply @,arguments
|
|
17
|
+
@setupHooks(@hooks)
|
|
18
|
+
|
|
19
|
+
componentClass: 'luca-ui-card'
|
|
20
|
+
|
|
21
|
+
beforeLayout: ()->
|
|
22
|
+
@cards = _(@components).map (card,cardIndex) =>
|
|
23
|
+
classes: @componentClass
|
|
24
|
+
style: "display:#{ (if cardIndex is @activeCard then 'block' else 'none' )}"
|
|
25
|
+
id: "#{ @cid }-#{ cardIndex }"
|
|
26
|
+
|
|
27
|
+
prepareLayout: ()->
|
|
28
|
+
@card_containers = _( @cards ).map (card, index)=>
|
|
29
|
+
@$el.append Luca.templates["containers/basic"](card)
|
|
30
|
+
$("##{ card.id }")
|
|
31
|
+
|
|
32
|
+
prepareComponents: ()->
|
|
33
|
+
@components = _( @components ).map (object,index)=>
|
|
34
|
+
card = @cards[index]
|
|
35
|
+
object.container = "##{ card.id }"
|
|
36
|
+
object
|
|
37
|
+
|
|
38
|
+
activeComponent: ()->
|
|
39
|
+
@getComponent( @activeCard )
|
|
40
|
+
|
|
41
|
+
cycle: ()->
|
|
42
|
+
nextIndex = if @activeCard < @components.length - 1 then @activeCard + 1 else 0
|
|
43
|
+
@activate( nextIndex )
|
|
44
|
+
|
|
45
|
+
find: (name)->
|
|
46
|
+
@findComponentByName(name,true)
|
|
47
|
+
|
|
48
|
+
firstActivation: ()->
|
|
49
|
+
@activeComponent().trigger "first:activation", @, @activeComponent()
|
|
50
|
+
|
|
51
|
+
activate: (index, silent=false, callback)->
|
|
52
|
+
if _.isFunction(silent)
|
|
53
|
+
silent = false
|
|
54
|
+
callback = silent
|
|
55
|
+
|
|
56
|
+
return if index is @activeCard
|
|
57
|
+
|
|
58
|
+
previous = @activeComponent()
|
|
59
|
+
current = @getComponent(index)
|
|
60
|
+
|
|
61
|
+
if !current
|
|
62
|
+
index = @indexOf(index)
|
|
63
|
+
current = @getComponent( index )
|
|
64
|
+
|
|
65
|
+
return unless current
|
|
66
|
+
|
|
67
|
+
@trigger "before:card:switch", previous, current unless silent
|
|
68
|
+
|
|
69
|
+
_( @card_containers ).each (container)->
|
|
70
|
+
container.trigger?.apply(container, ["deactivation", @, previous, current])
|
|
71
|
+
container.hide()
|
|
72
|
+
|
|
73
|
+
unless current.previously_activated
|
|
74
|
+
current.trigger "first:activation"
|
|
75
|
+
current.previously_activated = true
|
|
76
|
+
|
|
77
|
+
$( current.container ).show()
|
|
78
|
+
|
|
79
|
+
@activeCard = index
|
|
80
|
+
|
|
81
|
+
unless silent
|
|
82
|
+
@trigger "after:card:switch", previous, current
|
|
83
|
+
current.trigger?.apply(current, ["activation", @, previous, current])
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if _.isFunction(callback)
|
|
87
|
+
callback.apply @, [@,previous,current]
|
|
88
|
+
|
|
89
|
+
Luca.register 'card_view', "Luca.containers.CardView"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Luca.containers.ColumnView = Luca.core.Container.extend
|
|
2
|
+
componentType: 'column_view'
|
|
3
|
+
|
|
4
|
+
className: 'luca-ui-column-view'
|
|
5
|
+
|
|
6
|
+
components: []
|
|
7
|
+
|
|
8
|
+
initialize: (@options={})->
|
|
9
|
+
Luca.core.Container::initialize.apply @, arguments
|
|
10
|
+
@setColumnWidths()
|
|
11
|
+
|
|
12
|
+
componentClass: 'luca-ui-column'
|
|
13
|
+
|
|
14
|
+
containerTemplate: "containers/basic"
|
|
15
|
+
|
|
16
|
+
appendContainers: true
|
|
17
|
+
|
|
18
|
+
autoColumnWidths: ()->
|
|
19
|
+
widths = []
|
|
20
|
+
|
|
21
|
+
_( @components.length ).times ()=>
|
|
22
|
+
widths.push( parseInt( 100 / @components.length ) )
|
|
23
|
+
|
|
24
|
+
widths
|
|
25
|
+
|
|
26
|
+
setColumnWidths: ()->
|
|
27
|
+
@columnWidths = if @layout?
|
|
28
|
+
_( @layout.split('/') ).map((v)-> parseInt(v) )
|
|
29
|
+
else
|
|
30
|
+
@autoColumnWidths()
|
|
31
|
+
|
|
32
|
+
@columnWidths = _( @columnWidths ).map (val)-> "#{ val }%"
|
|
33
|
+
|
|
34
|
+
beforeComponents: ()->
|
|
35
|
+
@debug "column_view before components"
|
|
36
|
+
_( @components ).each (component)->
|
|
37
|
+
component.ctype ||= "panel_view"
|
|
38
|
+
|
|
39
|
+
beforeLayout: ()->
|
|
40
|
+
@debug "column_view before layout"
|
|
41
|
+
|
|
42
|
+
_(@columnWidths).each (width,index) =>
|
|
43
|
+
@components[index].float = "left"
|
|
44
|
+
@components[index].width = width
|
|
45
|
+
|
|
46
|
+
Luca.core.Container::beforeLayout?.apply @, arguments
|
|
47
|
+
|
|
48
|
+
Luca.register 'column_view', "Luca.containers.ColumnView"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Luca.containers.ModalView = Luca.core.Container.extend
|
|
2
|
+
componentType: 'modal_view'
|
|
3
|
+
|
|
4
|
+
className: 'luca-ui-modal-view'
|
|
5
|
+
|
|
6
|
+
components:[]
|
|
7
|
+
|
|
8
|
+
renderOnInitialize: true
|
|
9
|
+
|
|
10
|
+
showOnRender: false
|
|
11
|
+
|
|
12
|
+
hooks:[
|
|
13
|
+
'before:show',
|
|
14
|
+
'before:hide'
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
defaultModalOptions:
|
|
18
|
+
minWidth: 375
|
|
19
|
+
maxWidth: 375
|
|
20
|
+
minHeight: 550
|
|
21
|
+
maxHeight: 550
|
|
22
|
+
opacity: 80
|
|
23
|
+
onOpen: (modal)->
|
|
24
|
+
@onOpen.apply @
|
|
25
|
+
@onModalOpen.apply modal, [modal, @]
|
|
26
|
+
onClose: (modal)->
|
|
27
|
+
@onClose.apply @
|
|
28
|
+
@onModalClose.apply modal, [modal, @]
|
|
29
|
+
|
|
30
|
+
modalOptions: {}
|
|
31
|
+
|
|
32
|
+
initialize: (@options={})->
|
|
33
|
+
Luca.core.Container::initialize.apply @,arguments
|
|
34
|
+
@setupHooks(@hooks)
|
|
35
|
+
|
|
36
|
+
_( @defaultModalOptions ).each (value,setting) => @modalOptions[ setting ] ||= value
|
|
37
|
+
|
|
38
|
+
@modalOptions.onOpen = _.bind( @modalOptions.onOpen, @)
|
|
39
|
+
@modalOptions.onClose = _.bind( @modalOptions.onClose, @)
|
|
40
|
+
|
|
41
|
+
# this will get called within the context of the modal view
|
|
42
|
+
onOpen: ()-> true
|
|
43
|
+
|
|
44
|
+
# this will get called within the context of the modal view
|
|
45
|
+
onClose: ()-> true
|
|
46
|
+
|
|
47
|
+
getModal: ()-> @modal
|
|
48
|
+
|
|
49
|
+
# this will be called within the context of the simple modal object
|
|
50
|
+
onModalOpen: (modal, view)->
|
|
51
|
+
view.modal = modal
|
|
52
|
+
|
|
53
|
+
modal.overlay.show()
|
|
54
|
+
modal.container.show()
|
|
55
|
+
modal.data.show()
|
|
56
|
+
|
|
57
|
+
# this will be called within the context of the simple modal object
|
|
58
|
+
onModalClose: (modal, view)->
|
|
59
|
+
$.modal.close()
|
|
60
|
+
|
|
61
|
+
prepareLayout: ()->
|
|
62
|
+
$('body').append( @$el )
|
|
63
|
+
|
|
64
|
+
prepareComponents: ()->
|
|
65
|
+
@components = _(@components).map (object,index) =>
|
|
66
|
+
object.container = @el
|
|
67
|
+
object
|
|
68
|
+
|
|
69
|
+
afterInitialize: ()->
|
|
70
|
+
@$el.hide()
|
|
71
|
+
@render() if @renderOnInitialize
|
|
72
|
+
|
|
73
|
+
afterRender: ()->
|
|
74
|
+
@show() if @showOnRender
|
|
75
|
+
|
|
76
|
+
wrapper: ()-> $( @$el.parent() )
|
|
77
|
+
|
|
78
|
+
show: ()->
|
|
79
|
+
@trigger "before:show", @
|
|
80
|
+
@$el.modal( @modalOptions )
|
|
81
|
+
|
|
82
|
+
hide: ()->
|
|
83
|
+
@trigger "before:hide", @
|
|
84
|
+
|
|
85
|
+
Luca.register "modal_view","Luca.containers.ModalView"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Luca.containers.PanelView = Luca.core.Container.extend
|
|
2
|
+
className: 'luca-ui-panel'
|
|
3
|
+
|
|
4
|
+
initialize: (@options={})->
|
|
5
|
+
Luca.core.Container::initialize.apply @, arguments
|
|
6
|
+
|
|
7
|
+
afterLayout: ()->
|
|
8
|
+
if @template
|
|
9
|
+
contents = ( Luca.templates || JST )[ @template ]( @ )
|
|
10
|
+
@$el.html(contents)
|
|
11
|
+
|
|
12
|
+
render: ()->
|
|
13
|
+
$(@container).append @$el
|
|
14
|
+
|
|
15
|
+
afterRender: ()->
|
|
16
|
+
Luca.core.Container::afterRender?.apply @, arguments
|
|
17
|
+
if @css
|
|
18
|
+
console.log "Yes Yes Yall", @css, @$el
|
|
19
|
+
_( @css ).each (value,property)=>
|
|
20
|
+
@$el.css(property,value)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Luca.containers.SplitView = Luca.core.Container.extend
|
|
2
|
+
layout: '100'
|
|
3
|
+
|
|
4
|
+
componentType: 'split_view'
|
|
5
|
+
|
|
6
|
+
containerTemplate: 'containers/basic'
|
|
7
|
+
|
|
8
|
+
className: 'luca-ui-split-view'
|
|
9
|
+
|
|
10
|
+
componentClass: 'luca-ui-panel'
|
|
11
|
+
|
|
12
|
+
Luca.register 'split_view', "Luca.containers.SplitView"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Luca.containers.TabView = Luca.containers.CardView.extend
|
|
2
|
+
events:
|
|
3
|
+
"click ul.nav-tabs li" : "select"
|
|
4
|
+
|
|
5
|
+
hooks:[
|
|
6
|
+
"before:select"
|
|
7
|
+
"after:select"
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
componentType: 'tab_view'
|
|
11
|
+
|
|
12
|
+
className: 'luca-ui-tab-view tabbable'
|
|
13
|
+
|
|
14
|
+
tab_position: 'top'
|
|
15
|
+
|
|
16
|
+
tabVerticalOffset: '50px'
|
|
17
|
+
|
|
18
|
+
initialize: (@options={})->
|
|
19
|
+
Luca.containers.CardView::initialize.apply @, arguments
|
|
20
|
+
_.bindAll @, "select", "highlightSelectedTab"
|
|
21
|
+
@setupHooks( @hooks )
|
|
22
|
+
|
|
23
|
+
@bind "after:card:switch", @highlightSelectedTab
|
|
24
|
+
|
|
25
|
+
activeTabSelector: ()->
|
|
26
|
+
@tabSelectors().eq( @activeCard )
|
|
27
|
+
|
|
28
|
+
prepareLayout: ()->
|
|
29
|
+
@card_containers = _( @cards ).map (card, index)=>
|
|
30
|
+
@$('.tab-content').append Luca.templates["containers/basic"](card)
|
|
31
|
+
$("##{ card.id }")
|
|
32
|
+
|
|
33
|
+
beforeLayout: ()->
|
|
34
|
+
@$el.addClass("tabs-#{ @tab_position }")
|
|
35
|
+
|
|
36
|
+
if @tab_position is "below"
|
|
37
|
+
@$el.append Luca.templates["containers/tab_view"](@)
|
|
38
|
+
@$el.append Luca.templates["containers/tab_selector_container"](@)
|
|
39
|
+
else
|
|
40
|
+
@$el.append Luca.templates["containers/tab_selector_container"](@)
|
|
41
|
+
@$el.append Luca.templates["containers/tab_view"](@)
|
|
42
|
+
|
|
43
|
+
Luca.containers.CardView::beforeLayout.apply @, arguments
|
|
44
|
+
|
|
45
|
+
beforeRender: ()->
|
|
46
|
+
Luca.containers.CardView::beforeRender?.apply @, arguments
|
|
47
|
+
@activeTabSelector().addClass('active')
|
|
48
|
+
|
|
49
|
+
if Luca.enableBootstrap and @tab_position is "left" or @tab_position is "right"
|
|
50
|
+
@$el.addClass('grid-12')
|
|
51
|
+
@tabContainerWrapper().addClass('grid-3')
|
|
52
|
+
@tabContentWrapper().addClass('grid-9')
|
|
53
|
+
|
|
54
|
+
if @tabVerticalOffset
|
|
55
|
+
@tabContainerWrapper().css('padding-top', @tabVerticalOffset )
|
|
56
|
+
|
|
57
|
+
highlightSelectedTab: ()->
|
|
58
|
+
@tabSelectors().removeClass('active')
|
|
59
|
+
@activeTabSelector().addClass('active')
|
|
60
|
+
|
|
61
|
+
select: (e)->
|
|
62
|
+
me = my = $( e.currentTarget )
|
|
63
|
+
@trigger "before:select", @
|
|
64
|
+
@activate my.data('target')
|
|
65
|
+
@trigger "after:select", @
|
|
66
|
+
|
|
67
|
+
tabContentWrapper: ()->
|
|
68
|
+
$("##{ @cid }-tab-view-content")
|
|
69
|
+
|
|
70
|
+
tabContainerWrapper: ()->
|
|
71
|
+
$("##{ @cid }-tabs-selector")
|
|
72
|
+
|
|
73
|
+
tabContainer: ()->
|
|
74
|
+
$("ul##{ @cid }-tabs-nav")
|
|
75
|
+
|
|
76
|
+
tabSelectors: ()->
|
|
77
|
+
$( 'li.tab-selector', @tabContainer() )
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Luca.containers.Viewport = Luca.containers.CardView.extend
|
|
2
|
+
activeItem: 0
|
|
3
|
+
|
|
4
|
+
className: 'luca-ui-viewport'
|
|
5
|
+
|
|
6
|
+
fullscreen: true
|
|
7
|
+
|
|
8
|
+
initialize: (@options={})->
|
|
9
|
+
Luca.core.Container::initialize.apply(@, arguments)
|
|
10
|
+
|
|
11
|
+
$('html,body').addClass('luca-ui-fullscreen') if @fullscreen
|
|
12
|
+
|
|
13
|
+
render: ()->
|
|
14
|
+
console.log "Rendering Viewport"
|
|
15
|
+
@$el.addClass('luca-ui-viewport')
|
|
16
|
+
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Luca.Collection
|
|
2
|
+
#
|
|
3
|
+
# Luca.Collection is an extenstion of Backbone.Collection which provides
|
|
4
|
+
# a bunch of commonly used patterns for doing things like:
|
|
5
|
+
#
|
|
6
|
+
# - setting base parameters used on every request to your REST API
|
|
7
|
+
#
|
|
8
|
+
# - bootstrapping a collection of objects which are
|
|
9
|
+
# rendered in your markup on page load
|
|
10
|
+
#
|
|
11
|
+
# - filtering with query string parameters against your API
|
|
12
|
+
#
|
|
13
|
+
# - automatic interaction with your Luca.CollectionManager class
|
|
14
|
+
#
|
|
15
|
+
# - make it easier to parse Rails style responses which include the root
|
|
16
|
+
# by specifying a @root parameter
|
|
17
|
+
#
|
|
18
|
+
# - use backbone-query if available
|
|
19
|
+
#
|
|
20
|
+
# - onceLoaded: run a callback once if there are models present, otherwise wait until
|
|
21
|
+
# the collection fetches
|
|
22
|
+
#
|
|
23
|
+
# - ifLoaded: run a callback any time the model gets reset, or if there are already models
|
|
24
|
+
#
|
|
25
|
+
Luca.Collection = (Backbone.QueryCollection || Backbone.Collection).extend
|
|
26
|
+
|
|
27
|
+
initialize: (models=[], @options)->
|
|
28
|
+
_.extend @, @options
|
|
29
|
+
|
|
30
|
+
# By specifying a @cached property or method, you can instruct
|
|
31
|
+
# Luca.Collection instances where to pull an array of model attributes
|
|
32
|
+
# usually done with the bootstrap functionality provided.
|
|
33
|
+
if @cached
|
|
34
|
+
@bootstrap_cache_key = if _.isFunction( @cached ) then @cached() else @cached
|
|
35
|
+
|
|
36
|
+
if @registerAs or @registerWith
|
|
37
|
+
console.log "This configuration API is deprecated. use @name and @manager properties instead"
|
|
38
|
+
|
|
39
|
+
# support the older configuration API
|
|
40
|
+
@name ||= @registerAs
|
|
41
|
+
@manager ||= @registerWith
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# if they specify a
|
|
45
|
+
if @name and not @manager
|
|
46
|
+
@manager = Luca.CollectionManager.get()
|
|
47
|
+
|
|
48
|
+
# If we are going to be registering this collection with the CollectionManager
|
|
49
|
+
# class, then we need to specify a key to register ourselves under. @registerAs can be
|
|
50
|
+
# as simple as something as "books", or if you are using collections which need
|
|
51
|
+
# to be scoped with some sort of unique id, as say some sort of belongsTo relationship
|
|
52
|
+
# then you can specify @registerAs as a method()
|
|
53
|
+
if @manager
|
|
54
|
+
@name ||= @cached()
|
|
55
|
+
@name = if _.isFunction( @name ) then @name() else @name
|
|
56
|
+
|
|
57
|
+
unless @private or @anonymous
|
|
58
|
+
@bind "after:initialize", ()=>
|
|
59
|
+
@register( @manager, @name, @)
|
|
60
|
+
|
|
61
|
+
# by passing useLocalStorage = true to your collection definition
|
|
62
|
+
# you will bypass the RESTful persistence layer and just persist everything
|
|
63
|
+
# locally in localStorage
|
|
64
|
+
if @useLocalStorage is true and window.localStorage?
|
|
65
|
+
table = @bootstrap_cache_key || @name
|
|
66
|
+
throw "Must specify either a cached or registerAs property to use localStorage"
|
|
67
|
+
@localStorage = new Luca.LocalStore( table )
|
|
68
|
+
|
|
69
|
+
# Populating a collection with local data
|
|
70
|
+
#
|
|
71
|
+
# by specifying a @data property which is an array
|
|
72
|
+
# then you can set the collection to be a @memoryCollection
|
|
73
|
+
# which never interacts with a persistence layer at all.
|
|
74
|
+
#
|
|
75
|
+
# this is mainly used by the Luca.fields.SelectField class for
|
|
76
|
+
# generating simple select fields with static data
|
|
77
|
+
if _.isArray(@data) and @data.length > 0
|
|
78
|
+
@memoryCollection = true
|
|
79
|
+
|
|
80
|
+
@__wrapUrl() unless @useNormalUrl is true
|
|
81
|
+
|
|
82
|
+
Backbone.Collection.prototype.initialize.apply @, [models, @options]
|
|
83
|
+
|
|
84
|
+
@trigger "after:initialize"
|
|
85
|
+
|
|
86
|
+
#### Automatic Query String Generation
|
|
87
|
+
#
|
|
88
|
+
# Luca.Collections will append a query string to the URL
|
|
89
|
+
# and will automatically do this for you without you having
|
|
90
|
+
# to write a special url handler. If you want to use a normal
|
|
91
|
+
# url without this feature, just set @useNormalUrl = true
|
|
92
|
+
__wrapUrl: ()->
|
|
93
|
+
if _.isFunction(@url)
|
|
94
|
+
@url = _.wrap @url, (fn)=>
|
|
95
|
+
val = fn.apply @
|
|
96
|
+
parts = val.split('?')
|
|
97
|
+
|
|
98
|
+
existing_params = _.last(parts) if parts.length > 1
|
|
99
|
+
|
|
100
|
+
queryString = @queryString()
|
|
101
|
+
|
|
102
|
+
if existing_params and val.match(existing_params)
|
|
103
|
+
queryString = queryString.replace( existing_params, '')
|
|
104
|
+
|
|
105
|
+
new_val = "#{ val }?#{ queryString }"
|
|
106
|
+
new_val = new_val.replace(/\?$/,'') if new_val.match(/\?$/)
|
|
107
|
+
|
|
108
|
+
new_val
|
|
109
|
+
else
|
|
110
|
+
url = @url
|
|
111
|
+
params = @queryString()
|
|
112
|
+
|
|
113
|
+
@url = _([url,params]).compact().join("?")
|
|
114
|
+
|
|
115
|
+
queryString: ()->
|
|
116
|
+
parts = _( @base_params ||= Luca.Collection.baseParams() ).inject (memo, value, key)=>
|
|
117
|
+
str = "#{ key }=#{ value }"
|
|
118
|
+
memo.push(str)
|
|
119
|
+
memo
|
|
120
|
+
, []
|
|
121
|
+
|
|
122
|
+
_.uniq(parts).join("&")
|
|
123
|
+
|
|
124
|
+
resetFilter: ()->
|
|
125
|
+
@base_params = Luca.Collection.baseParams()
|
|
126
|
+
@
|
|
127
|
+
|
|
128
|
+
# Applying a filter to a collection, will automatically apply
|
|
129
|
+
# the filter parameters and then call fetch. passing an additional
|
|
130
|
+
# options hash will pass these options to the call to @fetch()
|
|
131
|
+
# setting refresh to true, forcing a remote call to the REST API
|
|
132
|
+
applyFilter: (filter={}, options={})->
|
|
133
|
+
@applyParams(filter)
|
|
134
|
+
@fetch _.extend(options,refresh:true)
|
|
135
|
+
|
|
136
|
+
# You can apply params to a collection, so that any upcoming requests
|
|
137
|
+
# made to the REST API are made with the key values specified
|
|
138
|
+
applyParams: (params)->
|
|
139
|
+
@base_params ||= Luca.Collection.baseParams()
|
|
140
|
+
_.extend @base_params, params
|
|
141
|
+
|
|
142
|
+
# Collection Manager Registry
|
|
143
|
+
#
|
|
144
|
+
# If this collection is to be registered with some global collection
|
|
145
|
+
# tracker such as new Luca.CollectionManager() then we will register
|
|
146
|
+
# ourselves automatically
|
|
147
|
+
#
|
|
148
|
+
# To automatically register a collection with the registry, instantiate
|
|
149
|
+
# it with the registerWith property, which can either be a reference to
|
|
150
|
+
# the manager itself, or a string in case the manager isn't available
|
|
151
|
+
# at compile time
|
|
152
|
+
register: (collectionManager=Luca.CollectionManager.get(), key="", collection)->
|
|
153
|
+
throw "Can not register with a collection manager without a key" unless key.length >= 1
|
|
154
|
+
throw "Can not register with a collection manager without a valid collection manager" unless collectionManager?
|
|
155
|
+
|
|
156
|
+
# by passing a string instead of a reference to an object, we can look up
|
|
157
|
+
# that object only when necessary. this prevents us from having to create
|
|
158
|
+
# the manager instance before we can define our collections
|
|
159
|
+
if _.isString( collectionManager )
|
|
160
|
+
collectionManager = Luca.util.nestedValue( collectionManager, (window || global) )
|
|
161
|
+
|
|
162
|
+
throw "Could not register with collection manager" unless collectionManager
|
|
163
|
+
|
|
164
|
+
if _.isFunction( collectionManager.add )
|
|
165
|
+
return collectionManager.add(key, collection)
|
|
166
|
+
|
|
167
|
+
if _.isObject( collectionManager )
|
|
168
|
+
collectionManager[ key ] = collection
|
|
169
|
+
|
|
170
|
+
# A Luca.Collection will load models from the in memory model store
|
|
171
|
+
# returned from Luca.Collection.cache, where the key returned from
|
|
172
|
+
# the @cached attribute or method matches the key of the model cache
|
|
173
|
+
loadFromBootstrap: ()->
|
|
174
|
+
return unless @bootstrap_cache_key
|
|
175
|
+
@reset @cached_models()
|
|
176
|
+
@trigger "bootstrapped", @
|
|
177
|
+
|
|
178
|
+
# an alias for loadFromBootstrap which is a bit more descriptive
|
|
179
|
+
bootstrap: ()->
|
|
180
|
+
@loadFromBootstrap()
|
|
181
|
+
|
|
182
|
+
# cached_models is a reference to the Luca.Collection.cache object
|
|
183
|
+
# key'd on whatever this collection's bootstrap_cache_key is set to be
|
|
184
|
+
# via the @cached() interface
|
|
185
|
+
cached_models: ()->
|
|
186
|
+
Luca.Collection.cache( @bootstrap_cache_key )
|
|
187
|
+
|
|
188
|
+
# Luca.Collection overrides the default Backbone.Collection.fetch method
|
|
189
|
+
# and triggers an event "before:fetch" which gives you additional control
|
|
190
|
+
# over the process
|
|
191
|
+
#
|
|
192
|
+
# in addition, it loads models directly from the bootstrap cache instead
|
|
193
|
+
# of going directly to the API
|
|
194
|
+
fetch: (options={})->
|
|
195
|
+
@trigger "before:fetch", @
|
|
196
|
+
|
|
197
|
+
return @reset(@data) if @memoryCollection is true
|
|
198
|
+
|
|
199
|
+
# fetch will try to pull from the bootstrap if it is setup to do so
|
|
200
|
+
# you can actually make the roundtrip to the server anyway if you pass
|
|
201
|
+
# refresh = true in the options hash
|
|
202
|
+
return @bootstrap() if @cached_models().length and not options.refresh
|
|
203
|
+
|
|
204
|
+
url = if _.isFunction(@url) then @url() else @url
|
|
205
|
+
|
|
206
|
+
return true unless ((url and url.length > 1) or @localStorage)
|
|
207
|
+
|
|
208
|
+
@fetching = true
|
|
209
|
+
|
|
210
|
+
try
|
|
211
|
+
Backbone.Collection.prototype.fetch.apply @, arguments
|
|
212
|
+
catch e
|
|
213
|
+
console.log "Error in Collection.fetch", e
|
|
214
|
+
|
|
215
|
+
throw e
|
|
216
|
+
|
|
217
|
+
# onceLoaded is equivalent to binding to the
|
|
218
|
+
# reset trigger with a function wrapped in _.once
|
|
219
|
+
# so that it only gets run...ahem...once.
|
|
220
|
+
#
|
|
221
|
+
# that being said, if the collection already has models
|
|
222
|
+
# it won't even bother fetching it it will just run
|
|
223
|
+
# as if reset was already triggered
|
|
224
|
+
onceLoaded: (fn, options={autoFetch:true})->
|
|
225
|
+
if @length > 0 and not @fetching
|
|
226
|
+
fn.apply @, [@]
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
wrapped = ()=> fn.apply @,[@]
|
|
230
|
+
|
|
231
|
+
@bind "reset", ()->
|
|
232
|
+
wrapped()
|
|
233
|
+
@unbind "reset", @
|
|
234
|
+
|
|
235
|
+
unless @fetching or not options.autoFetch
|
|
236
|
+
@fetch()
|
|
237
|
+
|
|
238
|
+
# ifLoaded is equivalent to binding to the reset trigger with
|
|
239
|
+
# a function, if the collection already has models it will just
|
|
240
|
+
# run automatically. similar to onceLoaded except the binding
|
|
241
|
+
# stays in place
|
|
242
|
+
ifLoaded: (fn, options={scope:@,autoFetch:true})->
|
|
243
|
+
scope = options.scope || @
|
|
244
|
+
|
|
245
|
+
if @length > 0 and not @fetching
|
|
246
|
+
fn.apply scope, [@]
|
|
247
|
+
|
|
248
|
+
@bind "reset", (collection)=> fn.apply scope, [collection]
|
|
249
|
+
|
|
250
|
+
unless @fetching is true or !options.autoFetch or @length > 0
|
|
251
|
+
@fetch()
|
|
252
|
+
|
|
253
|
+
# parse is very close to the stock Backbone.Collection parse, which
|
|
254
|
+
# just returns the response. However, it also triggers a callback
|
|
255
|
+
# after:response, and automatically parses responses which contain
|
|
256
|
+
# a JSON root like you would see in rails, if you specify the @root
|
|
257
|
+
# property.
|
|
258
|
+
#
|
|
259
|
+
# it will also update the Luca.Collection.cache with the models from
|
|
260
|
+
# the response, so that any subsequent calls to fetch() on a bootstrapped
|
|
261
|
+
# collection, will have updated models from the server. Really only
|
|
262
|
+
# useful if you call fetch(refresh:true) manually on any bootstrapped
|
|
263
|
+
# collection
|
|
264
|
+
parse: (response)->
|
|
265
|
+
@fetching = false
|
|
266
|
+
@trigger "after:response", response
|
|
267
|
+
models = if @root? then response[ @root ] else response
|
|
268
|
+
|
|
269
|
+
if @bootstrap_cache_key
|
|
270
|
+
Luca.Collection.cache( @bootstrap_cache_key, models)
|
|
271
|
+
|
|
272
|
+
models
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# Global Collection Observer
|
|
276
|
+
_.extend Luca.Collection.prototype,
|
|
277
|
+
trigger: ()->
|
|
278
|
+
if Luca.enableGlobalObserver
|
|
279
|
+
Luca.CollectionObserver ||= new Luca.Observer(type:"collection")
|
|
280
|
+
Luca.CollectionObserver.relay(@, arguments)
|
|
281
|
+
|
|
282
|
+
Backbone.View.prototype.trigger.apply @, arguments
|
|
283
|
+
|
|
284
|
+
#### Base Parameters
|
|
285
|
+
#
|
|
286
|
+
# Always include these parameters in every request to your REST API.
|
|
287
|
+
#
|
|
288
|
+
# either specify a function which returns a hash, or just a normal hash
|
|
289
|
+
Luca.Collection.baseParams = (obj)->
|
|
290
|
+
return Luca.Collection._baseParams = obj if obj
|
|
291
|
+
|
|
292
|
+
if _.isFunction( Luca.Collection._baseParams )
|
|
293
|
+
return Luca.Collection._baseParams.call()
|
|
294
|
+
|
|
295
|
+
if _.isObject( Luca.Collection._baseParams )
|
|
296
|
+
Luca.Collection._baseParams
|
|
297
|
+
|
|
298
|
+
#### Bootstrapped Models ( stuff loaded on page load )
|
|
299
|
+
#
|
|
300
|
+
# In order to make our Backbone Apps super fast it is a good practice
|
|
301
|
+
# to pre-populate your collections by what is referred to as bootstrapping
|
|
302
|
+
#
|
|
303
|
+
# Luca.Collections make it easier for you to do this cleanly and automatically
|
|
304
|
+
#
|
|
305
|
+
# by specifying a @cached property or method in your collection definition
|
|
306
|
+
# Luca.Collections will automatically look in this space to find models
|
|
307
|
+
# and avoid a roundtrip to your API unless explicitly told to.
|
|
308
|
+
Luca.Collection._bootstrapped_models = {}
|
|
309
|
+
|
|
310
|
+
# In order to do this, just load an object whose keys
|
|
311
|
+
Luca.Collection.bootstrap = (obj)->
|
|
312
|
+
_.extend Luca.Collection._bootstrapped_models, obj
|
|
313
|
+
|
|
314
|
+
# Lookup cached() or bootstrappable models. This is used by the
|
|
315
|
+
# augmented version of Backbone.Collection.fetch() in order to avoid
|
|
316
|
+
# roundtrips to the API
|
|
317
|
+
Luca.Collection.cache = (key, models)->
|
|
318
|
+
return Luca.Collection._bootstrapped_models[ key ] = models if models
|
|
319
|
+
Luca.Collection._bootstrapped_models[ key ] || []
|