luca 0.8.06 → 0.8.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/CHANGELOG +32 -1
  2. data/Guardfile +14 -9
  3. data/app.rb +1 -0
  4. data/assets/javascripts/sandbox/config.coffee +1 -1
  5. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +6 -0
  6. data/lib/luca/rails/version.rb +1 -1
  7. data/spec/framework_spec.coffee +33 -1
  8. data/src/components/application.coffee +1 -3
  9. data/src/components/base_toolbar.coffee +5 -6
  10. data/src/components/collection_inspector.coffee +2 -0
  11. data/src/components/collection_loader_view.coffee +7 -6
  12. data/src/components/controller.coffee +3 -1
  13. data/src/components/development_console.coffee +7 -4
  14. data/src/components/fields/button_field.coffee +2 -5
  15. data/src/components/fields/checkbox_array.coffee +64 -0
  16. data/src/components/fields/checkbox_field.coffee +7 -10
  17. data/src/components/fields/file_upload_field.coffee +3 -6
  18. data/src/components/fields/hidden_field.coffee +4 -10
  19. data/src/components/fields/select_field.coffee +15 -18
  20. data/src/components/fields/text_area_field.coffee +5 -8
  21. data/src/components/fields/text_field.coffee +7 -14
  22. data/src/components/fields/type_ahead_field.coffee +4 -6
  23. data/src/components/form_button_toolbar.coffee +4 -4
  24. data/src/components/form_view.coffee +24 -10
  25. data/src/components/grid_view.coffee +80 -42
  26. data/src/components/record_manager.coffee +21 -22
  27. data/src/components/template.coffee +6 -8
  28. data/src/containers/card_view.coffee +2 -4
  29. data/src/containers/column_view.coffee +10 -12
  30. data/src/containers/modal_view.coffee +7 -9
  31. data/src/containers/panel_view.coffee +4 -4
  32. data/src/containers/split_view.coffee +3 -5
  33. data/src/containers/tab_view.coffee +3 -2
  34. data/src/containers/viewport.coffee +2 -3
  35. data/src/core/container.coffee +4 -4
  36. data/src/core/field.coffee +14 -13
  37. data/src/core/model.coffee +1 -1
  38. data/src/core/view.coffee +12 -3
  39. data/src/framework.coffee +134 -17
  40. data/src/managers/collection_manager.coffee +1 -1
  41. data/src/stylesheets/components/development_console.scss +5 -0
  42. data/src/templates/fields/checkbox_array.luca +5 -0
  43. data/src/templates/fields/checkbox_array_item.luca +4 -0
  44. data/vendor/assets/javascripts/luca-ui-base.js +155 -43
  45. data/vendor/assets/javascripts/luca-ui-spec.js +385 -133
  46. data/vendor/assets/javascripts/luca-ui.js +344 -132
  47. data/vendor/assets/javascripts/luca-ui.min.js +3 -3
  48. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +4 -1
  49. data/vendor/assets/stylesheets/luca-ui-spec.css +4 -1
  50. data/vendor/assets/stylesheets/luca-ui.css +4 -1
  51. metadata +6 -2
@@ -5,7 +5,8 @@
5
5
  # it contains, assigning them to a DOM container, and
6
6
  # automatically instantiating and rendering the components
7
7
  # in their proper place.
8
- Luca.core.Container = Luca.View.extend
8
+ _.component('Luca.core.Container').extends('Luca.View').with
9
+
9
10
  className: 'luca-ui-container'
10
11
 
11
12
  componentClass: 'luca-ui-panel'
@@ -182,6 +183,7 @@ Luca.core.Container = Luca.View.extend
182
183
  console.log "Error Rendering Component #{ component.name || component.cid }", component
183
184
  console.log e.message
184
185
  console.log e.stack
186
+ throw e unless Luca.silenceRenderErrors? is true
185
187
 
186
188
  #### Container Activation
187
189
  #
@@ -261,6 +263,4 @@ Luca.core.Container = Luca.View.extend
261
263
  !@getParent?
262
264
 
263
265
  getRootComponent: ()->
264
- if @rootComponent() then @ else @getParent().getRootComponent()
265
-
266
- Luca.register "container", "Luca.core.Container"
266
+ if @rootComponent() then @ else @getParent().getRootComponent()
@@ -1,10 +1,11 @@
1
- Luca.core.Field = Luca.View.extend
1
+ _.component('Luca.core.Field').extends('Luca.View').with
2
+
2
3
  className: 'luca-ui-text-field luca-ui-field'
3
-
4
+
4
5
  isField: true
