neat-rails 0.1.0 → 0.2.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.
- data/lib/neat/rails/version.rb +1 -1
- data/vendor/assets/javascripts/neat/collection_editor.coffee +69 -65
- data/vendor/assets/javascripts/neat/lib/delayed_action.js +7 -7
- data/vendor/assets/javascripts/neat/lib/inflect.js +19 -19
- data/vendor/assets/javascripts/neat/lib/jquery_extensions.coffee +2 -2
- data/vendor/assets/javascripts/neat/lib/observer.js +1 -1
- data/vendor/assets/javascripts/neat/lib/paginated_list.js +46 -46
- data/vendor/assets/javascripts/neat/model_editor.coffee +43 -38
- metadata +20 -10
- checksums.yaml +0 -7
data/lib/neat/rails/version.rb
CHANGED
@@ -15,7 +15,6 @@ KEYS = {
|
|
15
15
|
# viewPath - by default this is set to resource
|
16
16
|
#
|
17
17
|
class window.Neat.CollectionEditor extends Backbone.View
|
18
|
-
sortedBy: 'name'
|
19
18
|
sortOrder: 'asc'
|
20
19
|
sortAliases: {}
|
21
20
|
templateOptions: {}
|
@@ -23,29 +22,29 @@ class window.Neat.CollectionEditor extends Backbone.View
|
|
23
22
|
useKeyboardToChangeRows: true
|
24
23
|
cancelOnEsc: true
|
25
24
|
saveOnEnter: true
|
26
|
-
|
25
|
+
|
27
26
|
initialize: ->
|
28
27
|
@keyDownHandlers = {}
|
29
|
-
|
28
|
+
|
30
29
|
@viewPath = @viewPath ? @resource
|
31
30
|
@singular = inflect.singularize(@resource) # e.g. "calendar"
|
32
31
|
@modelView = @modelView ? (()=>
|
33
32
|
viewName = inflect.camelize(@singular) + "View" # e.g. "CalendarView"
|
34
33
|
@debug "expects viewName to be #{viewName}"
|
35
34
|
window[viewName])() # e.g. window["CalendarView"]
|
36
|
-
|
35
|
+
|
37
36
|
@debug "looking for template at #{"#{@viewPath}/index"}"
|
38
37
|
@template = @template ? Neat.template["#{@viewPath}/index"]
|
39
|
-
|
38
|
+
|
40
39
|
@paginator = new window.Lail.PaginatedList [],
|
41
40
|
page_size: if window.Neat.forPrint then Infinity else @pageSize
|
42
41
|
always_show: false
|
43
42
|
@paginator.onPageChange _.bind(@renderPage, @)
|
44
|
-
|
43
|
+
|
45
44
|
@collection.bind 'reset', @__reset, @
|
46
45
|
@collection.bind 'add', @__add, @
|
47
46
|
@collection.bind 'remove', @__remove, @
|
48
|
-
|
47
|
+
|
49
48
|
# We need to rerender the page if a model's attributes
|
50
49
|
# have changed just in case this would affect how the
|
51
50
|
# models are sorted.
|
@@ -68,96 +67,101 @@ class window.Neat.CollectionEditor extends Backbone.View
|
|
68
67
|
@delayedRerender = new Lail.DelayedAction(_.bind(@rerenderPage, @), delay: 500)
|
69
68
|
@collection.bind 'change', =>
|
70
69
|
@delayedRerender.trigger() if @sortedBy
|
71
|
-
|
70
|
+
|
72
71
|
# If the view's headers are 'a' tags, this view will try
|
73
72
|
# to sort the collection using the header tags.
|
74
73
|
$(@el).delegate '.header a', 'click', _.bind(@sort, @)
|
75
74
|
$(@el).delegate '.editor', 'keydown', _.bind(@onKeyDown, @)
|
76
|
-
|
75
|
+
|
77
76
|
if @cancelOnEsc
|
78
77
|
@keyDownHandlers['ESC'] = -> @viewInEdit?.cancelEdit()
|
79
|
-
|
78
|
+
|
80
79
|
if @saveOnEnter
|
81
80
|
@keyDownHandlers['RETURN'] = -> @viewInEdit?.save()
|
82
|
-
|
81
|
+
|
83
82
|
if @useKeyboardToChangeRows
|
84
83
|
@keyDownHandlers['UP'] = -> @edit @prevView()
|
85
84
|
@keyDownHandlers['DOWN'] = -> @edit @nextView()
|
86
|
-
|
85
|
+
|
87
86
|
@views = []
|
88
87
|
@viewInEdit = null
|
89
88
|
@templateOptions = {}
|
90
|
-
|
89
|
+
|
91
90
|
repaginate: ->
|
92
91
|
@rerenderPage(1)
|
93
|
-
|
92
|
+
|
94
93
|
rerenderPage: (page)->
|
95
94
|
page = @paginator.getCurrentPage() unless _.isNumber(page)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
if @sortedBy
|
96
|
+
sortField = @sortField(@sortedBy)
|
97
|
+
items = @collection.sortBy (model)->
|
98
|
+
val = model.get(sortField) || ''
|
99
|
+
if _.isString(val) then val.toLowerCase() else val
|
100
|
+
items.reverse() if @sortOrder == 'desc'
|
101
|
+
else
|
102
|
+
items = @collection.toArray()
|
101
103
|
@paginator.init items, page
|
102
|
-
|
103
|
-
|
104
|
+
|
105
|
+
|
104
106
|
render: ->
|
105
107
|
$el = $(@el)
|
106
108
|
$el.html @template(@context())
|
107
109
|
$el.cssHover '.neat-row.neat-interactive'
|
108
|
-
|
110
|
+
|
109
111
|
@afterRender()
|
110
|
-
|
112
|
+
|
111
113
|
@updateSortStyle() if @sortedBy
|
112
|
-
|
114
|
+
|
113
115
|
@paginator.renderPaginationIn($el.find('.pagination'))
|
114
116
|
@repaginate()
|
115
117
|
@
|
116
|
-
|
118
|
+
|
117
119
|
context: ->
|
118
120
|
collection: @collection
|
119
|
-
|
121
|
+
|
120
122
|
afterRender: ->
|
121
123
|
@
|
122
|
-
|
124
|
+
|
123
125
|
renderPage: ->
|
124
126
|
alt = false
|
125
127
|
$ul = $(@el).find("##{@resource}").empty() # e.g. $('#calendars')
|
126
128
|
@views = []
|
127
129
|
self = @
|
128
|
-
|
130
|
+
|
129
131
|
$(@el).find('.extended-pagination').html(@paginator.renderExtendedPagination())
|
130
|
-
|
132
|
+
|
131
133
|
for model in @paginator.getCurrentSet()
|
132
|
-
view =
|
134
|
+
view = @constructModelView # e.g. window.CalendarView
|
133
135
|
resource: @resource
|
134
136
|
viewPath: @viewPath
|
135
137
|
model: model
|
136
138
|
templateOptions: @templateOptions
|
137
139
|
view.bind 'edit:begin', -> self.beforeEdit.call(self, @)
|
138
140
|
view.bind 'edit:end', -> self.afterEdit.call(self, @)
|
139
|
-
|
141
|
+
|
140
142
|
@views.push(view)
|
141
|
-
|
143
|
+
|
142
144
|
$el = $(view.render().el)
|
143
145
|
$el.toggleClass 'alt', !(alt = !alt)
|
144
146
|
$ul.append $el
|
145
147
|
@
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
|
149
|
+
constructModelView: (options) ->
|
150
|
+
new @modelView options
|
151
|
+
|
152
|
+
|
149
153
|
beforeEdit: (view)->
|
150
|
-
if @viewInEdit
|
154
|
+
if @viewInEdit and @viewInEdit isnt view
|
151
155
|
@debug "cancelling edit for ##{$(@viewInEdit.el).attr('id')} (#{@indexOfViewInEdit()})"
|
152
156
|
@viewInEdit.cancelEdit()
|
153
157
|
@viewInEdit = view
|
154
158
|
@debug "beginning edit for ##{$(@viewInEdit.el).attr('id')} (#{@indexOfViewInEdit()})"
|
155
|
-
|
159
|
+
|
156
160
|
afterEdit: (view)->
|
157
161
|
@viewInEdit = null if @viewInEdit == view
|
158
|
-
|
159
|
-
|
160
|
-
|
162
|
+
|
163
|
+
|
164
|
+
|
161
165
|
sort: (e)->
|
162
166
|
e.preventDefault()
|
163
167
|
e.stopImmediatePropagation()
|
@@ -171,69 +175,69 @@ class window.Neat.CollectionEditor extends Backbone.View
|
|
171
175
|
@repaginate()
|
172
176
|
@updateSortStyle()
|
173
177
|
false
|
174
|
-
|
178
|
+
|
175
179
|
removeSortStyle: (field)->
|
176
|
-
|
180
|
+
|
177
181
|
updateSortStyle: ()->
|
178
182
|
@removeSortStyle @sortedBy
|
179
|
-
|
183
|
+
|
180
184
|
getHeader: (field)->
|
181
185
|
$(@el).find(".header > .#{@singular}-#{field}")
|
182
|
-
|
186
|
+
|
183
187
|
sortField: (field)->
|
184
188
|
@sortAliases[field] ? field
|
185
|
-
|
186
|
-
|
187
|
-
|
189
|
+
|
190
|
+
|
191
|
+
|
188
192
|
onKeyDown: (e)->
|
189
193
|
keyName = @identifyKey(e.keyCode)
|
190
194
|
handler = @keyDownHandlers[keyName]
|
191
195
|
if handler && !@ignoreKeyEventsForTarget(e.target)
|
192
196
|
e.preventDefault()
|
193
197
|
handler.apply(@)
|
194
|
-
|
198
|
+
|
195
199
|
identifyKey: (code)->
|
196
200
|
KEYS[code]
|
197
|
-
|
201
|
+
|
198
202
|
ignoreKeyEventsForTarget: (target)->
|
199
203
|
# i.e. return true if target is in a dropdown control like Chosen
|
200
204
|
false
|
201
|
-
|
202
|
-
|
203
|
-
|
205
|
+
|
206
|
+
|
207
|
+
|
204
208
|
nextView: ->
|
205
209
|
@views[@indexOfViewInEdit() + 1]
|
206
|
-
|
210
|
+
|
207
211
|
prevView: ->
|
208
212
|
@views[@indexOfViewInEdit() - 1]
|
209
|
-
|
213
|
+
|
210
214
|
indexOfViewInEdit: ->
|
211
215
|
_.indexOf @views, @viewInEdit
|
212
|
-
|
216
|
+
|
213
217
|
edit: (view)->
|
214
218
|
if view
|
215
219
|
@viewInEdit?.save()
|
216
220
|
view.edit()
|
217
221
|
@viewInEdit = view
|
218
|
-
|
222
|
+
|
219
223
|
cancelEdit: ->
|
220
224
|
@viewInEdit?.cancelEdit()
|
221
|
-
|
222
|
-
|
223
|
-
|
225
|
+
|
226
|
+
|
227
|
+
|
224
228
|
__reset: ->
|
225
229
|
@render()
|
226
|
-
|
230
|
+
|
227
231
|
__add: ->
|
228
232
|
@rerenderPage()
|
229
|
-
|
233
|
+
|
230
234
|
__remove: ->
|
231
235
|
@rerenderPage()
|
232
|
-
|
233
|
-
|
234
|
-
|
236
|
+
|
237
|
+
|
238
|
+
|
235
239
|
debug: (o...)->
|
236
240
|
@log(o...) if Neat.debug
|
237
|
-
|
241
|
+
|
238
242
|
log: (o...)->
|
239
243
|
Neat.logger.log "[#{@viewPath}] ", o...
|
@@ -1,7 +1,7 @@
|
|
1
1
|
var Lail; if(!Lail) Lail={};
|
2
2
|
Lail.DelayedAction = function(callback, options) {
|
3
3
|
// !todo: paste John Resig's code
|
4
|
-
|
4
|
+
|
5
5
|
options = options || {};
|
6
6
|
var self = this,
|
7
7
|
delay = options.delay || 1000,
|
@@ -10,19 +10,19 @@ Lail.DelayedAction = function(callback, options) {
|
|
10
10
|
counter = 0,
|
11
11
|
_params,
|
12
12
|
_interval;
|
13
|
-
|
13
|
+
|
14
14
|
this.trigger = function(params) {
|
15
15
|
_params = params;
|
16
16
|
restartCountdown();
|
17
17
|
}
|
18
|
-
|
18
|
+
|
19
19
|
function restartCountdown() {
|
20
20
|
counter = steps;
|
21
21
|
if(!_interval) {
|
22
22
|
_interval = setInterval(countdown, intervalPeriod);
|
23
23
|
}
|
24
24
|
}
|
25
|
-
|
25
|
+
|
26
26
|
function countdown() {
|
27
27
|
if(counter > 0) {
|
28
28
|
counter = counter - 1;
|
@@ -31,14 +31,14 @@ Lail.DelayedAction = function(callback, options) {
|
|
31
31
|
fireCallback();
|
32
32
|
}
|
33
33
|
}
|
34
|
-
|
34
|
+
|
35
35
|
function stopCountdown() {
|
36
36
|
if(_interval) {
|
37
37
|
clearInterval(_interval);
|
38
38
|
_interval = null;
|
39
39
|
}
|
40
40
|
}
|
41
|
-
|
41
|
+
|
42
42
|
function fireCallback() {
|
43
43
|
try {
|
44
44
|
callback(_params);
|
@@ -46,4 +46,4 @@ Lail.DelayedAction = function(callback, options) {
|
|
46
46
|
App.debug(e);
|
47
47
|
}
|
48
48
|
}
|
49
|
-
}
|
49
|
+
}
|
@@ -25,33 +25,33 @@ require._core = {
|
|
25
25
|
require.resolve = (function () {
|
26
26
|
return function (x, cwd) {
|
27
27
|
if (!cwd) cwd = '/';
|
28
|
-
|
28
|
+
|
29
29
|
if (require._core[x]) return x;
|
30
30
|
var path = require.modules.path();
|
31
31
|
var y = cwd || '.';
|
32
|
-
|
32
|
+
|
33
33
|
if (x.match(/^(?:\.\.?\/|\/)/)) {
|
34
34
|
var m = loadAsFileSync(path.resolve(y, x))
|
35
35
|
|| loadAsDirectorySync(path.resolve(y, x));
|
36
36
|
if (m) return m;
|
37
37
|
}
|
38
|
-
|
38
|
+
|
39
39
|
var n = loadNodeModulesSync(x, y);
|
40
40
|
if (n) return n;
|
41
|
-
|
41
|
+
|
42
42
|
throw new Error("Cannot find module '" + x + "'");
|
43
|
-
|
43
|
+
|
44
44
|
function loadAsFileSync (x) {
|
45
45
|
if (require.modules[x]) {
|
46
46
|
return x;
|
47
47
|
}
|
48
|
-
|
48
|
+
|
49
49
|
for (var i = 0; i < require.extensions.length; i++) {
|
50
50
|
var ext = require.extensions[i];
|
51
51
|
if (require.modules[x + ext]) return x + ext;
|
52
52
|
}
|
53
53
|
}
|
54
|
-
|
54
|
+
|
55
55
|
function loadAsDirectorySync (x) {
|
56
56
|
x = x.replace(/\/+$/, '');
|
57
57
|
var pkgfile = x + '/package.json';
|
@@ -71,10 +71,10 @@ require.resolve = (function () {
|
|
71
71
|
if (m) return m;
|
72
72
|
}
|
73
73
|
}
|
74
|
-
|
74
|
+
|
75
75
|
return loadAsFileSync(x + '/index');
|
76
76
|
}
|
77
|
-
|
77
|
+
|
78
78
|
function loadNodeModulesSync (x, start) {
|
79
79
|
var dirs = nodeModulesPathsSync(start);
|
80
80
|
for (var i = 0; i < dirs.length; i++) {
|
@@ -84,23 +84,23 @@ require.resolve = (function () {
|
|
84
84
|
var n = loadAsDirectorySync(dir + '/' + x);
|
85
85
|
if (n) return n;
|
86
86
|
}
|
87
|
-
|
87
|
+
|
88
88
|
var m = loadAsFileSync(x);
|
89
89
|
if (m) return m;
|
90
90
|
}
|
91
|
-
|
91
|
+
|
92
92
|
function nodeModulesPathsSync (start) {
|
93
93
|
var parts;
|
94
94
|
if (start === '/') parts = [ '' ];
|
95
95
|
else parts = path.normalize(start).split('/');
|
96
|
-
|
96
|
+
|
97
97
|
var dirs = [];
|
98
98
|
for (var i = parts.length - 1; i >= 0; i--) {
|
99
99
|
if (parts[i] === 'node_modules') continue;
|
100
100
|
var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
|
101
101
|
dirs.push(dir);
|
102
102
|
}
|
103
|
-
|
103
|
+
|
104
104
|
return dirs;
|
105
105
|
}
|
106
106
|
};
|
@@ -116,9 +116,9 @@ require.alias = function (from, to) {
|
|
116
116
|
res = require.resolve(from, '/');
|
117
117
|
}
|
118
118
|
var basedir = path.dirname(res);
|
119
|
-
|
119
|
+
|
120
120
|
var keys = Object_keys(require.modules);
|
121
|
-
|
121
|
+
|
122
122
|
for (var i = 0; i < keys.length; i++) {
|
123
123
|
var key = keys[i];
|
124
124
|
if (key.slice(0, basedir.length + 1) === basedir + '/') {
|
@@ -136,7 +136,7 @@ require.define = function (filename, fn) {
|
|
136
136
|
? ''
|
137
137
|
: require.modules.path().dirname(filename)
|
138
138
|
;
|
139
|
-
|
139
|
+
|
140
140
|
var require_ = function (file) {
|
141
141
|
return require(file, dirname)
|
142
142
|
};
|
@@ -146,7 +146,7 @@ require.define = function (filename, fn) {
|
|
146
146
|
require_.modules = require.modules;
|
147
147
|
require_.define = require.define;
|
148
148
|
var module_ = { exports : {} };
|
149
|
-
|
149
|
+
|
150
150
|
require.modules[filename] = function () {
|
151
151
|
require.modules[filename]._cached = module_.exports;
|
152
152
|
fn.call(
|
@@ -274,7 +274,7 @@ path = normalizeArray(filter(path.split('/'), function(p) {
|
|
274
274
|
if (path && trailingSlash) {
|
275
275
|
path += '/';
|
276
276
|
}
|
277
|
-
|
277
|
+
|
278
278
|
return (isAbsolute ? '/' : '') + path;
|
279
279
|
};
|
280
280
|
|
@@ -816,7 +816,7 @@ require.define("/inflect/default_inflections.coffee", function (require, module,
|
|
816
816
|
});
|
817
817
|
|
818
818
|
require.define("/index.coffee", function (require, module, exports, __dirname, __filename) {
|
819
|
-
|
819
|
+
|
820
820
|
module.exports = require("./inflect");
|
821
821
|
|
822
822
|
});
|
@@ -1,10 +1,10 @@
|
|
1
1
|
var Lail; if(!Lail) Lail={};
|
2
2
|
Lail.PaginatedList = function(list, options) {
|
3
3
|
// todo: paste John Resig's code
|
4
|
-
|
4
|
+
|
5
5
|
options = options || {};
|
6
6
|
var self = this;
|
7
|
-
|
7
|
+
|
8
8
|
this.set = [];
|
9
9
|
this.set_length = 0;
|
10
10
|
this.current_page = 1;
|
@@ -14,15 +14,15 @@ Lail.PaginatedList = function(list, options) {
|
|
14
14
|
this.observer = new Observer();
|
15
15
|
this.pagination_container = null;
|
16
16
|
this.during_init = false;
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
|
18
|
+
|
19
|
+
|
20
20
|
this.count = function() {
|
21
21
|
return self.set_length;
|
22
22
|
}
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
|
24
|
+
|
25
|
+
|
26
26
|
this.init = function(list, initialPage, options) {
|
27
27
|
if((options || {}).page_size) {
|
28
28
|
self.page_size = options.page_size;
|
@@ -38,98 +38,98 @@ Lail.PaginatedList = function(list, options) {
|
|
38
38
|
self.gotoPage(initialPage || 1);
|
39
39
|
self.during_init = false;
|
40
40
|
}
|
41
|
-
|
41
|
+
|
42
42
|
this.gotoPage = function(page_number) {
|
43
43
|
page_number = +page_number; // needs to be an integer
|
44
44
|
if(page_number < 1) page_number = 1;
|
45
45
|
if(page_number > self.page_count) page_number = self.page_count;
|
46
46
|
if(page_number != self.current_page) __setCurrentPage(page_number);
|
47
47
|
}
|
48
|
-
|
48
|
+
|
49
49
|
function __setCurrentPage(page_number) {
|
50
50
|
self.current_page = page_number;
|
51
51
|
self.current_set = self.set.slice(self.firstItemIndex(), self.lastItemIndex());
|
52
52
|
renderPagination();
|
53
53
|
notifyOfPageChange();
|
54
54
|
}
|
55
|
-
|
55
|
+
|
56
56
|
this.firstItemIndex = function() {
|
57
57
|
return (self.current_page - 1) * self.page_size || 0;
|
58
58
|
}
|
59
|
-
|
59
|
+
|
60
60
|
this.lastItemIndex = function() {
|
61
61
|
var end = self.current_page * self.page_size;
|
62
62
|
return (end > self.set_length) ? self.set_length : end;
|
63
63
|
}
|
64
|
-
|
64
|
+
|
65
65
|
this.getCurrentPage = function() {
|
66
66
|
return self.current_page;
|
67
67
|
}
|
68
|
-
|
68
|
+
|
69
69
|
this.getCurrentSet = function() {
|
70
70
|
return self.current_set;
|
71
71
|
}
|
72
|
-
|
72
|
+
|
73
73
|
this.getEntireSet = function() {
|
74
74
|
return self.set;
|
75
75
|
}
|
76
|
-
|
76
|
+
|
77
77
|
function renderPagination() {
|
78
78
|
if(self.pagination_container) {
|
79
79
|
self.pagination_container.html(self.renderPagination());
|
80
80
|
}
|
81
81
|
}
|
82
|
-
|
82
|
+
|
83
83
|
function notifyOfPageChange() {
|
84
84
|
self.observer.fire('changed', {onInit: self.during_init});
|
85
85
|
}
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
|
87
|
+
|
88
|
+
|
89
89
|
this.onPageChange = function(callback) {
|
90
90
|
self.observer.observe('changed', callback);
|
91
91
|
}
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
|
93
|
+
|
94
|
+
|
95
95
|
this.gotoNextPage = function() {
|
96
|
-
if(self.isLastPage()) {
|
96
|
+
if(self.isLastPage()) {
|
97
97
|
return false;
|
98
98
|
} else {
|
99
99
|
self.gotoPage(self.current_page + 1);
|
100
100
|
return true;
|
101
101
|
}
|
102
102
|
}
|
103
|
-
|
103
|
+
|
104
104
|
this.getNextPageNumber = function() {
|
105
105
|
return self.isLastPage() ? self.current_page : (self.current_page + 1);
|
106
106
|
}
|
107
|
-
|
107
|
+
|
108
108
|
this.isLastPage = function() {
|
109
109
|
return (self.current_page == self.page_count);
|
110
110
|
}
|
111
|
-
|
112
|
-
|
113
|
-
|
111
|
+
|
112
|
+
|
113
|
+
|
114
114
|
this.gotoPreviousPage = function() {
|
115
|
-
if(self.isFirstPage()) {
|
115
|
+
if(self.isFirstPage()) {
|
116
116
|
return false;
|
117
117
|
} else {
|
118
118
|
self.gotoPage(self.current_page - 1);
|
119
119
|
return true;
|
120
120
|
}
|
121
121
|
}
|
122
|
-
|
122
|
+
|
123
123
|
this.getPreviousPageNumber = function() {
|
124
124
|
return self.isFirstPage() ? self.current_page : (self.current_page - 1);
|
125
125
|
}
|
126
|
-
|
126
|
+
|
127
127
|
this.isFirstPage = function() {
|
128
128
|
return (self.current_page == 1);
|
129
129
|
}
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
|
131
|
+
|
132
|
+
|
133
133
|
// !nb: uses jQuery!!!
|
134
134
|
this.renderPaginationIn = function(selector) {
|
135
135
|
self.pagination_container = jQuery(selector);
|
@@ -147,7 +147,7 @@ Lail.PaginatedList = function(list, options) {
|
|
147
147
|
return false;
|
148
148
|
});
|
149
149
|
}
|
150
|
-
|
150
|
+
|
151
151
|
// !todo: use Handlebars
|
152
152
|
this.renderPagination = function() {
|
153
153
|
var html = '',
|
@@ -155,14 +155,14 @@ Lail.PaginatedList = function(list, options) {
|
|
155
155
|
count = self.page_count,
|
156
156
|
min = 1,
|
157
157
|
max = count;
|
158
|
-
|
158
|
+
|
159
159
|
if(this.always_show || count > 1) {
|
160
160
|
if(self.isFirstPage()) {
|
161
161
|
html += '<span class="prev_page disabled">« Previous</span> ';
|
162
162
|
} else {
|
163
163
|
html += '<a class="prev_page" href="#" rel="previous">« Previous</a> ';
|
164
164
|
}
|
165
|
-
|
165
|
+
|
166
166
|
// list no more than 7 page numbers
|
167
167
|
if(self.page_count > 7) {
|
168
168
|
min = current - 3;
|
@@ -178,27 +178,27 @@ Lail.PaginatedList = function(list, options) {
|
|
178
178
|
html += ' <a class="goto_page" href="#" id="page_' + i + '">' + i + '</a> ';
|
179
179
|
}
|
180
180
|
}
|
181
|
-
|
181
|
+
|
182
182
|
if(self.isLastPage()) {
|
183
183
|
html += ' <span class="next_page disabled">Next »</span>';
|
184
184
|
} else {
|
185
185
|
html += ' <a class="next_page" href="#" rel="next">Next »</a>';
|
186
186
|
}
|
187
187
|
}
|
188
|
-
|
188
|
+
|
189
189
|
return html;
|
190
190
|
}
|
191
|
-
|
191
|
+
|
192
192
|
// !todo: use handlebars
|
193
193
|
this.renderExtendedPagination = function() {
|
194
194
|
var html = 'Listing <strong>';
|
195
|
-
if(self.page_count > 1) {
|
195
|
+
if(self.page_count > 1) {
|
196
196
|
html += (self.firstItemIndex()+1) + '–' + self.lastItemIndex() + '</strong> of <strong>';
|
197
197
|
}
|
198
198
|
return html + self.count() + '</strong>';
|
199
199
|
}
|
200
|
-
|
201
|
-
|
202
|
-
|
200
|
+
|
201
|
+
|
202
|
+
|
203
203
|
this.init(list || []);
|
204
|
-
}
|
204
|
+
}
|
@@ -1,50 +1,55 @@
|
|
1
1
|
class window.Neat.ModelEditor extends Backbone.View
|
2
2
|
tagName: 'li'
|
3
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
|
-
|
11
|
+
|
12
12
|
@model.bind 'change', @render, @
|
13
|
-
|
13
|
+
|
14
14
|
# Renders the 'show' template normally,
|
15
15
|
# renders 'edit' when in edit mode.
|
16
16
|
@showTemplate = Neat.template["#{@viewPath}/show"]
|
17
17
|
@editTemplate = Neat.template["#{@viewPath}/edit"]
|
18
|
-
|
18
|
+
|
19
19
|
# Wire up events.
|
20
20
|
# Don't use Backbone's events hash because if subclasses
|
21
21
|
# use that more familiar syntax, they'll blow away events
|
22
22
|
# defined in this class.
|
23
23
|
@$el.delegate('.save-button', 'click', _.bind(@save, @))
|
24
|
-
@$el.delegate('.delete-button', 'click', _.bind(@
|
24
|
+
@$el.delegate('.delete-button', 'click', _.bind(@destroy, @))
|
25
25
|
@$el.delegate('.cancel-button', 'click', _.bind(@cancelEdit, @))
|
26
|
-
|
26
|
+
|
27
27
|
# Begin editing when this resource is clicked
|
28
28
|
# unless the user clicked a link or button.
|
29
29
|
@$el.click (e)=>
|
30
30
|
@edit() if @canEdit() and !$(e.target).isIn('input, button, a, label')
|
31
|
-
|
31
|
+
|
32
32
|
render: ->
|
33
33
|
json = _.extend(@model.toJSON(), {options: @templateOptions})
|
34
34
|
@$el.html @template()(json)
|
35
35
|
@$el.attr('id', "#{@resource}_#{@model.get('id')}") # e.g. "calendar_5"
|
36
|
-
|
36
|
+
|
37
37
|
@afterRender()
|
38
38
|
@
|
39
|
-
|
39
|
+
|
40
40
|
afterRender: ->
|
41
41
|
@
|
42
|
-
|
42
|
+
|
43
43
|
inEdit: -> @$el.hasClass('editor')
|
44
44
|
canEdit: -> @$el.hasClass('neat-editable') and !@inEdit()
|
45
45
|
template: -> if @inEdit() then @editTemplate else @showTemplate
|
46
|
-
|
46
|
+
|
47
47
|
cancelEdit: (e)->
|
48
|
+
e?.preventDefault()
|
49
|
+
e?.stopImmediatePropagation()
|
50
|
+
@endEdit()
|
51
|
+
|
52
|
+
endEdit: (e)->
|
48
53
|
e?.preventDefault()
|
49
54
|
e?.stopImmediatePropagation()
|
50
55
|
if @inEdit()
|
@@ -53,7 +58,7 @@ class window.Neat.ModelEditor extends Backbone.View
|
|
53
58
|
@render()
|
54
59
|
@trigger('edit:end')
|
55
60
|
@
|
56
|
-
|
61
|
+
|
57
62
|
edit: ->
|
58
63
|
unless @inEdit()
|
59
64
|
@$el.addClass('editor').removeClass('neat-editable hovered')
|
@@ -61,21 +66,21 @@ class window.Neat.ModelEditor extends Backbone.View
|
|
61
66
|
@render()
|
62
67
|
@autofocus()
|
63
68
|
@
|
64
|
-
|
69
|
+
|
65
70
|
autofocus: ->
|
66
71
|
@$el.find(':input:visible').first().focus()
|
67
|
-
|
72
|
+
|
68
73
|
save: (e)->
|
69
74
|
e?.preventDefault()
|
70
75
|
newAttributes = @attributesFromForm(@$el)
|
71
76
|
@debug 'saving: ', newAttributes
|
72
77
|
attributes = @model.changedAttributes(newAttributes)
|
73
|
-
|
78
|
+
|
74
79
|
return unless @okToSave(attributes)
|
75
|
-
|
80
|
+
|
76
81
|
if attributes
|
77
82
|
previousAttributes = @model.toJSON()
|
78
|
-
|
83
|
+
|
79
84
|
@model.save attributes,
|
80
85
|
wait: true
|
81
86
|
success: =>
|
@@ -83,12 +88,12 @@ class window.Neat.ModelEditor extends Backbone.View
|
|
83
88
|
@debug " . #{attribute} changed from ", previousAttributes[attribute], " to ", @model.get(attribute)
|
84
89
|
@onSaveSuccess()
|
85
90
|
error: _.bind(@onSaveError, @)
|
86
|
-
|
87
|
-
@
|
88
|
-
|
91
|
+
|
92
|
+
@endEdit()
|
93
|
+
|
89
94
|
okToSave: (attributes)->
|
90
95
|
true
|
91
|
-
|
96
|
+
|
92
97
|
attributesFromForm: ($el)->
|
93
98
|
attrs = {}
|
94
99
|
$el.find('input, select, textarea').each ->
|
@@ -110,33 +115,33 @@ class window.Neat.ModelEditor extends Backbone.View
|
|
110
115
|
else
|
111
116
|
attrs[name] = value
|
112
117
|
attrs
|
113
|
-
|
114
|
-
|
118
|
+
|
119
|
+
destroy: (e)->
|
115
120
|
e?.preventDefault()
|
116
|
-
@
|
121
|
+
@confirmDestroy @resource, =>
|
117
122
|
@$el.removeClass('neat-editable').addClass('deleted')
|
118
|
-
|
123
|
+
|
119
124
|
@model.destroy
|
120
125
|
wait: true
|
121
|
-
success: => @
|
126
|
+
success: => @onDestroySuccess
|
122
127
|
error: _.bind(@onSaveError, @)
|
123
|
-
@
|
124
|
-
|
125
|
-
|
128
|
+
@endEdit()
|
129
|
+
|
130
|
+
confirmDestroy: (resource, callback)->
|
126
131
|
if confirm("Delete this #{resource}?")
|
127
132
|
callback()
|
128
|
-
|
129
|
-
|
130
|
-
|
133
|
+
|
134
|
+
|
135
|
+
|
131
136
|
onSaveSuccess: ->
|
132
137
|
onSaveError: ->
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
+
onDestroySuccess: ->
|
139
|
+
onDestroyError: ->
|
140
|
+
|
141
|
+
|
142
|
+
|
138
143
|
debug: (o...)->
|
139
144
|
@log(o...) if Neat.debug
|
140
|
-
|
145
|
+
|
141
146
|
log: (o...)->
|
142
147
|
Neat.logger.log "[#{@resource}] ", o...
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neat-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Bob Lail
|
@@ -9,20 +10,22 @@ authors:
|
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2016-02-08 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: rake
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
17
19
|
requirements:
|
18
|
-
- -
|
20
|
+
- - ! '>='
|
19
21
|
- !ruby/object:Gem::Version
|
20
22
|
version: '0'
|
21
23
|
type: :development
|
22
24
|
prerelease: false
|
23
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
24
27
|
requirements:
|
25
|
-
- -
|
28
|
+
- - ! '>='
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: '0'
|
28
31
|
description: It allows editing collections and models inline
|
@@ -33,7 +36,7 @@ executables: []
|
|
33
36
|
extensions: []
|
34
37
|
extra_rdoc_files: []
|
35
38
|
files:
|
36
|
-
-
|
39
|
+
- .gitignore
|
37
40
|
- Gemfile
|
38
41
|
- LICENSE.txt
|
39
42
|
- README.md
|
@@ -52,25 +55,32 @@ files:
|
|
52
55
|
- vendor/assets/javascripts/neat/model_editor.coffee
|
53
56
|
homepage: ''
|
54
57
|
licenses: []
|
55
|
-
metadata: {}
|
56
58
|
post_install_message:
|
57
59
|
rdoc_options: []
|
58
60
|
require_paths:
|
59
61
|
- lib
|
60
62
|
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
61
64
|
requirements:
|
62
|
-
- -
|
65
|
+
- - ! '>='
|
63
66
|
- !ruby/object:Gem::Version
|
64
67
|
version: '0'
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
hash: 2435929593431474536
|
65
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
66
73
|
requirements:
|
67
|
-
- -
|
74
|
+
- - ! '>='
|
68
75
|
- !ruby/object:Gem::Version
|
69
76
|
version: '0'
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
hash: 2435929593431474536
|
70
80
|
requirements: []
|
71
81
|
rubyforge_project:
|
72
|
-
rubygems_version:
|
82
|
+
rubygems_version: 1.8.23.2
|
73
83
|
signing_key:
|
74
|
-
specification_version:
|
84
|
+
specification_version: 3
|
75
85
|
summary: It's like FreightTrain for Backbone. That's pretty neat!
|
76
86
|
test_files: []
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 695ee4ffacf2d5ff9962b563842796a8e19f1133
|
4
|
-
data.tar.gz: 5d86e89f8d9fa6bd3d8bcf4b890bac853047b568
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 26244d4b5882ee55c5413495fe5897dbb93473f4f1135bd3610a0059e368e6cc3f38a41b7037398e3bfe0608670bc038ae5a1e0ebf18e39eebaf9e2a5674cb5f
|
7
|
-
data.tar.gz: 110fbfca1f62d9101e10f605ac46663a5dbff5ebb7428d765b529d4ba8cebcd9a6baf5299fd40d2f83f9b3acd7aa95d71424216c72637e5317d44af172a0fa3f
|