luca 0.8.599 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/CHANGELOG +51 -2
- data/README.md +10 -247
- data/ROADMAP +6 -2
- data/app.rb +16 -2
- data/assets/javascripts/dependencies/bootstrap.min.js +7 -1
- data/assets/javascripts/dependencies/codemirror-coffeescript.js +347 -0
- data/assets/javascripts/dependencies/codemirror-css.js +124 -0
- data/assets/javascripts/dependencies/codemirror-html.js +410 -0
- data/assets/javascripts/dependencies/codemirror-javascript.js +361 -0
- data/assets/javascripts/dependencies/codemirror-less.js +232 -0
- data/assets/javascripts/dependencies/codemirror-vim.js +500 -0
- data/assets/javascripts/dependencies/codemirror.js +3076 -0
- data/assets/javascripts/dependencies.coffee +0 -1
- data/assets/javascripts/luca-ui-base.coffee +10 -3
- data/assets/javascripts/luca-ui-bootstrap.js +1 -0
- data/assets/javascripts/luca-ui-development-tools.coffee +9 -0
- data/assets/javascripts/luca-ui.coffee +6 -1
- data/assets/javascripts/sandbox/application.coffee +51 -0
- data/assets/javascripts/sandbox/router.coffee +14 -0
- data/assets/javascripts/sandbox/templates/main.luca +33 -0
- data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +1 -0
- data/assets/javascripts/sandbox/templates/sandbox.luca +1 -0
- data/assets/javascripts/sandbox/views/top_navigation.coffee +4 -0
- data/assets/javascripts/sandbox.coffee +2 -2
- data/assets/stylesheets/bootstrap.min.css +395 -297
- data/assets/stylesheets/codemirror-blackboard.css +25 -0
- data/assets/stylesheets/codemirror-monokai.css +33 -0
- data/assets/stylesheets/codemirror.css +126 -0
- data/assets/stylesheets/luca-ui-bootstrap.css +0 -1
- data/assets/stylesheets/luca-ui-development-tools.css +5 -0
- data/assets/stylesheets/sandbox/sandbox.scss +1 -3
- data/assets/stylesheets/themes/amelia-bootstrap.css +826 -0
- data/assets/stylesheets/themes/slate-bootstrap.css +797 -0
- data/assets/stylesheets/themes/superhero-bootstrap.css +830 -0
- data/lib/luca/code_browser.rb +55 -0
- data/lib/luca/rails/version.rb +1 -1
- data/lib/luca/rails.rb +1 -0
- data/spec/components/fields/checkbox_array_spec.coffee +46 -0
- data/spec/components/form_view_spec.coffee +10 -4
- data/spec/containers/card_view_spec.coffee +7 -0
- data/spec/core/collection_spec.coffee +58 -4
- data/spec/core/container_spec.coffee +6 -6
- data/spec/core/view_spec.coffee +93 -7
- data/spec/framework_spec.coffee +15 -12
- data/src/components/application.coffee +126 -18
- data/src/components/base_toolbar.coffee +2 -2
- data/src/components/collection_loader_view.coffee +1 -2
- data/src/components/collection_view.coffee +77 -0
- data/src/components/controller.coffee +1 -4
- data/src/components/fields/button_field.coffee +1 -1
- data/src/components/fields/checkbox_array.coffee +2 -2
- data/src/components/fields/checkbox_field.coffee +3 -1
- data/src/components/fields/file_upload_field.coffee +1 -1
- data/src/components/fields/hidden_field.coffee +1 -1
- data/src/components/fields/select_field.coffee +1 -1
- data/src/components/fields/text_area_field.coffee +1 -1
- data/src/components/fields/text_field.coffee +10 -6
- data/src/components/fields/type_ahead_field.coffee +18 -5
- data/src/components/form_button_toolbar.coffee +1 -2
- data/src/components/form_view.coffee +44 -62
- data/src/components/grid_view.coffee +27 -20
- data/src/components/load_mask.coffee +3 -0
- data/src/components/nav_bar.coffee +26 -0
- data/src/components/record_manager.coffee +1 -3
- data/src/components/router.coffee +1 -1
- data/src/components/template.coffee +3 -15
- data/src/components/toolbar_dialog.coffee +25 -0
- data/src/containers/card_view.coffee +22 -23
- data/src/containers/column_view.coffee +1 -6
- data/src/containers/modal_view.coffee +20 -71
- data/src/containers/panel_toolbar.coffee +156 -0
- data/src/containers/panel_view.coffee +1 -1
- data/src/containers/split_view.coffee +1 -3
- data/src/containers/tab_view.coffee +29 -29
- data/src/containers/viewport.coffee +38 -3
- data/src/core/collection.coffee +80 -48
- data/src/core/container.coffee +153 -72
- data/src/core/core.coffee +181 -0
- data/src/core/field.coffee +4 -2
- data/src/core/model.coffee +1 -1
- data/src/core/observer.coffee +3 -3
- data/src/core/panel.coffee +143 -0
- data/src/core/registry.coffee +104 -0
- data/src/core/util.coffee +82 -0
- data/src/core/view.coffee +158 -85
- data/src/framework.coffee +112 -178
- data/src/index.coffee +0 -255
- data/src/managers/collection_manager.coffee +1 -0
- data/src/samples/definition.coffee +49 -0
- data/src/stylesheets/base.scss +0 -78
- data/src/stylesheets/components/form_view.scss +8 -3
- data/src/stylesheets/components/grid_view.scss +3 -7
- data/src/stylesheets/components/load_mask.scss +14 -0
- data/src/stylesheets/components/toolbar.scss +0 -15
- data/src/stylesheets/containers/container.scss +14 -2
- data/src/stylesheets/containers/panels.scss +23 -0
- data/src/stylesheets/tools/class_browser.scss +32 -0
- data/src/stylesheets/tools/code_editor.scss +24 -0
- data/src/stylesheets/tools/component_tester.scss +8 -0
- data/src/stylesheets/tools/console.scss +26 -0
- data/src/templates/components/collection_loader_view.luca +1 -1
- data/src/templates/components/form_view.luca +2 -13
- data/src/templates/components/grid_view.luca +0 -2
- data/src/templates/components/load_mask.luca +3 -0
- data/src/templates/components/nav_bar.luca +2 -0
- data/src/templates/containers/tab_view.luca +1 -0
- data/src/templates/fields/text_field.luca +4 -1
- data/src/tools/class_browser.coffee +39 -0
- data/src/tools/code_editor.coffee +258 -0
- data/src/tools/code_mirror_field.coffee +57 -0
- data/src/tools/coffee_script_editor.coffee +60 -0
- data/src/tools/collection_inspector.coffee +4 -0
- data/src/tools/component_tester.coffee +472 -0
- data/src/tools/components/class_browser_detail.coffee +10 -0
- data/src/tools/components/class_browser_list.coffee +74 -0
- data/src/tools/console.coffee +147 -0
- data/src/tools/development_console.coffee +147 -0
- data/src/tools/models/components.coffee +63 -0
- data/src/tools/templates/component_tester/help.luca +14 -0
- data/vendor/assets/javascripts/luca-ui-base.js +1389 -611
- data/vendor/assets/javascripts/luca-ui-bootstrap.js +9 -0
- data/vendor/assets/javascripts/luca-ui-development-tools.js +18719 -0
- data/vendor/assets/javascripts/luca-ui-spec.js +2065 -878
- data/vendor/assets/javascripts/luca-ui.js +1759 -852
- data/vendor/assets/javascripts/luca-ui.min.js +3 -3
- data/vendor/assets/stylesheets/luca-ui-bootstrap.css +494 -440
- data/vendor/assets/stylesheets/luca-ui-development-tools.css +224 -0
- data/vendor/assets/stylesheets/luca-ui-spec.css +99 -140
- data/vendor/assets/stylesheets/luca-ui.css +99 -140
- data/views/index.erb +6 -3
- metadata +60 -18
- data/assets/javascripts/dependencies/jquery-console.js +0 -649
- data/assets/javascripts/development-console.coffee +0 -2
- data/assets/javascripts/sandbox/sandbox.coffee +0 -16
- data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +0 -33
- data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +0 -48
- data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +0 -24
- data/assets/javascripts/sandbox/templates/features/introduction.luca +0 -11
- data/assets/javascripts/sandbox/templates/features/view_helpers.luca +0 -43
- data/assets/javascripts/sandbox/templates/navigation.luca +0 -8
- data/assets/javascripts/sandbox/views/form_demo.coffee +0 -47
- data/assets/javascripts/sandbox/views/grid_demo.coffee +0 -23
- data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +0 -1
- data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +0 -38
- data/src/components/collection_inspector.coffee +0 -2
- data/src/components/development_console.coffee +0 -59
- data/src/stylesheets/components/development_console.scss +0 -47
@@ -0,0 +1,181 @@
|
|
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
|
+
# automatically register this with the component registry
|
63
|
+
Luca.register( _.string.underscored(@componentId), @componentName)
|
64
|
+
|
65
|
+
at[@componentId]
|
66
|
+
|
67
|
+
# The last method of the DefineProxy chain is always going to result in
|
68
|
+
# a call to Luca.extend. Luca.extend wraps the call to Luca.View.extend,
|
69
|
+
# or Backbone.Collection.extend, and accepts the names of the extending,
|
70
|
+
# and extended classes as strings. This allows us to maintain information
|
71
|
+
# and references to the classes and their prototypes, mainly for the purposes
|
72
|
+
# of introspection and development tools
|
73
|
+
Luca.extend = (superClassName, childName, properties={})->
|
74
|
+
superClass = Luca.util.resolve( superClassName, (window || global) )
|
75
|
+
|
76
|
+
unless _.isFunction(superClass?.extend)
|
77
|
+
throw "#{ superClassName } is not a valid component to extend from"
|
78
|
+
|
79
|
+
properties.displayName = childName
|
80
|
+
|
81
|
+
properties._superClass = ()->
|
82
|
+
superClass.displayName ||= superClassName
|
83
|
+
superClass
|
84
|
+
|
85
|
+
properties._super = (method, context, args)->
|
86
|
+
@_superClass().prototype[method]?.apply(context, args)
|
87
|
+
|
88
|
+
superClass.extend(properties)
|
89
|
+
|
90
|
+
_.mixin
|
91
|
+
def: Luca.define
|
92
|
+
|
93
|
+
|
94
|
+
# Luca.Events
|
95
|
+
#
|
96
|
+
# These helpers will get mixed into Luca.Collection, Luca.View, and Luca.Model.
|
97
|
+
#
|
98
|
+
# They allow for syntactic sugar like:
|
99
|
+
#
|
100
|
+
# view.defer("someMethodOnTheView").until("collection","fetch")
|
101
|
+
#
|
102
|
+
# or
|
103
|
+
#
|
104
|
+
# view.defer( myCallback ).until("triggered:event")
|
105
|
+
class DeferredBindingProxy
|
106
|
+
constructor: (@object, operation, wrapWithUnderscore=true)->
|
107
|
+
if _.isFunction(operation)
|
108
|
+
fn = operation
|
109
|
+
|
110
|
+
else if _.isString(operation) and _.isFunction(@object[operation])
|
111
|
+
fn = @object[operation]
|
112
|
+
|
113
|
+
unless _.isFunction(fn)
|
114
|
+
throw "Must pass a function or a string representing one"
|
115
|
+
|
116
|
+
if wrapWithUnderscore is true
|
117
|
+
@fn = ()=>
|
118
|
+
_.defer(fn)
|
119
|
+
else
|
120
|
+
@fn = fn
|
121
|
+
|
122
|
+
@
|
123
|
+
|
124
|
+
# until accepts an object to bind to, and a trigger to bind with
|
125
|
+
# if you just pass a trigger, the object getting bound to
|
126
|
+
# will implicitly be @object
|
127
|
+
until: (watch, trigger)->
|
128
|
+
if watch? and not trigger?
|
129
|
+
trigger = watch
|
130
|
+
watch = @object
|
131
|
+
|
132
|
+
watch.once(trigger, @fn)
|
133
|
+
|
134
|
+
@object
|
135
|
+
|
136
|
+
Luca.Events =
|
137
|
+
defer: (operation, wrapWithUnderscore=true)->
|
138
|
+
new DeferredBindingProxy(@, operation, wrapWithUnderscore)
|
139
|
+
|
140
|
+
once: (trigger, callback, context)->
|
141
|
+
context ||= @
|
142
|
+
|
143
|
+
onceFn = ()->
|
144
|
+
callback.apply(context, arguments)
|
145
|
+
@unbind(trigger, onceFn)
|
146
|
+
|
147
|
+
@bind trigger, onceFn
|
148
|
+
|
149
|
+
class Luca.ScriptLoader
|
150
|
+
@loaded: {}
|
151
|
+
|
152
|
+
constructor: (options={})->
|
153
|
+
_.extend(@, Backbone.Events, Luca.Events)
|
154
|
+
@autoStart = options.autoStart is true
|
155
|
+
@scripts = options.scripts
|
156
|
+
|
157
|
+
ready = ()-> @trigger("ready")
|
158
|
+
|
159
|
+
@ready = _.after( @scripts.length, ready)
|
160
|
+
|
161
|
+
_.bindAll @, "load", "ready"
|
162
|
+
|
163
|
+
@defer("load").until(@, "start")
|
164
|
+
|
165
|
+
if @autoStart is true
|
166
|
+
@trigger("start")
|
167
|
+
|
168
|
+
@bind "ready", @onReady
|
169
|
+
|
170
|
+
applyPrefix: (script)->
|
171
|
+
script
|
172
|
+
|
173
|
+
onReady: ()->
|
174
|
+
console.log "All dependencies loaded"
|
175
|
+
|
176
|
+
start: ()->
|
177
|
+
@trigger("start")
|
178
|
+
|
179
|
+
load: ()->
|
180
|
+
Luca.util.loadScript( @applyPrefix(script), @ready ) for script in @scripts
|
181
|
+
|
data/src/core/field.coffee
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
_.
|
1
|
+
_.def('Luca.core.Field').extends('Luca.View').with
|
2
2
|
|
3
3
|
className: 'luca-ui-text-field luca-ui-field'
|
4
4
|
|
@@ -23,10 +23,10 @@ _.component('Luca.core.Field').extends('Luca.View').with
|
|
23
23
|
|
24
24
|
initialize: (@options={})->
|
25
25
|
_.extend @, @options
|
26
|
-
Luca.View::initialize.apply(@, arguments)
|
27
26
|
|
28
27
|
@input_id ||= _.uniqueId('field')
|
29
28
|
@input_name ||= @name
|
29
|
+
@input_class ||= ""
|
30
30
|
@helperText ||= ""
|
31
31
|
@label ||= "*#{ @label }" if @required and not @label?.match(/^\*/)
|
32
32
|
@inputStyles ||= ""
|
@@ -36,6 +36,8 @@ _.component('Luca.core.Field').extends('Luca.View').with
|
|
36
36
|
@updateState( @state )
|
37
37
|
@placeHolder ||= ""
|
38
38
|
|
39
|
+
Luca.View::initialize.apply(@, arguments)
|
40
|
+
|
39
41
|
beforeRender: ()->
|
40
42
|
if Luca.enableBootstrap
|
41
43
|
@$el.addClass('control-group')
|
data/src/core/model.coffee
CHANGED
data/src/core/observer.coffee
CHANGED
@@ -4,10 +4,10 @@ class Luca.Observer
|
|
4
4
|
@type = @options.type
|
5
5
|
|
6
6
|
if @options.debugAll
|
7
|
-
@bind "
|
8
|
-
console.log "
|
9
|
-
|
7
|
+
@bind "all", (trigger, one, two)=>
|
8
|
+
console.log "ALL", trigger, one, two
|
10
9
|
relay: (triggerer, args...)->
|
10
|
+
console.log "Relaying", trigger, args
|
11
11
|
@trigger "event", triggerer, args
|
12
12
|
@trigger "event:#{ args[0] }", triggerer, args.slice(1)
|
13
13
|
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# This is a helper for creating the DOM element that go along with
|
2
|
+
# a given component, if it is configured to use one via the topToolbar
|
3
|
+
# and bottomToolbar properties
|
4
|
+
attachToolbar = (config={})->
|
5
|
+
config.orientation ||= "top"
|
6
|
+
config.ctype ||= @toolbarType || "panel_toolbar"
|
7
|
+
|
8
|
+
id = "#{ @cid }-tbc-#{ config.orientation }"
|
9
|
+
|
10
|
+
toolbar = Luca.util.lazyComponent( config )
|
11
|
+
|
12
|
+
container = @make "div",
|
13
|
+
class:"toolbar-container #{ config.orientation }",
|
14
|
+
id: id
|
15
|
+
,
|
16
|
+
toolbar.render().el
|
17
|
+
|
18
|
+
hasBody = @bodyClassName or @bodyTagName
|
19
|
+
|
20
|
+
# there will be a body panel inside of the views $el
|
21
|
+
# so just place the toolbar before, or after the body
|
22
|
+
action = switch config.orientation
|
23
|
+
when "top", "left"
|
24
|
+
if hasBody then "before" else "prepend"
|
25
|
+
when "bottom", "right"
|
26
|
+
if hasBody then "after" else "append"
|
27
|
+
|
28
|
+
@$bodyEl()[action]( container )
|
29
|
+
|
30
|
+
# A Panel is a basic Luca.View but with Toolbar extensions
|
31
|
+
#
|
32
|
+
# In general other components should inherit from the panel class.
|
33
|
+
|
34
|
+
_.def("Luca.components.Panel").extends("Luca.View").with
|
35
|
+
|
36
|
+
topToolbar: undefined
|
37
|
+
|
38
|
+
bottomToolbar: undefined
|
39
|
+
|
40
|
+
# Load Mask will apply a transparent overlay over the form
|
41
|
+
# upon submission, with a moving progress bar which will be
|
42
|
+
# hidden upon successful response
|
43
|
+
loadMask: false
|
44
|
+
loadMaskTemplate: ["components/load_mask"]
|
45
|
+
|
46
|
+
initialize: (@options={})->
|
47
|
+
Luca.View::initialize.apply(@, arguments)
|
48
|
+
|
49
|
+
if @loadMask is true
|
50
|
+
@defer ()=>
|
51
|
+
@$el.addClass('with-mask')
|
52
|
+
|
53
|
+
if @$('.load-mask').length is 0
|
54
|
+
@loadMaskTarget().prepend Luca.template(@loadMaskTemplate, @)
|
55
|
+
@$('.load-mask').hide()
|
56
|
+
.until("after:render")
|
57
|
+
|
58
|
+
@on "enable:loadmask", @applyLoadMask
|
59
|
+
@on "disable:loadmask", @applyLoadMask
|
60
|
+
|
61
|
+
loadMaskTarget: ()->
|
62
|
+
if @loadMaskEl? then @$(@loadMaskEl) else @$bodyEl()
|
63
|
+
|
64
|
+
applyLoadMask: ()->
|
65
|
+
if @$('.load-mask').is(":visible")
|
66
|
+
@$('.load-mask .bar').css("width","100%")
|
67
|
+
@$('.load-mask').hide()
|
68
|
+
clearInterval(@loadMaskInterval)
|
69
|
+
else
|
70
|
+
@$('.load-mask').show().find('.bar').css("width","0%")
|
71
|
+
maxWidth = @$('.load-mask .progress').width()
|
72
|
+
if maxWidth < 20 and (maxWidth = @$el.width()) < 20
|
73
|
+
maxWidth = @$el.parent().width()
|
74
|
+
|
75
|
+
@loadMaskInterval = setInterval ()=>
|
76
|
+
currentWidth = @$('.load-mask .bar').width()
|
77
|
+
newWidth = currentWidth + 12
|
78
|
+
@$('.load-mask .bar').css('width', newWidth)
|
79
|
+
, 200
|
80
|
+
|
81
|
+
applyStyles: (styles={},body=false)->
|
82
|
+
|
83
|
+
target = if body then @$bodyEl() else @$el
|
84
|
+
|
85
|
+
for setting, value of styles
|
86
|
+
target.css(setting,value)
|
87
|
+
|
88
|
+
@
|
89
|
+
|
90
|
+
beforeRender: ()->
|
91
|
+
Luca.View::beforeRender?.apply(@, arguments)
|
92
|
+
@applyStyles( @styles ) if @styles?
|
93
|
+
@applyStyles( @bodyStyles, true ) if @bodyStyles?
|
94
|
+
@renderToolbars?()
|
95
|
+
|
96
|
+
$bodyEl: ()->
|
97
|
+
element = @bodyTagName || "div"
|
98
|
+
className = @bodyClassName || "view-body"
|
99
|
+
|
100
|
+
@bodyEl ||= "#{ element }.#{ className }"
|
101
|
+
|
102
|
+
bodyEl = @$(@bodyEl)
|
103
|
+
|
104
|
+
return bodyEl if bodyEl.length > 0
|
105
|
+
|
106
|
+
# if we've been configured to have one, and it doesn't exist
|
107
|
+
# then we should append it to ourselves
|
108
|
+
if bodyEl.length is 0 and (@bodyClassName? || @bodyTagName?)
|
109
|
+
newElement = @make(element,class:className,"data-auto-appended":true)
|
110
|
+
$(@el).append( newElement )
|
111
|
+
return @$(@bodyEl)
|
112
|
+
|
113
|
+
|
114
|
+
$(@el)
|
115
|
+
|
116
|
+
$wrap: (wrapper)->
|
117
|
+
if !wrapper.match(/[<>]/)
|
118
|
+
wrapper = @make("div",class:wrapper)
|
119
|
+
|
120
|
+
@$el.wrap( wrapper )
|
121
|
+
|
122
|
+
$template: (template, variables={})->
|
123
|
+
@$html( Luca.template(template,variables) )
|
124
|
+
|
125
|
+
$html: (content)->
|
126
|
+
@$bodyEl().html( content )
|
127
|
+
|
128
|
+
$append: (content)->
|
129
|
+
@$bodyEl().append(content)
|
130
|
+
|
131
|
+
# Luca containers can have toolbars,
|
132
|
+
# these will get injected before or after the bodyEl, or at the top
|
133
|
+
# or bottom of the $el
|
134
|
+
renderToolbars: ()->
|
135
|
+
_( ["top","left","right","bottom"] ).each (orientation)=>
|
136
|
+
if config = @["#{ orientation }Toolbar"]
|
137
|
+
@renderToolbar( orientation, config)
|
138
|
+
|
139
|
+
renderToolbar: (orientation="top", config={})->
|
140
|
+
config.parent = @
|
141
|
+
config.orientation = orientation
|
142
|
+
|
143
|
+
attachToolbar.call(@, config)
|
@@ -0,0 +1,104 @@
|
|
1
|
+
registry =
|
2
|
+
classes:{}
|
3
|
+
namespaces:['Luca.containers','Luca.components']
|
4
|
+
|
5
|
+
component_cache =
|
6
|
+
cid_index: {}
|
7
|
+
name_index: {}
|
8
|
+
|
9
|
+
# For container views, if a component is defined with no ctype
|
10
|
+
# then we will pick this one when using
|
11
|
+
Luca.defaultComponentType = 'view'
|
12
|
+
|
13
|
+
|
14
|
+
# When you use _.def to define a component, you say
|
15
|
+
# which class it extends() from, and with() which enhancements.
|
16
|
+
|
17
|
+
# We register that component class for you:
|
18
|
+
Luca.register = (component, prototypeName)->
|
19
|
+
Luca.trigger "component:registered", component, prototypeName
|
20
|
+
registry.classes[ component ] = prototypeName
|
21
|
+
|
22
|
+
Luca.development_mode_register = (component, prototypeName)->
|
23
|
+
existing = registry.classes[component]
|
24
|
+
|
25
|
+
if Luca.enableDevelopmentTools is true and existing?
|
26
|
+
prototypeDefinition = Luca.util.resolve( existing, window)
|
27
|
+
|
28
|
+
liveInstances = Luca.registry.findInstancesByClassName( prototypeName )
|
29
|
+
|
30
|
+
_( liveInstances ).each (instance)->
|
31
|
+
instance?.refreshCode?.call(instance, prototypeDefinition)
|
32
|
+
|
33
|
+
Luca.register( component, prototypeName )
|
34
|
+
|
35
|
+
# We create a @ctype alias for this component definition, and register
|
36
|
+
# the class in a registry.
|
37
|
+
|
38
|
+
# If you use a custom namespace like MyApp.views.ListView,
|
39
|
+
# then we will register MyApp.views as a namespace. You can
|
40
|
+
# do this yourself too.
|
41
|
+
Luca.registry.addNamespace = (identifier)->
|
42
|
+
registry.namespaces.push( identifier )
|
43
|
+
registry.namespaces = _( registry.namespaces ).uniq()
|
44
|
+
|
45
|
+
# This allows us to declare relationships between objects at definition time
|
46
|
+
# and have the instances of these objects be created at runtime when they
|
47
|
+
# are available.
|
48
|
+
#
|
49
|
+
# it also allows us to build tools to monitor what is going on inside of an
|
50
|
+
# application, which makes testing and debugging easier, and also serves as
|
51
|
+
# the basis of Luca's in browser development tools.
|
52
|
+
Luca.registry.namespaces = (resolve=true)->
|
53
|
+
_( registry.namespaces ).map (namespace)->
|
54
|
+
if resolve then Luca.util.resolve( namespace ) else namespace
|
55
|
+
|
56
|
+
# Lookup a component in the Luca component registry
|
57
|
+
# by it's ctype identifier. If it doesn't exist,
|
58
|
+
# check any other registered namespace
|
59
|
+
Luca.registry.lookup = (ctype)->
|
60
|
+
c = registry.classes[ctype]
|
61
|
+
|
62
|
+
return c if c?
|
63
|
+
|
64
|
+
className = Luca.util.classify(ctype)
|
65
|
+
|
66
|
+
parents = Luca.registry.namespaces()
|
67
|
+
|
68
|
+
fullPath = _( parents ).chain().map((parent)->
|
69
|
+
parent[className]).compact().value()?[0]
|
70
|
+
|
71
|
+
Luca.registry.findInstancesByClassName = (className)->
|
72
|
+
instances = _( component_cache.cid_index ).values()
|
73
|
+
_( instances ).select (instance)->
|
74
|
+
instance.displayName is className or instance._superClass?()?.displayName is className
|
75
|
+
|
76
|
+
Luca.registry.classes = (toString=false)->
|
77
|
+
_( registry.classes ).map (className, ctype)->
|
78
|
+
if toString
|
79
|
+
className
|
80
|
+
else
|
81
|
+
className: className
|
82
|
+
ctype: ctype
|
83
|
+
|
84
|
+
Luca.cache = (needle, component)->
|
85
|
+
component_cache.cid_index[ needle ] = component if component?
|
86
|
+
|
87
|
+
component = component_cache.cid_index[ needle ]
|
88
|
+
|
89
|
+
# optionally, cache it by tying its name to its cid for easier lookups
|
90
|
+
if component?.component_name?
|
91
|
+
Luca.trigger "component:created:#{ component.component_name }", component
|
92
|
+
component_cache.name_index[ component.component_name ] = component.cid
|
93
|
+
else if component?.name?
|
94
|
+
Luca.trigger "component:created:#{ component.component_name }", component
|
95
|
+
component_cache.name_index[ component.name ] = component.cid
|
96
|
+
|
97
|
+
return component if component?
|
98
|
+
|
99
|
+
# perform a lookup by name if the component_id didn't turn anything
|
100
|
+
lookup_id = component_cache.name_index[ needle ]
|
101
|
+
|
102
|
+
component_cache.cid_index[ lookup_id ]
|
103
|
+
|
104
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Takes an string like "deep.nested.value" and an object like window
|
2
|
+
# and returns the value of window.deep.nested.value. useful for defining
|
3
|
+
# references on objects which don't yet exist, as strings, which get
|
4
|
+
# evaluated at runtime when such references will be available
|
5
|
+
Luca.util.resolve = (accessor, source_object)->
|
6
|
+
source_object ||= (window || global)
|
7
|
+
_( accessor.split(/\./) ).inject (obj,key)->
|
8
|
+
obj = obj?[key]
|
9
|
+
, source_object
|
10
|
+
|
11
|
+
# A better name for Luca.util.nestedValue
|
12
|
+
Luca.util.nestedValue = Luca.util.resolve
|
13
|
+
|
14
|
+
# turns a word like form_view into FormView
|
15
|
+
Luca.util.classify = (string="")->
|
16
|
+
_.string.camelize( _.string.capitalize( string ) )
|
17
|
+
|
18
|
+
# looks up a method on an object by its event trigger
|
19
|
+
# in the format of what:ever => whatEver
|
20
|
+
Luca.util.hook = (eventId="")->
|
21
|
+
parts = eventId.split(':')
|
22
|
+
prefix = parts.shift()
|
23
|
+
|
24
|
+
parts = _( parts ).map (p)-> _.string.capitalize(p)
|
25
|
+
fn = prefix + parts.join('')
|
26
|
+
|
27
|
+
Luca.util.isIE = ()->
|
28
|
+
try
|
29
|
+
Object.defineProperty({}, '', {})
|
30
|
+
return false
|
31
|
+
catch e
|
32
|
+
return true
|
33
|
+
|
34
|
+
currentNamespace = (window || global)
|
35
|
+
|
36
|
+
Luca.util.namespace = (namespace)->
|
37
|
+
return currentNamespace unless namespace?
|
38
|
+
currentNamespace = if _.isString(namespace) then Luca.util.resolve(namespace,(window||global)) else namespace
|
39
|
+
|
40
|
+
if currentNamespace?
|
41
|
+
return currentNamespace
|
42
|
+
|
43
|
+
currentNamespace = eval("(window||global).#{ namespace } = {}")
|
44
|
+
|
45
|
+
# one of the main benefits of Luca is the ability to structure your app as
|
46
|
+
# large blocks of JSON configuration. In order to convert an object into
|
47
|
+
# a Luca component, we lookup the object's class by converting its ctype / type
|
48
|
+
# property into a class that has been registered in the component registry
|
49
|
+
Luca.util.lazyComponent = (config)->
|
50
|
+
if _.isObject(config)
|
51
|
+
ctype = config.ctype || config.type
|
52
|
+
|
53
|
+
if _.isString(config)
|
54
|
+
ctype = config
|
55
|
+
|
56
|
+
componentClass = Luca.registry.lookup( ctype )
|
57
|
+
|
58
|
+
throw "Invalid Component Type: #{ ctype }. Did you forget to register it?" unless componentClass
|
59
|
+
|
60
|
+
constructor = eval( componentClass )
|
61
|
+
|
62
|
+
new constructor(config)
|
63
|
+
|
64
|
+
Luca.util.selectProperties = (iterator, object, context)->
|
65
|
+
values = _( object ).values()
|
66
|
+
_( values ).select( iterator )
|
67
|
+
|
68
|
+
Luca.util.loadScript = (url, callback) ->
|
69
|
+
script = document.createElement("script")
|
70
|
+
script.type = "text/javascript"
|
71
|
+
|
72
|
+
if (script.readyState)
|
73
|
+
script.onreadystatechange = ()->
|
74
|
+
if script.readyState == "loaded" || script.readyState == "complete"
|
75
|
+
script.onreadystatechange = null
|
76
|
+
callback()
|
77
|
+
else
|
78
|
+
script.onload = ()->
|
79
|
+
callback()
|
80
|
+
|
81
|
+
script.src = url
|
82
|
+
document.body.appendChild(script)
|