neat-rails 0.0.2 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0917bb29396d40820cd7ea76add02769a75ebf06
4
- data.tar.gz: 215afdec3ef8a2ea45eed909282ce24b33cb573a
3
+ metadata.gz: 695ee4ffacf2d5ff9962b563842796a8e19f1133
4
+ data.tar.gz: 5d86e89f8d9fa6bd3d8bcf4b890bac853047b568
5
5
  SHA512:
6
- metadata.gz: 881a5a3ee3673cf59dcb969c1fb92be12f0cc1851e238f7ab4842191ff28bd60667427c97d7479b5665ecd0b8e540412118e9aab8ee8f8741a843671f875a3c4
7
- data.tar.gz: a383cfcdfcf454b35d9a5d2d4486a127f2482de763ae076b6472338e05eb3455bc89ece97427f6af4e0fcfe2e7891c753c72a5185608fa179751fce892f66e33
6
+ metadata.gz: 26244d4b5882ee55c5413495fe5897dbb93473f4f1135bd3610a0059e368e6cc3f38a41b7037398e3bfe0608670bc038ae5a1e0ebf18e39eebaf9e2a5674cb5f
7
+ data.tar.gz: 110fbfca1f62d9101e10f605ac46663a5dbff5ebb7428d765b529d4ba8cebcd9a6baf5299fd40d2f83f9b3acd7aa95d71424216c72637e5317d44af172a0fa3f
@@ -1,5 +1,5 @@
1
1
  module Neat
2
2
  module Rails
3
- VERSION = "0.0.2"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -6,6 +6,7 @@
6
6
  //
7
7
  //= require_self
8
8
  //= require ./neat/lib/inflect
9
+ //= require ./neat/lib/observer
9
10
  //= require ./neat/lib/paginated_list
10
11
  //= require ./neat/lib/delayed_action
11
12
  //= require ./neat/lib/jquery_extensions
@@ -20,14 +20,13 @@ class window.Neat.CollectionEditor extends Backbone.View
20
20
  sortAliases: {}
21
21
  templateOptions: {}
22
22
  pageSize: 30
23
-
24
- keyDownHandlers:
25
- ESC: -> @viewInEdit?.cancelEdit()
26
- RETURN: -> @viewInEdit?.save()
27
- UP: -> @edit @prevView()
28
- DOWN: -> @edit @nextView()
23
+ useKeyboardToChangeRows: true
24
+ cancelOnEsc: true
25
+ saveOnEnter: true
29
26
 
30
27
  initialize: ->
28
+ @keyDownHandlers = {}
29
+
31
30
  @viewPath = @viewPath ? @resource
32
31
  @singular = inflect.singularize(@resource) # e.g. "calendar"
