neat-rails 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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!
|