5
6
 
6
7
  template: 'fields/text_field'
7
-
8
+
8
9
  labelAlign: 'top'
9
10
 
10
11
  hooks:[
@@ -24,8 +25,8 @@ Luca.core.Field = Luca.View.extend
24
25
  _.extend @, @options
25
26
  Luca.View::initialize.apply(@, arguments)
26
27
 
27
- @input_id ||= _.uniqueId('field')
28
- @input_name ||= @name
28
+ @input_id ||= _.uniqueId('field')
29
+ @input_name ||= @name
29
30
  @helperText ||= ""
30
31
  @label ||= "*#{ @label }" if @required and not @label?.match(/^\*/)
31
32
  @inputStyles ||= ""
@@ -43,26 +44,26 @@ Luca.core.Field = Luca.View.extend
43
44
 
44
45
  @$el.html Luca.templates[ @template ]( @ )
45
46
  @input = $('input', @el)
46
-
47
+
47
48
  change_handler: (e)->
48
- @trigger "on:change", @, e
49
+ @trigger "on:change", @, e
49
50
 
50
51
  disable: ()->
51
52
  $("input",@el).attr('disabled', true)
52
-
53
+
53
54
  enable: ()->
54
- $("input", @el).attr('disabled', false)
55
+ $("input", @el).attr('disabled', false)
55
56
 
56
- getValue: ()->
57
+ getValue: ()->
57
58
  @input.attr('value')
58
59
 
59
60
  render: ()->
60
61
  $( @container ).append( @$el )
61
62
 
62
- setValue: (value)->
63
+ setValue: (value)->
63
64
  @input.attr('value', value)
64
-
65
+
65
66
  updateState: (state)->
66
- _( @statuses ).each (cls)=>
67
+ _( @statuses ).each (cls)=>
67
68
  @$el.removeClass(cls)
68
69
  @$el.addClass(state)
@@ -4,7 +4,7 @@
4
4
  # few useful patterns:
5
5
  #
6
6
  # - computed properties support
7
- Luca.Model = Backbone.Model.extend
7
+ _.component('Luca.Model').extends('Backbone.Model').with
8
8
  initialize: ()->
9
9
  Backbone.Model::initialize @, arguments
10
10
 
data/src/core/view.coffee CHANGED
@@ -35,6 +35,9 @@ Luca.View.extend = (definition)->
35
35
  return @
36
36
 
37
37
  definition.render = ()->
38
+ if @layoutTemplate?
39
+ @$el.html()
40
+
38
41
  if @deferrable
39
42
  @trigger "before:render", @
40
43
 
@@ -64,15 +67,21 @@ Luca.View.extend = (definition)->
64
67
 
65
68
  return @
66
69
 
67
- Luca.View.originalExtend.apply @, [definition]
70
+ Luca.View.originalExtend.call(@, definition)
68
71
 
69
72
  _.extend Luca.View.prototype,
73
+ applyStyles: (styles={})->
74
+ for setting, value of styles
75
+ @$el.css(setting,value)
76
+
77
+ @
78
+
70
79
  debug: ()->
71
80
  return unless @debugMode or window.LucaDebugMode?
72
81
  console.log [(@name || @cid),message] for message in arguments
73
82
 
74
83
  trigger: ()->
75
- if Luca.enableGlobalObserver
84
+ if Luca.enableGlobalObserver and @observeEvents is true
76
85
  Luca.ViewObserver ||= new Luca.Observer(type:"view")
77
86
  Luca.ViewObserver.relay @, arguments
78
87
 
@@ -141,7 +150,7 @@ _.extend Luca.View.prototype,
141
150
  parts = eventId.split(':')
142
151
  prefix = parts.shift()
143
152
 
144
- parts = _( parts ).map (p)-> _.capitalize(p)
153
+ parts = _( parts ).map (p)-> _.string.capitalize(p)
145
154
  fn = prefix + parts.join('')
146
155
 
147
156
  @bind eventId, ()=> @[fn].apply @, arguments if @[fn]
data/src/framework.coffee CHANGED
@@ -1,20 +1,24 @@
1
- _.mixin( _.string )
2
-
3
1
  window.Luca =
4
- VERSION: "0.8.06"
2
+ VERSION: "0.8.59"
5
3
  core: {}
6
4
  containers: {}
7
5
  components: {}
8
6
  modules: {}
9
- fields: {}
10
7
  util: {}
11
- registry:
12
- classes: {}
13
- namespaces:["Luca.containers","Luca.components"]
8
+ fields: {}
14
9
  component_cache:
15
10
  cid_index: {}
16
11
  name_index: {}
12
+ registry:
13
+ classes: {}
14
+ namespaces:["Luca.containers","Luca.components"]
15
+
17
16
 
17
+ # The Global Observer is very helpful in development
18
+ # it observes every event triggered on every view, collection, model
19
+ # and allows you to inspect / respond to them. Use in production
20
+ # may have performance impacts which has not been tested
21
+ Luca.enableGlobalObserver = false
18
22
 
19
23
  # let's use the Twitter 2.0 Bootstrap Framework
20
24
  # for what it is best at, and not try to solve this
@@ -58,12 +62,21 @@ Luca.cache = (needle, component)->
58
62
  Luca.component_cache.cid_index[ lookup_id ]
59
63
 
60
64
  # Takes an string like "deep.nested.value" and an object like window
61
- # and returns the value of window.deep.nested.value
62
- Luca.util.nestedValue = (accessor, source_object)->
65
+ # and returns the value of window.deep.nested.value. useful for defining
66
+ # references on objects which don't yet exist, as strings, which get
67
+ # evaluated at runtime when such references will be available
68
+ Luca.util.resolve = (accessor, source_object)->
63
69
  _( accessor.split(/\./) ).inject (obj,key)->
64
70
  obj = obj?[key]
65
71
  , source_object
66
72
 
73
+ # A better name for Luca.util.nestedValue
74
+ Luca.util.nestedValue = Luca.util.resolve
75
+
76
+ # turns a word like form_view into FormView
77
+ Luca.util.classify = (string="")->
78
+ _.string.camelize( _.string.capitalize( string ) )
79
+
67
80
  # Lookup a component in the Luca component registry
68
81
  # by it's ctype identifier. If it doesn't exist,
69
82
  # check any other registered namespace
@@ -72,16 +85,18 @@ Luca.registry.lookup = (ctype)->
72
85
 
73
86
  return c if c?
74
87
 
75
- className = _.camelize _.capitalize( ctype )
88
+ className = Luca.util.classify(ctype)
76
89
 
77
90
  parents = _( Luca.registry.namespaces ).map (namespace)-> Luca.util.nestedValue(namespace, (window || global))
78
91
 
79
- _.first _.compact _( parents ).map (parent)-> parent[className]
92
+ _( parents ).chain().map((parent)-> parent[className]).compact().value()?[0]
80
93
 
81
- # creates a new object from a hash with a ctype property
82
- # matching something in the Luca registry
94
+ # one of the main benefits of Luca is the ability to structure your app as
95
+ # large blocks of JSON configuration. In order to convert an object into
96
+ # a Luca component, we lookup the object's class by converting its ctype / type
97
+ # property into a class that has been registered in the component registry
83
98
  Luca.util.lazyComponent = (config)->
84
- ctype = config.ctype
99
+ ctype = config.ctype || config.type
85
100
 
86
101
  componentClass = Luca.registry.lookup( ctype )
87
102
 
@@ -95,8 +110,8 @@ Luca.util.lazyComponent = (config)->
95
110
  Luca.register = (component, constructor_class)->
96
111
  exists = Luca.registry.classes[component]
97
112
 
98
- if exists?
99
- throw "Can not register component with the signature #{ component }. Already exists"
113
+ if exists? and !window.TestRun?
114
+ console.log "Attempting to register component with the signature #{ component }. Already exists"
100
115
  else
101
116
  Luca.registry.classes[component] = constructor_class
102
117
 
@@ -115,5 +130,107 @@ Luca.util.isIE = ()->
115
130
  catch e
116
131
  return true
117
132
 
133
+ # This is a convenience method for accessing the templates
134
+ # available to the client side app, either the ones which ship with Luca
135
+ # available in Luca.templates ( these take precedence ) or
136
+ # the app's own templates which are usually available in JST
137
+
138
+ # optionally, passing in variables will compile the template for you, instead
139
+ # of returning a reference to the function which you would then call yourself
140
+ Luca.template = (template_name, variables)->
141
+ window.JST ||= {}
142
+
143
+ luca = Luca.templates?[ template_name ]
144
+ jst = JST?[ template_name ]
145
+
146
+ unless luca? or jst?
147
+ needle = new RegExp("#{ template_name }$")
148
+
149
+ luca = _( Luca.templates ).detect (fn,template_id)->
150
+ needle.exec( template_id )
151
+
152
+ jst = _( JST ).detect (fn,template_id)->
153
+ needle.exec( template_id )
154
+
155
+ throw "Could not find template with #{ template_name }" unless luca || jst
156
+
157
+ template = luca || jst
158
+
159
+ return template(variables) if variables?
160
+
161
+ template
162
+
163
+ #### Component Definition And Inheritance
164
+ #
165
+ # this is a nice way of extending / inheriting
166
+ # this allows for syntactic sugar such as:
167
+ #
168
+ # Luca.define("TestClass").extends("Luca.View").with
169
+ # property: "value"
170
+ # name: "whatever"
171
+ #
172
+ # All instances of TestClass defined this way, will have
173
+ # _className properties of 'TestClass' as well as a reference
174
+ # to the extended class 'Luca.View' so that you can inspect
175
+ # an instance of TestClass and know that it inherits from 'Luca.View'
176
+ class DefineProxy
177
+ constructor:(componentName)->
178
+ @namespace = (window || global)
179
+ @componentId = @componentName = componentName
180
+
181
+ if componentName.match(/\./)
182
+ @namespaced = true
183
+ parts = componentName.split('.')
184
+ @componentId = parts.pop()
185
+ @namespace = parts.join('.')
186
+
187
+ # automatically add the namespace to the namespace registry
188
+ Luca.registry.addNamespace( parts.join('.') )
189
+
190
+ in: (@namespace)-> @
191
+ from: (@superClassName)-> @
192
+ extends: (@superClassName)-> @
193
+ extend: (@superClassName)-> @
194
+ with: (properties)->
195
+ at = if @namespaced then Luca.util.resolve(@namespace, (window || global)) else (window||global)
196
+
197
+ if @namespaced and _.isUndefined(at)
198
+ eval("window.#{ @namespace } = {}")
199
+ at = Luca.util.resolve(@namespace,(window || global))
200
+
201
+ at[@componentId] = Luca.extend(@superClassName,@componentName, properties)
202
+
203
+ # automatically register this with the component registry
204
+ Luca.register( _.string.underscored(@componentId), @componentName)
205
+
206
+ at[@componentId]
207
+
208
+ Luca.define = (componentName)->
209
+ new DefineProxy(componentName)
210
+
211
+ # An alias for Luca.define
212
+ # which I think reads better:
213
+ #
214
+ # Luca.component('Whatever').extends('Something').with(enhancements)
215
+ Luca.component = Luca.define
216
+
217
+ Luca.extend = (superClassName, childName, properties={})->
218
+ superClass = Luca.util.resolve( superClassName, (window || global) )
219
+
220
+ unless _.isFunction(superClass?.extend)
221
+ throw "#{ superClassName } is not a valid component to extend from"
222
+
223
+ properties._className = childName
224
+
225
+ properties._superClass = ()->
226
+ superClass._className ||= superClassName
227
+ superClass
228
+
229
+ superClass.extend(properties)
230
+
231
+ _.mixin
232
+ component: Luca.define
233
+
234
+ #### Once We Are Ready To go....
118
235
  $ do ->
119
- $('body').addClass('luca-ui-enabled')
236
+ $('body').addClass('luca-ui-enabled')
@@ -125,7 +125,7 @@ class Luca.CollectionManager
125
125
  @get(key) || @create(key,collectionOptions,initialModels,false)
126
126
 
127
127
  guessCollectionClass: (key)->
128
- classified = _( key ).chain().capitalize().camelize().value()
128
+ classified = Luca.util.classify( key )
129
129
  guess = (@collectionNamespace || (window || global) )[ classified ]
130
130
  guess ||= (@collectionNamespace || (window || global) )[ "#{classified}Collection" ]
131
131
  guess
@@ -29,6 +29,10 @@
29
29
  background: rgba(255,255,255,0.2);
30
30
  }
31
31
 
32
+ .jquery-console-message {
33
+ margin:10px 0px;
34
+ }
35
+
32
36
  .jquery-console-message-error {
33
37
  font-weight: bold;
34
38
  color: #ef0505;
@@ -37,6 +41,7 @@
37
41
 
38
42
  .jquery-console-prompt-label {
39
43
  font-weight: bold;
44
+ color: yellow;
40
45
  }
41
46
  }
42
47
  }
@@ -0,0 +1,5 @@
1
+ .form-horizontal
2
+ .control-group
3
+ %label{:for=>"<%= input_id %>"}
4
+ <%= label %>
5
+ .controls
@@ -0,0 +1,4 @@
1
+ %label{:for => "<%= input_id %>"}
2
+ %input{:id => "<%= input_id %>", :type => "checkbox", :name => "<%= input_name %>", :value => "<%= value %>"}
3
+ <%= label %>
4
+