luca 0.9.2 → 0.9.4
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 +1 -0
- data/.rvmrc +1 -1
- data/CHANGELOG +46 -2
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/Guardfile +1 -1
- data/README.md +64 -27
- data/ROADMAP +17 -2
- data/Rakefile +49 -1
- data/app.rb +38 -2
- data/assets/javascripts/luca-ui-base.coffee +1 -20
- data/assets/javascripts/luca-ui-full.js +3 -0
- data/assets/javascripts/luca-ui.coffee +0 -5
- data/assets/javascripts/sandbox/application.coffee +24 -18
- data/assets/javascripts/sandbox/router.coffee +16 -6
- data/assets/javascripts/sandbox/templates/builder/component_list.luca +1 -0
- data/assets/javascripts/sandbox/templates/builder.luca +2 -0
- data/assets/javascripts/sandbox/templates/main.luca +4 -3
- data/assets/javascripts/sandbox/templates/sandbox/docs_index.luca +1 -0
- data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +6 -1
- data/assets/javascripts/sandbox/templates/sandbox/readme.luca +30 -0
- data/assets/javascripts/sandbox/views/builder/builder_canvas.coffee +3 -0
- data/assets/javascripts/sandbox/views/builder/builder_editor.coffee +6 -0
- data/assets/javascripts/sandbox/views/builder/component_list.coffee +38 -0
- data/assets/javascripts/sandbox/views/builder/project_browser.coffee +14 -0
- data/assets/javascripts/sandbox/views/builder.coffee +133 -0
- data/assets/javascripts/sandbox/views/docs_controller.coffee +7 -0
- data/assets/javascripts/sandbox/views/inspector/instance_filter.coffee +18 -0
- data/assets/javascripts/sandbox/{collections/sample.coffee → views/inspector/instance_list.coffee} +0 -0
- data/assets/javascripts/sandbox/views/inspector.coffee +11 -0
- data/assets/javascripts/sandbox.coffee +2 -0
- data/assets/stylesheets/luca-ui-full.css +3 -0
- data/assets/stylesheets/sandbox/builder.scss +79 -0
- data/assets/stylesheets/sandbox/sandbox.scss +2 -1
- data/docs/application.md +41 -0
- data/docs/collection.md +79 -0
- data/docs/collection_manager.md +76 -0
- data/docs/container_philosophy.md +122 -0
- data/docs/event_binding_helpers.md +164 -0
- data/docs/method_caching_and_computed_properties.md +77 -0
- data/docs/view.md +119 -0
- data/lib/luca/rails/version.rb +1 -1
- data/lib/luca/template.rb +9 -9
- data/site/assets/bootstrap.min.js +7 -0
- data/site/assets/luca-ui-bootstrap.css +19 -1
- data/site/assets/luca-ui-development-tools.css +10 -0
- data/site/assets/luca-ui-development-tools.min.js +15 -0
- data/site/assets/luca-ui-full.min.js +8 -0
- data/site/assets/luca-ui.min.js +4 -0
- data/site/assets/sandbox.css +52 -4
- data/site/assets/sandbox.js +368 -30
- data/site/docs/application.html +41 -0
- data/site/docs/caching.html +43 -0
- data/site/docs/collection.html +75 -0
- data/site/docs/collection_manager.html +71 -0
- data/site/docs/containers.html +118 -0
- data/site/docs/events.html +153 -0
- data/site/docs/view.html +128 -0
- data/site/img/glyphicons-halflings-white.png +0 -0
- data/site/img/glyphicons-halflings.png +0 -0
- data/site/source-map.js +1 -0
- data/spec/core/view_spec.coffee +5 -17
- data/spec/managers/collection_manager_spec.coffee +4 -7
- data/src/components/application.coffee +202 -77
- data/src/components/base_toolbar.coffee +1 -1
- data/src/components/collection_view.coffee +38 -10
- data/src/components/controller.coffee +24 -1
- data/src/components/fields/checkbox_field.coffee +9 -12
- data/src/components/fields/label_field.coffee +14 -0
- data/src/components/fields/select_field.coffee +2 -2
- data/src/components/fields/text_field.coffee +12 -7
- data/src/components/fields/type_ahead_field.coffee +1 -0
- data/src/components/form_view.coffee +44 -25
- data/src/components/page_controller.coffee +2 -0
- data/src/containers/card_view.coffee +4 -1
- data/src/containers/column_view.coffee +2 -1
- data/src/containers/modal_view.coffee +6 -2
- data/src/containers/page_view.coffee +2 -0
- data/src/containers/panel_toolbar.coffee +0 -5
- data/src/containers/viewport.coffee +28 -10
- data/src/core/collection.coffee +7 -1
- data/src/core/container.coffee +57 -30
- data/src/core/core.coffee +0 -186
- data/src/core/field.coffee +11 -3
- data/src/core/model.coffee +31 -16
- data/src/core/panel.coffee +6 -46
- data/src/core/registry.coffee +19 -2
- data/src/core/script_loader.coffee +32 -0
- data/src/core/view.coffee +112 -139
- data/src/define.coffee +110 -0
- data/src/framework.coffee +8 -2
- data/src/luca.coffee +22 -0
- data/src/managers/collection_manager.coffee +65 -31
- data/src/modules/load_mask.coffee +47 -0
- data/src/plugins/development_tool_helpers.coffee +21 -0
- data/src/plugins/events.coffee +54 -0
- data/src/stylesheets/components/viewport.scss +15 -0
- data/src/stylesheets/containers/container.scss +1 -4
- data/src/stylesheets/tools/component_tester.scss +18 -0
- data/src/templates/fields/select_field.luca +6 -5
- data/src/templates/fields/text_field.luca +10 -9
- data/src/tools/application_inspector.coffee +2 -0
- data/src/tools/coffee_script_editor.coffee +28 -6
- data/src/tools/collections/components.coffee +59 -0
- data/src/tools/collections/instances.coffee +15 -0
- data/src/tools/component_tester.coffee +12 -22
- data/src/tools/console.coffee +22 -4
- data/src/tools/models/components.coffee +16 -54
- data/src/tools/models/instance.coffee +2 -0
- data/src/{core/util.coffee → util.coffee} +10 -1
- data/vendor/assets/javascripts/luca-ui-base.js +132 -137
- data/vendor/assets/javascripts/luca-ui-development-tools.js +191 -219
- data/vendor/assets/javascripts/luca-ui-development-tools.min.js +2 -2
- data/vendor/assets/javascripts/luca-ui-full.js +4680 -0
- data/vendor/assets/javascripts/luca-ui-full.min.js +8 -0
- data/vendor/assets/javascripts/luca-ui-spec.js +291 -225
- data/vendor/assets/javascripts/luca-ui.js +1001 -724
- data/vendor/assets/javascripts/luca-ui.min.js +4 -4
- data/vendor/assets/stylesheets/luca-ui-bootstrap.css +19 -1
- data/vendor/assets/stylesheets/luca-ui-development-tools.css +10 -0
- data/vendor/assets/stylesheets/luca-ui-full.css +1334 -0
- data/vendor/assets/stylesheets/luca-ui-spec.css +19 -1
- data/vendor/assets/stylesheets/luca-ui.css +19 -1
- data/views/index.erb +2 -5
- metadata +58 -9
- data/lib/sprockets/luca_template.rb +0 -49
- data/src/tools/class_browser.coffee +0 -39
- data/src/tools/components/class_browser_detail.coffee +0 -10
- data/src/tools/components/class_browser_list.coffee +0 -74
data/src/core/model.coffee
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Computed Properties Support
|
|
2
|
+
# ###
|
|
2
3
|
#
|
|
3
|
-
# Luca.Model
|
|
4
|
-
#
|
|
4
|
+
# Luca.Model supports computed properties, which are
|
|
5
|
+
# object methods which are composed of model attributes or
|
|
6
|
+
# of calculations which are dependent on these attributes.
|
|
7
|
+
|
|
8
|
+
# When these model attributes change, the computed property
|
|
9
|
+
# needs to be re-evaluated.
|
|
5
10
|
#
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
# The configuration API for computed properties expects a hash
|
|
12
|
+
# whose keys are the name of the method, and whose value is
|
|
13
|
+
# an array of the attribute dependencies for that method.
|
|
14
|
+
setupComputedProperties = ()->
|
|
15
|
+
return if _.isUndefined(@computed)
|
|
16
|
+
|
|
17
|
+
@_computed = {}
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
for attr, dependencies of @computed
|
|
20
|
+
@on "change:#{attr}", ()=>
|
|
21
|
+
@_computed[attr] = @[attr].call @
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
dependencies = dependencies.split(',') if _.isString(dependencies)
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
@on "change:#{
|
|
17
|
-
@
|
|
25
|
+
_(dependencies).each (dep)=>
|
|
26
|
+
@on "change:#{dep}", ()=>
|
|
27
|
+
@trigger "change:#{attr}"
|
|
28
|
+
|
|
29
|
+
@trigger "change:#{attr}" if @has(dep)
|
|
18
30
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
|
|
32
|
+
_.def('Luca.Model').extends('Backbone.Model').with
|
|
33
|
+
include: ['Luca.Events']
|
|
34
|
+
|
|
35
|
+
initialize: ()->
|
|
36
|
+
Backbone.Model::initialize @, arguments
|
|
37
|
+
setupComputedProperties.call(@)
|
|
23
38
|
|
|
24
39
|
get: (attr)->
|
|
25
40
|
if @computed?.hasOwnProperty(attr)
|
data/src/core/panel.coffee
CHANGED
|
@@ -43,55 +43,12 @@ _.def("Luca.components.Panel").extends("Luca.View").with
|
|
|
43
43
|
loadMask: false
|
|
44
44
|
loadMaskTemplate: ["components/load_mask"]
|
|
45
45
|
loadMaskTimeout: 3000
|
|
46
|
+
|
|
47
|
+
mixins:["LoadMaskable"]
|
|
46
48
|
|
|
47
49
|
initialize: (@options={})->
|
|
48
50
|
Luca.View::initialize.apply(@, arguments)
|
|
49
|
-
|
|
50
|
-
_.bindAll @, "applyLoadMask", "disableLoadMask"
|
|
51
|
-
|
|
52
|
-
if @loadMask is true
|
|
53
|
-
@defer ()=>
|
|
54
|
-
@$el.addClass('with-mask')
|
|
55
|
-
|
|
56
|
-
if @$('.load-mask').length is 0
|
|
57
|
-
@loadMaskTarget().prepend Luca.template(@loadMaskTemplate, @)
|
|
58
|
-
@$('.load-mask').hide()
|
|
59
|
-
.until("after:render")
|
|
60
|
-
|
|
61
|
-
@on "enable:loadmask", @applyLoadMask
|
|
62
|
-
@on "disable:loadmask", @applyLoadMask
|
|
63
|
-
|
|
64
|
-
loadMaskTarget: ()->
|
|
65
|
-
if @loadMaskEl? then @$(@loadMaskEl) else @$bodyEl()
|
|
66
|
-
|
|
67
|
-
disableLoadMask: ()->
|
|
68
|
-
@$('.load-mask .bar').css("width","100%")
|
|
69
|
-
@$('.load-mask').hide()
|
|
70
|
-
clearInterval(@loadMaskInterval)
|
|
71
|
-
|
|
72
|
-
enableLoadMask: ()->
|
|
73
|
-
@$('.load-mask').show().find('.bar').css("width","0%")
|
|
74
|
-
maxWidth = @$('.load-mask .progress').width()
|
|
75
|
-
if maxWidth < 20 and (maxWidth = @$el.width()) < 20
|
|
76
|
-
maxWidth = @$el.parent().width()
|
|
77
|
-
|
|
78
|
-
@loadMaskInterval = setInterval ()=>
|
|
79
|
-
currentWidth = @$('.load-mask .bar').width()
|
|
80
|
-
newWidth = currentWidth + 12
|
|
81
|
-
@$('.load-mask .bar').css('width', newWidth)
|
|
82
|
-
, 200
|
|
83
|
-
|
|
84
|
-
return unless @loadMaskTimeout?
|
|
85
|
-
|
|
86
|
-
_.delay ()=>
|
|
87
|
-
@disableLoadMask()
|
|
88
|
-
, @loadMaskTimeout
|
|
89
|
-
|
|
90
|
-
applyLoadMask: ()->
|
|
91
|
-
if @$('.load-mask').is(":visible")
|
|
92
|
-
@disableLoadMask()
|
|
93
|
-
else
|
|
94
|
-
@enableLoadMask()
|
|
51
|
+
|
|
95
52
|
|
|
96
53
|
applyStyles: (styles={},body=false)->
|
|
97
54
|
|
|
@@ -137,6 +94,9 @@ _.def("Luca.components.Panel").extends("Luca.View").with
|
|
|
137
94
|
$template: (template, variables={})->
|
|
138
95
|
@$html( Luca.template(template,variables) )
|
|
139
96
|
|
|
97
|
+
$empty: ()->
|
|
98
|
+
@$bodyEl().empty()
|
|
99
|
+
|
|
140
100
|
$html: (content)->
|
|
141
101
|
@$bodyEl().html( content )
|
|
142
102
|
|
data/src/core/registry.coffee
CHANGED
|
@@ -61,10 +61,24 @@ Luca.registry.namespaces = (resolve=true)->
|
|
|
61
61
|
_( registry.namespaces ).map (namespace)->
|
|
62
62
|
if resolve then Luca.util.resolve( namespace ) else namespace
|
|
63
63
|
|
|
64
|
+
Luca.registry.aliases =
|
|
65
|
+
grid: "grid_view"
|
|
66
|
+
form: "form_view"
|
|
67
|
+
text: "text_field"
|
|
68
|
+
button: "button_field"
|
|
69
|
+
select: "select_field"
|
|
70
|
+
card: "card_view"
|
|
71
|
+
paged: "card_view"
|
|
72
|
+
wizard: "card_view"
|
|
73
|
+
collection: "collection_view"
|
|
74
|
+
|
|
64
75
|
# Lookup a component in the Luca component registry
|
|
65
76
|
# by it's ctype identifier. If it doesn't exist,
|
|
66
77
|
# check any other registered namespace
|
|
67
78
|
Luca.registry.lookup = (ctype)->
|
|
79
|
+
if alias = Luca.registry.aliases[ ctype ]
|
|
80
|
+
ctype = alias
|
|
81
|
+
|
|
68
82
|
c = registry.classes[ctype]
|
|
69
83
|
|
|
70
84
|
return c if c?
|
|
@@ -76,13 +90,16 @@ Luca.registry.lookup = (ctype)->
|
|
|
76
90
|
fullPath = _( parents ).chain().map((parent)->
|
|
77
91
|
parent[className]).compact().value()?[0]
|
|
78
92
|
|
|
93
|
+
Luca.registry.instances = ()->
|
|
94
|
+
_( component_cache.cid_index ).values()
|
|
95
|
+
|
|
79
96
|
Luca.registry.findInstancesByClassName = (className)->
|
|
80
|
-
instances =
|
|
97
|
+
instances = Luca.registry.instances()
|
|
81
98
|
_( instances ).select (instance)->
|
|
82
99
|
instance.displayName is className or instance._superClass?()?.displayName is className
|
|
83
100
|
|
|
84
101
|
Luca.registry.classes = (toString=false)->
|
|
85
|
-
_(
|
|
102
|
+
_(_.extend({},registry.classes,registry.model_classes,registry.collection_classes)).map (className, ctype)->
|
|
86
103
|
if toString
|
|
87
104
|
className
|
|
88
105
|
else
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class Luca.ScriptLoader
|
|
2
|
+
@loaded: {}
|
|
3
|
+
|
|
4
|
+
constructor: (options={})->
|
|
5
|
+
_.extend(@, Backbone.Events, Luca.Events)
|
|
6
|
+
@autoStart = options.autoStart is true
|
|
7
|
+
@scripts = options.scripts
|
|
8
|
+
|
|
9
|
+
ready = ()-> @trigger("ready")
|
|
10
|
+
|
|
11
|
+
@ready = _.after( @scripts.length, ready)
|
|
12
|
+
|
|
13
|
+
_.bindAll @, "load", "ready"
|
|
14
|
+
|
|
15
|
+
@defer("load").until(@, "start")
|
|
16
|
+
|
|
17
|
+
if @autoStart is true
|
|
18
|
+
@trigger("start")
|
|
19
|
+
|
|
20
|
+
@bind "ready", @onReady
|
|
21
|
+
|
|
22
|
+
applyPrefix: (script)->
|
|
23
|
+
script
|
|
24
|
+
|
|
25
|
+
onReady: ()->
|
|
26
|
+
console.log "All dependencies loaded"
|
|
27
|
+
|
|
28
|
+
start: ()->
|
|
29
|
+
@trigger("start")
|
|
30
|
+
|
|
31
|
+
load: ()->
|
|
32
|
+
Luca.util.loadScript( @applyPrefix(script), @ready ) for script in @scripts
|
data/src/core/view.coffee
CHANGED
|
@@ -1,27 +1,8 @@
|
|
|
1
|
-
#### Luca Base View
|
|
2
|
-
|
|
3
|
-
# The Luca.View class adds some very commonly used patterns
|
|
4
|
-
# and functionality to the stock Backbone.View class. Features
|
|
5
|
-
# such as auto event binding, the facilitation of deferred rendering
|
|
6
|
-
# against a Backbone.Model or Backbone.Collection reset event, Caching
|
|
7
|
-
# views into a global Component Registry, and more.
|
|
8
|
-
|
|
9
1
|
_.def("Luca.View").extends("Backbone.View").with
|
|
2
|
+
include: ['Luca.Events']
|
|
10
3
|
|
|
11
4
|
additionalClassNames:[]
|
|
12
5
|
|
|
13
|
-
debug: ()->
|
|
14
|
-
return unless @debugMode or window.LucaDebugMode?
|
|
15
|
-
console.log [(@name || @cid),message] for message in arguments
|
|
16
|
-
|
|
17
|
-
trigger: ()->
|
|
18
|
-
if Luca.enableGlobalObserver
|
|
19
|
-
if Luca.developmentMode is true or @observeEvents is true
|
|
20
|
-
Luca.ViewObserver ||= new Luca.Observer(type:"view")
|
|
21
|
-
Luca.ViewObserver.relay @, arguments
|
|
22
|
-
|
|
23
|
-
Backbone.View.prototype.trigger.apply @, arguments
|
|
24
|
-
|
|
25
6
|
hooks:[
|
|
26
7
|
"after:initialize"
|
|
27
8
|
"before:render"
|
|
@@ -32,39 +13,64 @@ _.def("Luca.View").extends("Backbone.View").with
|
|
|
32
13
|
]
|
|
33
14
|
|
|
34
15
|
initialize: (@options={})->
|
|
16
|
+
@trigger "before:initialize", @, @options
|
|
35
17
|
|
|
36
18
|
_.extend @, @options
|
|
37
19
|
|
|
38
20
|
@cid = _.uniqueId(@name) if @name?
|
|
39
21
|
|
|
22
|
+
templateVars = if @bodyTemplateVars
|
|
23
|
+
@bodyTemplateVars.call(@)
|
|
24
|
+
else
|
|
25
|
+
@
|
|
26
|
+
|
|
40
27
|
if template = @bodyTemplate
|
|
41
28
|
@$el.empty()
|
|
42
|
-
Luca.View::$html.call(@, Luca.template(template,
|
|
29
|
+
Luca.View::$html.call(@, Luca.template(template, templateVars ) )
|
|
43
30
|
|
|
44
|
-
#### View Caching
|
|
45
|
-
#
|
|
46
|
-
# Luca.View(s) which get created get stored in a global cache by their
|
|
47
|
-
# component id. This allows us to re-use views when it makes sense
|
|
48
31
|
Luca.cache( @cid, @ )
|
|
49
32
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@setupHooks( unique )
|
|
33
|
+
@setupHooks _( Luca.View::hooks.concat( @hooks ) ).uniq()
|
|
53
34
|
|
|
54
|
-
if @autoBindEventHandlers is true
|
|
55
|
-
@bindAllEventHandlers()
|
|
35
|
+
bindAllEventHandlers.call(@) if @autoBindEventHandlers is true or @bindAllEvents is true
|
|
56
36
|
|
|
57
37
|
if @additionalClassNames
|
|
58
38
|
@additionalClassNames = @additionalClassNames.split(" ") if _.isString(@additionalClassNames)
|
|
39
|
+
|
|
40
|
+
if @gridSpan
|
|
41
|
+
@additionalClassNames.push "span#{ @gridSpan }"
|
|
42
|
+
|
|
43
|
+
if @gridOffset
|
|
44
|
+
@additionalClassNames.push "offset#{ @gridOffset }"
|
|
45
|
+
|
|
46
|
+
if @gridRowFluid
|
|
47
|
+
@additionalClassNames.push "row-fluid"
|
|
48
|
+
|
|
49
|
+
if @gridRow
|
|
50
|
+
@additionalClassNames.push "row"
|
|
51
|
+
|
|
52
|
+
if @additionalClassNames?.length > 0
|
|
59
53
|
@$el.addClass( additional ) for additional in @additionalClassNames
|
|
60
54
|
|
|
61
|
-
@
|
|
55
|
+
@$wrap( @wrapperClass ) if @wrapperClass?
|
|
62
56
|
|
|
63
|
-
|
|
57
|
+
registerCollectionEvents.call(@)
|
|
58
|
+
registerApplicationEvents.call( @)
|
|
64
59
|
|
|
65
60
|
@delegateEvents()
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
if @stateful is true and not @state?
|
|
63
|
+
@state = new Backbone.Model(@defaultState || {})
|
|
64
|
+
unless @set?
|
|
65
|
+
@set = _.bind @, @state.set
|
|
66
|
+
@get = _.bind @, @state.get
|
|
67
|
+
|
|
68
|
+
if @mixins?.length > 0
|
|
69
|
+
for module in @mixins
|
|
70
|
+
Luca.modules[ module ]._included.call(@, @, module)
|
|
71
|
+
|
|
72
|
+
@trigger "after:initialize", @
|
|
73
|
+
|
|
68
74
|
$wrap: (wrapper)->
|
|
69
75
|
if _.isString(wrapper) and not wrapper.match(/[<>]/)
|
|
70
76
|
wrapper = @make("div",class:wrapper)
|
|
@@ -80,17 +86,12 @@ _.def("Luca.View").extends("Backbone.View").with
|
|
|
80
86
|
$append: (content)->
|
|
81
87
|
@$el.append( content )
|
|
82
88
|
|
|
83
|
-
#### Containers
|
|
84
|
-
#
|
|
85
|
-
# Luca is heavily reliant on the concept of Container views. Views which
|
|
86
|
-
# contain other views and handle inter-component communication between the
|
|
87
|
-
# component views. The default render() operation consists of building the
|
|
88
|
-
# view's content, and then attaching that view to its container.
|
|
89
|
-
#
|
|
90
|
-
# 99% of the time this would happen automatically
|
|
91
89
|
$attach: ()->
|
|
92
90
|
@$container().append( @el )
|
|
93
91
|
|
|
92
|
+
$bodyEl: ()->
|
|
93
|
+
@$el
|
|
94
|
+
|
|
94
95
|
$container: ()->
|
|
95
96
|
$(@container)
|
|
96
97
|
|
|
@@ -120,120 +121,38 @@ _.def("Luca.View").extends("Backbone.View").with
|
|
|
120
121
|
|
|
121
122
|
@bind eventId, callback
|
|
122
123
|
|
|
123
|
-
|
|
124
|
-
#### Luca.Collection and Luca.CollectionManager integration
|
|
125
|
-
|
|
126
|
-
# under the hood, this will find your collection manager using
|
|
127
|
-
# Luca.CollectionManager.get, which is a function that returns
|
|
128
|
-
# the first instance of the CollectionManager class ever created.
|
|
129
|
-
#
|
|
130
|
-
# if you want to use more than one collection manager, over ride this
|
|
131
|
-
# function in your views with your own logic
|
|
132
|
-
getCollectionManager: ()->
|
|
133
|
-
@collectionManager || Luca.CollectionManager.get?()
|
|
134
|
-
|
|
135
|
-
##### Collection Events
|
|
136
|
-
#
|
|
137
|
-
# By defining a hash of collectionEvents in the form of
|
|
138
|
-
#
|
|
139
|
-
# "books add" : "onBookAdd"
|
|
140
|
-
#
|
|
141
|
-
# the Luca.View will bind to the collection found in the
|
|
142
|
-
# collectionManager with that key, and bind to that event.
|
|
143
|
-
# a property of @booksCollection will be created on the view,
|
|
144
|
-
# and the "add" event will trigger "onBookAdd"
|
|
145
|
-
#
|
|
146
|
-
# you may also specify a function directly. this
|
|
147
|
-
#
|
|
148
|
-
registerCollectionEvents: ()->
|
|
149
|
-
manager = @getCollectionManager()
|
|
150
|
-
|
|
151
|
-
_( @collectionEvents ).each (handler, signature)=>
|
|
152
|
-
[key,event] = signature.split(" ")
|
|
153
|
-
|
|
154
|
-
collection = @["#{ key }Collection"] = manager.getOrCreate( key )
|
|
155
|
-
|
|
156
|
-
if !collection
|
|
157
|
-
throw "Could not find collection specified by #{ key }"
|
|
158
|
-
|
|
159
|
-
if _.isString(handler)
|
|
160
|
-
handler = @[handler]
|
|
161
|
-
|
|
162
|
-
unless _.isFunction(handler)
|
|
163
|
-
throw "invalid collectionEvents configuration"
|
|
164
|
-
|
|
165
|
-
try
|
|
166
|
-
collection.bind(event, handler)
|
|
167
|
-
catch e
|
|
168
|
-
console.log "Error Binding To Collection in registerCollectionEvents", @
|
|
169
|
-
throw e
|
|
170
|
-
|
|
171
124
|
registerEvent: (selector, handler)->
|
|
172
125
|
@events ||= {}
|
|
173
126
|
@events[ selector ] = handler
|
|
174
127
|
@delegateEvents()
|
|
175
128
|
|
|
176
|
-
bindAllEventHandlers: ()->
|
|
177
|
-
_( @events ).each (handler,event)=>
|
|
178
|
-
if _.isString(handler)
|
|
179
|
-
_.bindAll @, handler
|
|
180
|
-
|
|
181
129
|
definitionClass: ()->
|
|
182
130
|
Luca.util.resolve(@displayName, window)?.prototype
|
|
183
131
|
|
|
184
|
-
# refreshCode happens whenever the Luca.Framework extension
|
|
185
|
-
# system is run after there are running instances of a given component
|
|
186
|
-
|
|
187
|
-
# in the context of views, what this means is that each eventHandler which
|
|
188
|
-
# is bound to a specific object via _.bind or _.bindAll, or autoBindEventHandlers
|
|
189
|
-
# is refreshed with the prototype method of the component that it inherits from,
|
|
190
|
-
# and then delegateEvents is called to refresh any of the updated event handlers
|
|
191
|
-
|
|
192
|
-
# in addition to this, all properties of the instance of a given view which are
|
|
193
|
-
# also backbone views will have the same process run against them
|
|
194
|
-
refreshCode: ()->
|
|
195
|
-
view = @
|
|
196
|
-
|
|
197
|
-
_( @eventHandlerProperties() ).each (prop)->
|
|
198
|
-
view[ prop ] = view.definitionClass()[prop]
|
|
199
|
-
|
|
200
|
-
if @autoBindEventHandlers is true
|
|
201
|
-
@bindAllEventHandlers()
|
|
202
|
-
|
|
203
|
-
@delegateEvents()
|
|
204
|
-
|
|
205
|
-
eventHandlerProperties: ()->
|
|
206
|
-
handlerIds = _( @events ).values()
|
|
207
|
-
_( handlerIds ).select (v)->
|
|
208
|
-
_.isString(v)
|
|
209
|
-
|
|
210
|
-
eventHandlerFunctions: ()->
|
|
211
|
-
handlerIds = _( @events ).values()
|
|
212
|
-
_( handlerIds ).map (handlerId)=>
|
|
213
|
-
if _.isFunction(handlerId) then handlerId else @[handlerId]
|
|
214
|
-
|
|
215
132
|
collections: ()-> Luca.util.selectProperties( Luca.isBackboneCollection, @ )
|
|
216
133
|
models: ()-> Luca.util.selectProperties( Luca.isBackboneModel, @ )
|
|
217
134
|
views: ()-> Luca.util.selectProperties( Luca.isBackboneView, @ )
|
|
218
135
|
|
|
136
|
+
debug: ()->
|
|
137
|
+
return unless @debugMode or window.LucaDebugMode?
|
|
138
|
+
console.log [(@name || @cid),message] for message in arguments
|
|
139
|
+
|
|
140
|
+
trigger: ()->
|
|
141
|
+
if Luca.enableGlobalObserver
|
|
142
|
+
if Luca.developmentMode is true or @observeEvents is true
|
|
143
|
+
Luca.ViewObserver ||= new Luca.Observer(type:"view")
|
|
144
|
+
Luca.ViewObserver.relay @, arguments
|
|
145
|
+
|
|
146
|
+
Backbone.View.prototype.trigger.apply @, arguments
|
|
147
|
+
|
|
219
148
|
|
|
220
149
|
originalExtend = Backbone.View.extend
|
|
221
150
|
|
|
222
151
|
customizeRender = (definition)->
|
|
223
|
-
#### Rendering
|
|
224
|
-
#
|
|
225
|
-
# Our base view class wraps the defined render() method
|
|
226
|
-
# of the views which inherit from it, and does things like
|
|
227
|
-
# trigger the before and after render events automatically.
|
|
228
|
-
# In addition, if the view has a deferrable property on it
|
|
229
|
-
# then it will make sure that the render method doesn't get called
|
|
230
|
-
# until.
|
|
231
|
-
|
|
232
152
|
_base = definition.render
|
|
233
153
|
|
|
234
154
|
_base ||= Luca.View::$attach
|
|
235
155
|
|
|
236
|
-
|
|
237
156
|
definition.render = ()->
|
|
238
157
|
view = @
|
|
239
158
|
# if a view has a deferrable property set
|
|
@@ -274,10 +193,64 @@ customizeRender = (definition)->
|
|
|
274
193
|
|
|
275
194
|
definition
|
|
276
195
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
196
|
+
bindAllEventHandlers = ()->
|
|
197
|
+
_( @events ).each (handler,event)=>
|
|
198
|
+
if _.isString(handler)
|
|
199
|
+
_.bindAll @, handler
|
|
200
|
+
|
|
201
|
+
registerApplicationEvents = ()->
|
|
202
|
+
return if _.isEmpty(@applicationEvents)
|
|
203
|
+
|
|
204
|
+
app = @app
|
|
205
|
+
|
|
206
|
+
if _.isString( app ) or _.isUndefined( app )
|
|
207
|
+
app = Luca.Application?.get?(app)
|
|
208
|
+
|
|
209
|
+
unless Luca.supportsEvents( app )
|
|
210
|
+
throw "Error binding to the application object on #{ @name || @cid }"
|
|
211
|
+
|
|
212
|
+
for eventTrigger, handler in @applicationEvents
|
|
213
|
+
handler = @[handler] if _.isString(handler)
|
|
214
|
+
|
|
215
|
+
unless _.isFunction(handler)
|
|
216
|
+
throw "Error registering application event #{ eventTrigger } on #{ @name || @cid }"
|
|
217
|
+
|
|
218
|
+
app.on(eventTrigger, handler)
|
|
219
|
+
|
|
220
|
+
registerCollectionEvents = ()->
|
|
221
|
+
return if _.isEmpty( @collectionEvents )
|
|
222
|
+
|
|
223
|
+
manager = @collectionManager
|
|
224
|
+
|
|
225
|
+
if _.isString( manager ) or _.isUndefined( manager )
|
|
226
|
+
manager = Luca.CollectionManager.get( manager )
|
|
227
|
+
|
|
228
|
+
for signature, handler of @collectionEvents
|
|
229
|
+
console.log "Sig", signature, "Handler", handler
|
|
230
|
+
[key,eventTrigger] = signature.split(" ")
|
|
231
|
+
|
|
232
|
+
collection = manager.getOrCreate( key )
|
|
233
|
+
|
|
234
|
+
if !collection
|
|
235
|
+
throw "Could not find collection specified by #{ key }"
|
|
236
|
+
|
|
237
|
+
if _.isString(handler)
|
|
238
|
+
handler = @[handler]
|
|
239
|
+
|
|
240
|
+
unless _.isFunction(handler)
|
|
241
|
+
throw "invalid collectionEvents configuration"
|
|
242
|
+
|
|
243
|
+
try
|
|
244
|
+
collection.bind(eventTrigger, handler)
|
|
245
|
+
catch e
|
|
246
|
+
console.log "Error Binding To Collection in registerCollectionEvents", @
|
|
247
|
+
throw e
|
|
248
|
+
|
|
249
|
+
|
|
280
250
|
Luca.View.extend = (definition)->
|
|
281
251
|
definition = customizeRender( definition )
|
|
282
|
-
originalExtend.call(@, definition)
|
|
283
252
|
|
|
253
|
+
if definition.mixins? and _.isArray( definition.mixins )
|
|
254
|
+
_.extend(definition, Luca.modules[module]) for module in definition.mixins
|
|
255
|
+
|
|
256
|
+
originalExtend.call(@, definition)
|
data/src/define.coffee
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Component Definition Helpers
|
|
2
|
+
#
|
|
3
|
+
#
|
|
4
|
+
# We have customized the core Backbone.extend process to use a slightly
|
|
5
|
+
# different syntax, which allows us to intercept the component definition at
|
|
6
|
+
# various points, and maintain information about classes being defined, and
|
|
7
|
+
# the relationships between inherited classes, etc.
|
|
8
|
+
|
|
9
|
+
# _.def, or Luca.define returns a chainable object which allows you to define
|
|
10
|
+
# your components with a readable syntax. For example:
|
|
11
|
+
|
|
12
|
+
# _.def("Luca.View").extends("Backbone.View").with the_good:"shit"
|
|
13
|
+
# _.def("MyView").extends("Luca.View").with the_custom:"shit"
|
|
14
|
+
|
|
15
|
+
Luca.define = (componentName)->
|
|
16
|
+
new DefineProxy(componentName)
|
|
17
|
+
|
|
18
|
+
Luca.component = Luca.define
|
|
19
|
+
|
|
20
|
+
# The define proxy chain sets up a call to Luca.extend, which is a wrapper around Luca and Backbone component class' extend function.
|
|
21
|
+
class DefineProxy
|
|
22
|
+
constructor:(componentName)->
|
|
23
|
+
@namespace = Luca.util.namespace()
|
|
24
|
+
@componentId = @componentName = componentName
|
|
25
|
+
|
|
26
|
+
if componentName.match(/\./)
|
|
27
|
+
@namespaced = true
|
|
28
|
+
parts = componentName.split('.')
|
|
29
|
+
@componentId = parts.pop()
|
|
30
|
+
@namespace = parts.join('.')
|
|
31
|
+
|
|
32
|
+
# automatically add the namespace to the namespace registry
|
|
33
|
+
Luca.registry.addNamespace( parts.join('.') )
|
|
34
|
+
|
|
35
|
+
# allow for specifying the namespace
|
|
36
|
+
in: (@namespace)-> @
|
|
37
|
+
|
|
38
|
+
# allow for multiple ways of saying the same thing for readability purposes
|
|
39
|
+
from: (@superClassName)-> @
|
|
40
|
+
extends: (@superClassName)-> @
|
|
41
|
+
extend: (@superClassName)-> @
|
|
42
|
+
|
|
43
|
+
# an alias for with, or a readability helper in multi-line definitions
|
|
44
|
+
enhance: (properties)->
|
|
45
|
+
return @with(properties) if properties?
|
|
46
|
+
@
|
|
47
|
+
|
|
48
|
+
# which properties, methods, etc will you be extending the base class with?
|
|
49
|
+
with: (properties)->
|
|
50
|
+
at = if @namespaced
|
|
51
|
+
Luca.util.resolve(@namespace, (window || global))
|
|
52
|
+
else
|
|
53
|
+
(window||global)
|
|
54
|
+
|
|
55
|
+
# automatically create the namespace
|
|
56
|
+
if @namespaced and not at?
|
|
57
|
+
eval("(window||global).#{ @namespace } = {}")
|
|
58
|
+
at = Luca.util.resolve(@namespace,(window || global))
|
|
59
|
+
|
|
60
|
+
at[@componentId] = Luca.extend(@superClassName,@componentName, properties)
|
|
61
|
+
|
|
62
|
+
if Luca.autoRegister is true
|
|
63
|
+
componentType = "view" if Luca.isViewPrototype( at[@componentId] )
|
|
64
|
+
|
|
65
|
+
if Luca.isCollectionPrototype( at[@componentId] )
|
|
66
|
+
Luca.Collection.namespaces ||= []
|
|
67
|
+
Luca.Collection.namespaces.push( @namespace )
|
|
68
|
+
componentType = "collection"
|
|
69
|
+
|
|
70
|
+
componentType = "model" if Luca.isModelPrototype( at[@componentId] )
|
|
71
|
+
|
|
72
|
+
# automatically register this with the component registry
|
|
73
|
+
Luca.register( _.string.underscored(@componentId), @componentName, componentType)
|
|
74
|
+
|
|
75
|
+
at[@componentId]
|
|
76
|
+
|
|
77
|
+
# The last method of the DefineProxy chain is always going to result in
|
|
78
|
+
# a call to Luca.extend. Luca.extend wraps the call to Luca.View.extend,
|
|
79
|
+
# or Backbone.Collection.extend, and accepts the names of the extending,
|
|
80
|
+
# and extended classes as strings. This allows us to maintain information
|
|
81
|
+
# and references to the classes and their prototypes, mainly for the purposes
|
|
82
|
+
# of introspection and development tools
|
|
83
|
+
Luca.extend = (superClassName, childName, properties={})->
|
|
84
|
+
superClass = Luca.util.resolve( superClassName, (window || global) )
|
|
85
|
+
|
|
86
|
+
unless _.isFunction(superClass?.extend)
|
|
87
|
+
throw "#{ superClassName } is not a valid component to extend from"
|
|
88
|
+
|
|
89
|
+
properties.displayName = childName
|
|
90
|
+
|
|
91
|
+
properties._superClass = ()->
|
|
92
|
+
superClass.displayName ||= superClassName
|
|
93
|
+
superClass
|
|
94
|
+
|
|
95
|
+
properties._super = (method, context, args)->
|
|
96
|
+
@_superClass().prototype[method]?.apply(context, args)
|
|
97
|
+
|
|
98
|
+
definition = superClass.extend(properties)
|
|
99
|
+
|
|
100
|
+
# _.def("MyView").extends("View").with
|
|
101
|
+
# include: ['Luca.Events']
|
|
102
|
+
if _.isArray( properties?.include )
|
|
103
|
+
for mixin in properties.include
|
|
104
|
+
mixin = Luca.util.resolve(mixin) if _.isString(mixin)
|
|
105
|
+
_.extend(definition::, mixin)
|
|
106
|
+
|
|
107
|
+
definition
|
|
108
|
+
|
|
109
|
+
_.mixin
|
|
110
|
+
def: Luca.define
|
data/src/framework.coffee
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
return fallback()
|
|
20
20
|
|
|
21
21
|
_.extend Luca,
|
|
22
|
-
VERSION: "0.9.
|
|
22
|
+
VERSION: "0.9.4"
|
|
23
23
|
core: {}
|
|
24
24
|
containers: {}
|
|
25
25
|
components: {}
|
|
@@ -27,6 +27,7 @@ _.extend Luca,
|
|
|
27
27
|
util: {}
|
|
28
28
|
fields: {}
|
|
29
29
|
registry:{}
|
|
30
|
+
options: {}
|
|
30
31
|
|
|
31
32
|
# for triggering / binding to component definitions
|
|
32
33
|
_.extend Luca, Backbone.Events
|
|
@@ -79,21 +80,27 @@ Luca.isComponentPrototype = (obj)->
|
|
|
79
80
|
Luca.isViewPrototype(obj) or Luca.isModelPrototype(obj) or Luca.isCollectionPrototype(obj)
|
|
80
81
|
|
|
81
82
|
Luca.isBackboneModel = (obj)->
|
|
83
|
+
obj = Luca.util.resolve(obj) if _.isString(obj)
|
|
82
84
|
_.isFunction(obj?.set) and _.isFunction(obj?.get) and _.isObject(obj?.attributes)
|
|
83
85
|
|
|
84
86
|
Luca.isBackboneView = (obj)->
|
|
87
|
+
obj = Luca.util.resolve(obj) if _.isString(obj)
|
|
85
88
|
_.isFunction(obj?.render) and !_.isUndefined(obj?.el)
|
|
86
89
|
|
|
87
90
|
Luca.isBackboneCollection = (obj)->
|
|
91
|
+
obj = Luca.util.resolve(obj) if _.isString(obj)
|
|
88
92
|
_.isFunction(obj?.fetch) and _.isFunction(obj?.reset)
|
|
89
93
|
|
|
90
94
|
Luca.isViewPrototype = (obj)->
|
|
95
|
+
obj = Luca.util.resolve(obj) if _.isString(obj)
|
|
91
96
|
obj? and obj::? and obj::make? and obj::$? and obj::render?
|
|
92
97
|
|
|
93
98
|
Luca.isModelPrototype = (obj)->
|
|
99
|
+
obj = Luca.util.resolve(obj) if _.isString(obj)
|
|
94
100
|
obj? and obj::? obj::save? and obj::changedAttributes?
|
|
95
101
|
|
|
96
102
|
Luca.isCollectionPrototype = (obj)->
|
|
103
|
+
obj = Luca.util.resolve(obj) if _.isString(obj)
|
|
97
104
|
obj? and obj::? and !Luca.isModelPrototype(obj) and obj::reset? and obj::select? and obj::reject?
|
|
98
105
|
|
|
99
106
|
Luca.inheritanceChain = (obj)->
|
|
@@ -168,7 +175,6 @@ Luca.available_templates = (filter="")->
|
|
|
168
175
|
available
|
|
169
176
|
|
|
170
177
|
|
|
171
|
-
|
|
172
178
|
UnderscoreExtensions =
|
|
173
179
|
module: (base,module)->
|
|
174
180
|
_.extend base, module
|