33
32
  @modelView = @modelView ? (()=>
@@ -43,9 +42,9 @@ class window.Neat.CollectionEditor extends Backbone.View
43
42
  always_show: false
44
43
  @paginator.onPageChange _.bind(@renderPage, @)
45
44
 
46
- @collection.bind 'reset', @render, @
47
- @collection.bind 'add', @rerenderPage, @
48
- @collection.bind 'remove', @rerenderPage, @
45
+ @collection.bind 'reset', @__reset, @
46
+ @collection.bind 'add', @__add, @
47
+ @collection.bind 'remove', @__remove, @
49
48
 
50
49
  # We need to rerender the page if a model's attributes
51
50
  # have changed just in case this would affect how the
@@ -67,13 +66,24 @@ class window.Neat.CollectionEditor extends Backbone.View
67
66
  # has settled into new state.
68
67
  #
69
68
  @delayedRerender = new Lail.DelayedAction(_.bind(@rerenderPage, @), delay: 500)
70
- @collection.bind 'change', @delayedRerender.trigger
69
+ @collection.bind 'change', =>
70
+ @delayedRerender.trigger() if @sortedBy
71
71
 
72
72
  # If the view's headers are 'a' tags, this view will try
73
73
  # to sort the collection using the header tags.
74
74
  $(@el).delegate '.header a', 'click', _.bind(@sort, @)
75
75
  $(@el).delegate '.editor', 'keydown', _.bind(@onKeyDown, @)
76
76
 
77
+ if @cancelOnEsc
78
+ @keyDownHandlers['ESC'] = -> @viewInEdit?.cancelEdit()
79
+
80
+ if @saveOnEnter
81
+ @keyDownHandlers['RETURN'] = -> @viewInEdit?.save()
82
+
83
+ if @useKeyboardToChangeRows
84
+ @keyDownHandlers['UP'] = -> @edit @prevView()
85
+ @keyDownHandlers['DOWN'] = -> @edit @nextView()
86
+
77
87
  @views = []
78
88
  @viewInEdit = null
79
89
  @templateOptions = {}
@@ -93,8 +103,8 @@ class window.Neat.CollectionEditor extends Backbone.View
93
103
 
94
104
  render: ->
95
105
  $el = $(@el)
96
- $el.html @template(collection: @collection)
97
- $el.cssHover '.row.interactive'
106
+ $el.html @template(@context())
107
+ $el.cssHover '.neat-row.neat-interactive'
98
108
 
99
109
  @afterRender()
100
110
 
@@ -104,6 +114,9 @@ class window.Neat.CollectionEditor extends Backbone.View
104
114
  @repaginate()
105
115
  @
106
116
 
117
+ context: ->
118
+ collection: @collection
119
+
107
120
  afterRender: ->
108
121
  @
109
122
 
@@ -208,6 +221,17 @@ class window.Neat.CollectionEditor extends Backbone.View
208
221
 
209
222
 
210
223
 
224
+ __reset: ->
225
+ @render()
226
+
227
+ __add: ->
228
+ @rerenderPage()
229
+
230
+ __remove: ->
231
+ @rerenderPage()
232
+
233
+
234
+
211
235
  debug: (o...)->
212
236
  @log(o...) if Neat.debug
213
237
 
@@ -0,0 +1,42 @@
1
+ /* Observer: this awesome class is described by The Grubbsian
2
+ http://www.thegrubbsian.com/?p=100 */
3
+ /* modified to use prototype extensions */
4
+
5
+ var Observer = (function(){
6
+ var Observation = function(name, func) {
7
+ this.name = name;
8
+ this.func = func;
9
+ };
10
+ var constructor = function() {
11
+ this.observations = [];
12
+ };
13
+ constructor.prototype = {
14
+ observe: function(name, func) {
15
+ var exists = this.observations.find(function(i) {
16
+ return (i.name==name) && (i.func==func);
17
+ });
18
+ if(!exists) {
19
+ this.observations.push(new Observation(name, func));
20
+ }
21
+ },
22
+ unobserve: function(name, func) {
23
+ for(var i=0; i<this.observations.length;) {
24
+ var observation = this.observations[i];
25
+ if((observation.name==name) && (observation.func==func)) {
26
+ this.observations.splice(i, 1);
27
+ } else {
28
+ i += 1;
29
+ }
30
+ }
31
+ },
32
+ fire: function(name, data, scope) {
33
+ if(!(data instanceof Array)) data = [data];
34
+ this.observations.each(function(i) {
35
+ if(i.name == name) {
36
+ i.func.apply(scope, data);
37
+ }
38
+ });
39
+ }
40
+ };
41
+ return constructor;
42
+ })();
@@ -1,67 +1,78 @@
1
1
  class window.Neat.ModelEditor extends Backbone.View
2
2
  tagName: 'li'
3
- className: 'row interactive editable'
3
+ className: 'neat-row neat-interactive neat-editable'
4
4
 
5
5
  initialize: (options)->
6
6
  options = options ? {}
7
7
  @templateOptions = options.templateOptions ? {}
8
8
  @viewPath = @viewPath ? options.viewPath
9
9
  @resource = @resource ? window.inflect.singularize(options.resource)
10
- $(@el).addClass(@resource)
10
+ @$el.addClass(@resource)
11
+
12
+ @model.bind 'change', @render, @
11
13
 
12
14
  # Renders the 'show' template normally,
13
15
  # renders 'edit' when in edit mode.
14
- @showTemplate = JST["#{@viewPath}/show"]
15
- @editTemplate = JST["#{@viewPath}/edit"]
16
+ @showTemplate = Neat.template["#{@viewPath}/show"]
17
+ @editTemplate = Neat.template["#{@viewPath}/edit"]
16
18
 
17
19
  # Wire up events.
18
20
  # Don't use Backbone's events hash because if subclasses
19
21
  # use that more familiar syntax, they'll blow away events
20
22
  # defined in this class.
21
- $(@el).delegate('.save-button', 'click', _.bind(@save, @))
22
- $(@el).delegate('.delete-button', 'click', _.bind(@delete, @))
23
- $(@el).delegate('.cancel-button', 'click', _.bind(@cancelEdit, @))
23
+ @$el.delegate('.save-button', 'click', _.bind(@save, @))
24
+ @$el.delegate('.delete-button', 'click', _.bind(@delete, @))
25
+ @$el.delegate('.cancel-button', 'click', _.bind(@cancelEdit, @))
24
26
 
25
27
  # Begin editing when this resource is clicked
26
28
  # unless the user clicked a link or button.
27
- $(@el).click (e)=>
29
+ @$el.click (e)=>
28
30
  @edit() if @canEdit() and !$(e.target).isIn('input, button, a, label')
29
31
 
30
32
  render: ->
31
33
  json = _.extend(@model.toJSON(), {options: @templateOptions})
32
- $(@el).html @template()(json)
33
- $(@el).attr('id', "#{@resource}_#{@model.get('id')}") # e.g. "calendar_5"
34
+ @$el.html @template()(json)
35
+ @$el.attr('id', "#{@resource}_#{@model.get('id')}") # e.g. "calendar_5"
36
+
37
+ @afterRender()
34
38
  @
35
39
 
36
- inEdit: -> $(@el).hasClass('editor')
37
- canEdit: -> $(@el).hasClass('editable') and !@inEdit()
40
+ afterRender: ->
41
+ @
42
+
43
+ inEdit: -> @$el.hasClass('editor')
44
+ canEdit: -> @$el.hasClass('neat-editable') and !@inEdit()
38
45
  template: -> if @inEdit() then @editTemplate else @showTemplate
39
46
 
40
47
  cancelEdit: (e)->
41
48
  e?.preventDefault()
42
49
  e?.stopImmediatePropagation()
43
50
  if @inEdit()
44
- $(@el).removeClass('editor').addClass('editable')
51
+ @$el.find(':focus').blur()
52
+ @$el.removeClass('editor').addClass('neat-editable')
45
53
  @render()
46
54
  @trigger('edit:end')
47
55
  @
48
56
 
49
57
  edit: ->
50
58
  unless @inEdit()
51
- $el = $(@el)
52
- $el.addClass('editor').removeClass('editable hovered')
59
+ @$el.addClass('editor').removeClass('neat-editable hovered')
53
60
  @trigger('edit:begin')
54
61
  @render()
55
- $el.find(':input:visible').first().focus()
62
+ @autofocus()
56
63
  @
57
64
 
65
+ autofocus: ->
66
+ @$el.find(':input:visible').first().focus()
67
+
58
68
  save: (e)->
59
69
  e?.preventDefault()
60
- $form = $(@el).closest('form')
61
- newAttributes = $form.serializeObject()
70
+ newAttributes = @attributesFromForm(@$el)
62
71
  @debug 'saving: ', newAttributes
63
72
  attributes = @model.changedAttributes(newAttributes)
64
73
 
74
+ return unless @okToSave(attributes)
75
+
65
76
  if attributes
66
77
  previousAttributes = @model.toJSON()
67
78
 
@@ -75,21 +86,45 @@ class window.Neat.ModelEditor extends Backbone.View
75
86
 
76
87
  @cancelEdit()
77
88
 
89
+ okToSave: (attributes)->
90
+ true
91
+
92
+ attributesFromForm: ($el)->
93
+ attrs = {}
94
+ $el.find('input, select, textarea').each ->
95
+ elem = $(this)
96
+ name = elem.attr('name')
97
+ if name
98
+ elemType = elem.attr('type')
99
+ value = elem.val()
100
+
101
+ if name.substr(-2) == '[]'
102
+ name = name.substring(0, name.length - 2)
103
+ attrs[name] = attrs[name] || []
104
+ attrs[name].push elem.val()
105
+
106
+ else if elemType == 'checkbox' || elemType == 'radio'
107
+ attrs[name] = '' if typeof(attrs[name]) == 'undefined'
108
+ attrs[name] = value if elem.prop('checked')
109
+
110
+ else
111
+ attrs[name] = value
112
+ attrs
113
+
78
114
  delete: (e)->
79
115
  e?.preventDefault()
80
- if @confirmDelete(@resource)
81
- $(@el).removeClass('editable').addClass('deleted')
116
+ @confirmDelete @resource, =>
117
+ @$el.removeClass('neat-editable').addClass('deleted')
82
118
 
83
119
  @model.destroy
84
120
  wait: true
85
- success: =>
86
- @model.collection.remove(@model) if @model.collection
87
- @onDeleteSuccess
121
+ success: => @onDeleteSuccess
88
122
  error: _.bind(@onSaveError, @)
89
123
  @cancelEdit()
90
124
 
91
- confirmDelete: (resource)->
92
- confirm("Delete this #{resource}?")
125
+ confirmDelete: (resource, callback)->
126
+ if confirm("Delete this #{resource}?")
127
+ callback()
93
128
 
94
129
 
95
130
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neat-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Lail
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-07 00:00:00.000000000 Z
12
+ date: 2015-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -47,6 +47,7 @@ files:
47
47
  - vendor/assets/javascripts/neat/lib/delayed_action.js
48
48
  - vendor/assets/javascripts/neat/lib/inflect.js
49
49
  - vendor/assets/javascripts/neat/lib/jquery_extensions.coffee
50
+ - vendor/assets/javascripts/neat/lib/observer.js
50
51
  - vendor/assets/javascripts/neat/lib/paginated_list.js
51
52
  - vendor/assets/javascripts/neat/model_editor.coffee
52
53
  homepage: ''
@@ -68,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
69
  version: '0'
69
70
  requirements: []
70
71
  rubyforge_project:
71
- rubygems_version: 2.2.0
72
+ rubygems_version: 2.2.2
72
73
  signing_key:
73
74
  specification_version: 4
74
75
  summary: It's like FreightTrain for Backbone. That's pretty neat!