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 +4 -4
- data/lib/neat/rails/version.rb +1 -1
- data/vendor/assets/javascripts/neat.js +1 -0
- data/vendor/assets/javascripts/neat/collection_editor.coffee +36 -12
- data/vendor/assets/javascripts/neat/lib/observer.js +42 -0
- data/vendor/assets/javascripts/neat/model_editor.coffee +60 -25
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 695ee4ffacf2d5ff9962b563842796a8e19f1133
|
4
|
+
data.tar.gz: 5d86e89f8d9fa6bd3d8bcf4b890bac853047b568
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26244d4b5882ee55c5413495fe5897dbb93473f4f1135bd3610a0059e368e6cc3f38a41b7037398e3bfe0608670bc038ae5a1e0ebf18e39eebaf9e2a5674cb5f
|
7
|
+
data.tar.gz: 110fbfca1f62d9101e10f605ac46663a5dbff5ebb7428d765b529d4ba8cebcd9a6baf5299fd40d2f83f9b3acd7aa95d71424216c72637e5317d44af172a0fa3f
|
data/lib/neat/rails/version.rb
CHANGED
@@ -20,14 +20,13 @@ class window.Neat.CollectionEditor extends Backbone.View
|
|
20
20
|
sortAliases: {}
|
21
21
|
templateOptions: {}
|
22
22
|
pageSize: 30
|
23
|
-
|
24
|
-
|
25
|
-
|
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',
|
47
|
-
@collection.bind 'add',
|
48
|
-
@collection.bind 'remove',
|
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',
|
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(
|
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
|
-
|
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 =
|
15
|
-
@editTemplate =
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
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
|
-
|
33
|
-
|
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
|
-
|
37
|
-
|
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
|
-
|
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
|
-
|
52
|
-
$el.addClass('editor').removeClass('editable hovered')
|
59
|
+
@$el.addClass('editor').removeClass('neat-editable hovered')
|
53
60
|
@trigger('edit:begin')
|
54
61
|
@render()
|
55
|
-
|
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
|
-
|
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
|
-
|
81
|
-
|
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
|
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:
|
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.
|
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!
|