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