caboose-cms 0.5.5 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OThhZmNiZGRmMDU2M2ZjN2ZmOGQyNTljYjk2NGVhZTcwNGQzYzU2MQ==
4
+ YjM5NDdjM2NhOTc3MzhjZDk1NDI3NTYwZWRmNDAxZGEzNGUwYzJkZQ==
5
5
  data.tar.gz: !binary |-
6
- NDdjNGEyYWZjMzk1MjI3ZTc2MWFlMmQ2OTc5NmY4YjkzYmEzMzk1OA==
6
+ NDUyMTQxN2VkYTYyMGQwYTJhM2E5MWUwZTRmNmM3ZjQ2MDQ0MDk2Ng==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NDU3NzE3ZDZlZjJhNWE5Y2FkNjVkNjI4NTUyMjg4YmJkMmMwYjk2ZjIwMmU2
10
- NWUxODA0ODRkY2U1N2U4YWI1YWU3NzU4MjRlYWVkODFiZDZlMjZmZmQ0ZDc3
11
- MTgyYWRkNTE3ZWRjYmNiNGRhZTZhZDEwZTAwMzgwYmM0ZWMxNDI=
9
+ ZjljMzZmMDZlYzEwMjJhYWUzZWY3ZmI2NDVmZWQxYTI2MjkzMWNmYmI2OWE0
10
+ YmY2ZmVlMjg5YzIzNDg1MmNlZjZjMWRmYzUyNjc5ZGZmOWI2NjRhMzYwNjNl
11
+ ZjdkYjZhMjAyZDBjNGY0M2NjOTE1YWExOWY1OTNiZGE0ZDI5MjE=
12
12
  data.tar.gz: !binary |-
13
- OWNlOTNiNDBkNDhiZmFkYjdhZDExZWU3MTMzNjY2NjA2NWU1NzBmOTc1M2Zl
14
- YWIyOTI2M2NiNDkyMDc1MmI1MTljMmEyMjk0NDg1YjVjYzM5OWJjYzExMGM1
15
- OTgzZDg4OWI0Y2RjYzI1OWM3NTllNDdhMzI1MmQ3MzMxYTFhZjg=
13
+ NDllYmUzMDlmZWIxNjc5NGQ2OTgwNzI1YjFjNzk3ZmVhZTkyZDJlYmM5Yjc3
14
+ ZmU0YTc0OGQxMTgwNTM0YTU4NDNiZWFhOWQwM2UwZjlkNjcxOTUyYjAwMjM1
15
+ NGJiNDhhNjY5ZWRjNGM5OWRhMTY3ODc0YjEyM2FmZmI4YWY1MGY=
@@ -16,6 +16,7 @@ IndexTable.prototype = {
16
16
 
17
17
  // Where to get model json data
18
18
  refresh_url: false,
19
+ refresh_single_url: false,
19
20
 
20
21
  // Where to send bulk updates
21
22
  bulk_update_url: false,
@@ -71,8 +72,8 @@ IndexTable.prototype = {
71
72
  //============================================================================
72
73
 
73
74
  models: [],
74
- model_ids: [],
75
- quick_edit_field: false, // The field currently being edited
75
+ model_ids: [],
76
+ quick_edit_model_id: false, // The id of the model currently being edited
76
77
  refresh_count: 0,
77
78
  pager: {
78
79
  options: { page: 1 },
@@ -84,18 +85,39 @@ IndexTable.prototype = {
84
85
  this[thing] = params[thing];
85
86
 
86
87
  var that = this;
87
- if (!this.refresh_url ) this.refresh_url = this.base_url + '/json';
88
- if (!this.bulk_update_url ) this.bulk_update_url = this.base_url + '/bulk';
89
- if (!this.bulk_delete_url ) this.bulk_delete_url = this.base_url + '/bulk';
90
- if (!this.add_url ) this.add_url = this.base_url;
91
- if (!this.update_url ) this.update_url = function(model_id) { return this.base_url + '/' + model_id; };
92
- if (!this.duplicate_url ) this.duplicate_url = function(model_id) { return this.base_url + '/' + model_id + '/duplicate'; };
93
- if (!this.row_click_handler ) this.row_click_handler = function(model_id) { window.location = this.base_url + '/' + model_id; };
88
+ if (!this.refresh_url ) this.refresh_url = this.base_url + '/json';
89
+ if (!this.bulk_update_url ) this.bulk_update_url = this.base_url + '/bulk';
90
+ if (!this.bulk_delete_url ) this.bulk_delete_url = this.base_url + '/bulk';
91
+ if (!this.add_url ) this.add_url = this.base_url;
92
+ if (!this.update_url ) this.update_url = function(model_id) { return that.base_url + '/' + model_id; };
93
+ if (!this.duplicate_url ) this.duplicate_url = function(model_id) { return that.base_url + '/' + model_id + '/duplicate'; };
94
+ if (!this.refresh_single_url) this.refresh_single_url = function(model_id) { return that.base_url + '/' + model_id + '/json'; };
95
+ if (!this.row_click_handler ) this.row_click_handler = function(model_id, e) {
96
+ if (that.quick_edit_model_id == model_id)
97
+ {
98
+ if ($(e.target).prop('tagName') == 'TD')
99
+ that.quick_edit_model_id = false;
100
+ else
101
+ return;
102
+ }
103
+ else
104
+ that.quick_edit_model_id = model_id;
105
+ that.print();
106
+ };
107
+ this.init_fields();
94
108
 
95
109
  $(window).on('hashchange', function() { that.refresh(); });
96
110
  this.refresh();
97
111
  },
98
112
 
113
+ init_fields: function()
114
+ {
115
+ var that = this;
116
+ $.each(this.fields, function(i, f) {
117
+ if (f.editable == null) f.editable = true;
118
+ });
119
+ },
120
+
99
121
  parse_querystring: function()
100
122
  {
101
123
  var b = {};
@@ -179,6 +201,25 @@ IndexTable.prototype = {
179
201
  });
180
202
  },
181
203
 
204
+ refresh_single: function(model_id)
205
+ {
206
+ var that = this;
207
+ $.ajax({
208
+ url: that.refresh_single_url(model_id),
209
+ type: 'get',
210
+ success: function(resp) {
211
+ for (var i=0; i<that.models.length; i++)
212
+ {
213
+ if (that.models[i].id == model_id)
214
+ {
215
+ that.models[i] = resp;
216
+ break;
217
+ }
218
+ }
219
+ }
220
+ });
221
+ },
222
+
182
223
  print: function()
183
224
  {
184
225
  var that = this;
@@ -226,28 +267,26 @@ IndexTable.prototype = {
226
267
  .append(controls);
227
268
  $('#' + that.container + '_columns').hide();
228
269
  }
229
-
230
- if (that.quick_edit_field)
231
- {
232
- $.each(that.models, function(i, m) {
233
- $.each(that.fields, function(j, field) {
234
- if (field.show && field.name == that.quick_edit_field)
235
- {
236
- var attrib = $.extend({}, field);
237
- attrib['value'] = field.value(m);
238
- attrib['fixed_placeholder'] = false;
239
- //if (field.text)
240
- // attrib['text'] = field.text(m);
241
- new ModelBinder({
242
- name: 'Model',
243
- id: m.id,
244
- update_url: that.update_url(m.id),
245
- authenticity_token: that.form_authenticity_token,
246
- attributes: [attrib]
247
- });
248
- }
249
- });
250
- });
270
+
271
+ if (that.quick_edit_model_id)
272
+ {
273
+ var m = that.model_for_id(that.quick_edit_model_id);
274
+ $.each(that.fields, function(j, field) {
275
+ if (field.show && field.editable)
276
+ {
277
+ var attrib = $.extend({}, field);
278
+ attrib['value'] = field.value(m);
279
+ attrib['fixed_placeholder'] = false;
280
+ attrib['after_update'] = function() { that.refresh_single(m.id); };
281
+ new ModelBinder({
282
+ name: 'Model',
283
+ id: m.id,
284
+ update_url: that.update_url(m.id),
285
+ authenticity_token: that.form_authenticity_token,
286
+ attributes: [attrib]
287
+ });
288
+ }
289
+ });
251
290
  }
252
291
  },
253
292
 
@@ -262,39 +301,27 @@ IndexTable.prototype = {
262
301
  $.each(this.fields, function(i, field) {
263
302
  if (field.show)
264
303
  {
265
- var s = field.sort ? field.sort : field.name;
266
- console.log("field.name = " + field.name);
267
- console.log("that.pager.options.sort = " + that.pager.options.sort);
268
- console.log("that.pager.options.desc = " + that.pager.options.desc);
269
- console.log("------------------------------");
304
+ var s = field.sort ? field.sort : field.name;
270
305
  var arrow = that.pager.options.sort == s ? (parseInt(that.pager.options.desc) == 1 ? ' &uarr;' : ' &darr;') : '';
271
306
  var link = that.pager_hash({
272
307
  sort: s,
273
308
  desc: (that.pager.options.sort == s ? (parseInt(that.pager.options.desc) == 1 ? '0' : '1') : '0')
274
309
  });
275
310
 
276
- var input = $('<input/>').attr('type', 'checkbox').attr('id', 'quick_edit_' + field.name).val(field.name)
277
- .change(function() {
278
- that.quick_edit_field = $(this).prop('checked') ? $(this).val() : false;
279
- that.refresh();
280
- });
281
- if (field.name == that.quick_edit_field)
282
- input.prop('checked', 'true');
311
+ //var input = $('<input/>').attr('type', 'checkbox').attr('id', 'quick_edit_' + field.name).val(field.name)
312
+ // .change(function() {
313
+ // that.quick_edit_field = $(this).prop('checked') ? $(this).val() : false;
314
+ // that.refresh();
315
+ // });
316
+ //if (field.name == that.quick_edit_field)
317
+ // input.prop('checked', 'true');
283
318
  tr.append($('<th/>')
284
- .append(input).append('<br/>')
319
+ //.append(input).append('<br/>')
285
320
  .append($('<a/>')
286
321
  .attr('id', 'quick_edit_' + field.name).val(field.name)
287
322
  .attr('href', link)
288
323
  .data('sort', s)
289
- .html(field.nice_name + arrow)
290
- //.mousedown(function(e) {
291
- // if (e.which == 3) // right click
292
- // {
293
- // var field_name = $(this).attr('id').replace('quick_edit_', '');
294
- // that.quick_edit_field = that.quick_edit_field == field_name ? false : field_name;
295
- // that.refresh();
296
- // }
297
- //})
324
+ .html(field.nice_name + arrow)
298
325
  )
299
326
  );
300
327
  }
@@ -328,21 +355,17 @@ IndexTable.prototype = {
328
355
  if (that.model_ids.indexOf(m.id) > -1)
329
356
  checkbox.prop('checked', 'true');
330
357
  tr.append($('<td/>').append(checkbox));
331
- }
332
-
333
- if (!that.quick_edit_field)
334
- {
335
- tr.click(function(e) {
336
- var model_id = $(this).attr('id').replace('model_row_', '');
337
- that.row_click_handler(model_id);
338
- });
339
- }
340
-
358
+ }
359
+ tr.click(function(e) {
360
+ var model_id = $(this).attr('id').replace('model_row_', '');
361
+ that.row_click_handler(model_id, e);
362
+ });
363
+
341
364
  $.each(that.fields, function(j, field) {
342
365
  if (field.show)
343
366
  {
344
367
  var td = $('<td/>');
345
- if (that.quick_edit_field == field.name)
368
+ if (field.editable && that.quick_edit_model_id == m.id)
346
369
  td.append($('<div/>').attr('id', 'model_' + m.id + '_' + field.name));
347
370
  else
348
371
  td.html(field.text ? field.text(m) : field.value(m));
@@ -0,0 +1,709 @@
1
+
2
+ var IndexTable = function(params) { this.init(params); }
3
+ IndexTable.prototype = {
4
+
5
+ //============================================================================
6
+ // Required parameters
7
+ //============================================================================
8
+
9
+ form_authenticity_token: false,
10
+
11
+ // Container for the table
12
+ container: 'models',
13
+
14
+ // Base URL used for default refresh/update/delete/bulk URLs
15
+ base_url: false,
16
+
17
+ // Where to get model json data
18
+ refresh_url: false,
19
+ refresh_single_url: false,
20
+
21
+ // Where to send bulk updates
22
+ bulk_update_url: false,
23
+
24
+ // Where to send bulk deletes
25
+ bulk_delete_url: false,
26
+
27
+ // Where to send normal updates
28
+ // Example: function(model_id) { return '/admin/models/' + model_id; }
29
+ update_url: false,
30
+
31
+ // Where to send duplicate calls
32
+ // Example: function(model_id) { return '/admin/models/' + model_id + '/duplicate' },
33
+ duplicate_url: false,
34
+
35
+ // Where to post new models
36
+ add_url: false,
37
+
38
+ // What to do when a row is clicked
39
+ // Example: function (model_id) { return '/admin/models/' + model_id; }
40
+ row_click_handler: false,
41
+
42
+ // Array of fields you want to show in the table (given as model binder attributes with additional text and value functions)
43
+ // [{
44
+ // show: true,
45
+ // bulk_edit: true,
46
+ // name: 'title',
47
+ // nice_name: 'Title',
48
+ // type: 'text',
49
+ // text: function(obj) { return obj.title; },
50
+ // value: function(obj) { return obj.id; },
51
+ // options_url: '/admin/dogs/collar-options'
52
+ // fixed_placeholder: false,
53
+ // width: 200,
54
+ // }]
55
+ fields: [],
56
+
57
+ // The post/get in the original request
58
+ post_get: false,
59
+
60
+ allow_bulk_edit: true,
61
+ allow_bulk_delete: true,
62
+ allow_duplicate: true,
63
+
64
+ no_models_text: "There are no models right now.",
65
+ new_model_text: 'New',
66
+ new_model_fields: [
67
+ { name: 'name', nice_name: 'Name', type: 'text', width: 400 }
68
+ ],
69
+
70
+ //============================================================================
71
+ // End of required parameters
72
+ //============================================================================
73
+
74
+ models: [],
75
+ model_ids: [],
76
+ quick_edit_field: false, // The field currently being edited
77
+ quick_edit_model_id: false, // The id of the model currently being edited
78
+ refresh_count: 0,
79
+ pager: {
80
+ options: { page: 1 },
81
+ params: {}
82
+ },
83
+
84
+ init: function(params) {
85
+ for (var thing in params)
86
+ this[thing] = params[thing];
87
+
88
+ var that = this;
89
+ if (!this.refresh_url ) this.refresh_url = this.base_url + '/json';
90
+ if (!this.bulk_update_url ) this.bulk_update_url = this.base_url + '/bulk';
91
+ if (!this.bulk_delete_url ) this.bulk_delete_url = this.base_url + '/bulk';
92
+ if (!this.add_url ) this.add_url = this.base_url;
93
+ if (!this.update_url ) this.update_url = function(model_id) { return that.base_url + '/' + model_id; };
94
+ if (!this.duplicate_url ) this.duplicate_url = function(model_id) { return that.base_url + '/' + model_id + '/duplicate'; };
95
+ if (!this.refresh_single_url) this.refresh_single_url = function(model_id) { return that.base_url + '/' + model_id + '/json'; };
96
+ if (!this.row_click_handler ) this.row_click_handler = function(model_id, e) {
97
+ if (that.quick_edit_model_id == model_id)
98
+ {
99
+ if ($(e.target).prop('tagName') == 'TD')
100
+ that.quick_edit_model_id = false;
101
+ else
102
+ return;
103
+ }
104
+ else
105
+ that.quick_edit_model_id = model_id;
106
+ that.print();
107
+ };
108
+ this.init_fields();
109
+
110
+ $(window).on('hashchange', function() { that.refresh(); });
111
+ this.refresh();
112
+ },
113
+
114
+ init_fields: function()
115
+ {
116
+ var that = this;
117
+ $.each(this.fields, function(i, f) {
118
+ if (f.editable == null) f.editable = true;
119
+ });
120
+ },
121
+
122
+ parse_querystring: function()
123
+ {
124
+ var b = {};
125
+
126
+ // Get the hash values
127
+ var a = window.location.hash;
128
+ if (a.length > 0)
129
+ {
130
+ a = a.substr(1).split('&');
131
+ for (var i=0; i<a.length; ++i)
132
+ {
133
+ var p = a[i].split('=', 2);
134
+ if (p.length == 1) b[p[0]] = "";
135
+ else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
136
+ }
137
+ }
138
+
139
+ // Get the querystring values
140
+ a = window.location.search;
141
+ if (a.length > 0)
142
+ {
143
+ a = a.substr(1).split('&');
144
+ for (var i=0; i<a.length; ++i)
145
+ {
146
+ var p = a[i].split('=', 2);
147
+ if (p.length == 1) b[p[0]] = "";
148
+ else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
149
+ }
150
+ }
151
+
152
+ // Set both hash and querystring values in the pager
153
+ for (var i in b)
154
+ {
155
+ if (i == 'sort' || i == 'desc' || i == 'page')
156
+ this.pager.options[i] = b[i];
157
+ else
158
+ this.pager.params[i] = b[i];
159
+ }
160
+
161
+ // If there's a querystring, then redirect to hash
162
+ //if (window.location.search.length > 0)
163
+ //{
164
+ // //alert('Testing');
165
+ // //window.location = this.pager_url({ base_url: window.location.pathname }).replace('?', '#');
166
+ //}
167
+ },
168
+
169
+ refresh: function()
170
+ {
171
+ this.pager = { options: { page: 1 }, params: {}};
172
+ this.parse_querystring();
173
+
174
+ var that = this;
175
+ var $el = $('#' + this.container + '_columns').length > 0 ? $('#' + this.container + '_table_container') : $('#' + this.container);
176
+ $el.html("<p class='loading'>Refreshing...</p>");
177
+ $.ajax({
178
+ url: that.refresh_url,
179
+ type: 'get',
180
+ data: that.pager_params(),
181
+ success: function(resp) {
182
+ for (var thing in resp['pager'])
183
+ that.pager[thing] = resp['pager'][thing];
184
+ that.models = resp['models'];
185
+ for (var i=0; i<that.models.length; i++)
186
+ {
187
+ var m = that.models[i];
188
+ m.id = parseInt(m.id);
189
+ }
190
+ that.print();
191
+
192
+ // Set the history state
193
+ //var qs = that.pager_querystring();
194
+ //if (that.refresh_count > 0 && qs != window.location.hash)
195
+ //{
196
+ // if(history.pushState) history.pushState(null, null, '#' + qs);
197
+ // else location.hash = '#' + qs;
198
+ //}
199
+ that.refresh_count += 1;
200
+ },
201
+ error: function() { $('#' + this.container).html("<p class='note error'>Error retrieving data.</p>"); }
202
+ });
203
+ },
204
+
205
+ refresh_single: function(model_id)
206
+ {
207
+ var that = this;
208
+ $.ajax({
209
+ url: that.refresh_single_url(model_id),
210
+ type: 'get',
211
+ success: function(resp) {
212
+ for (var i=0; i<that.models.length; i++)
213
+ {
214
+ if (that.models[i].id == model_id)
215
+ {
216
+ that.models[i] = resp;
217
+ break;
218
+ }
219
+ }
220
+ }
221
+ });
222
+ },
223
+
224
+ print: function()
225
+ {
226
+ var that = this;
227
+
228
+ if (that.models == null || that.models.length == 0)
229
+ {
230
+ $('#' + that.container).empty()
231
+ .append($('<p/>').append(that.new_model_link()))
232
+ .append($('<div/>').attr('id', that.container + '_new_form_container'))
233
+ .append($('<p/>').append(that.no_models_text));
234
+ return;
235
+ }
236
+
237
+ var tbody = $('<tbody/>').append(this.table_headers());
238
+ $.each(that.models, function(i, m) {
239
+ tbody.append(that.table_row(m));
240
+ });
241
+ var table = $('<table/>').addClass('data').css('margin-bottom', '10px').append(tbody);
242
+ var pager_div = this.pager_div();
243
+
244
+ if ($('#' + this.container + '_columns').length > 0)
245
+ {
246
+ $('#' + this.container + '_table_container').empty().append(table);
247
+ $('#' + this.container + '_pager').empty().append(pager_div);
248
+ $('#' + this.container + '_new_form_container').empty();
249
+ }
250
+ else
251
+ {
252
+ var columns = this.column_checkboxes();
253
+ var controls = $('<p/>');
254
+ if (this.allow_bulk_edit ) controls.append($('<input/>').attr('type', 'button').attr('id', this.container + '_bulk_edit' ).val('Bulk Edit' ).click(function(e) { that.bulk_edit(); })).append(' ');
255
+ if (this.allow_bulk_delete ) controls.append($('<input/>').attr('type', 'button').attr('id', this.container + '_bulk_delete').val('Bulk Delete').click(function(e) { that.bulk_delete(); })).append(' ');
256
+ if (this.allow_duplicate ) controls.append($('<input/>').attr('type', 'button').attr('id', this.container + '_duplicate' ).val('Duplicate' ).click(function(e) { that.duplicate(); }));
257
+
258
+ $('#' + that.container).empty()
259
+ .append($('<p/>')
260
+ .append(that.new_model_link()).append(' | ')
261
+ .append($('<a/>').attr('href', '#').html('Show/Hide Columns').click(function(e) { e.preventDefault(); $('#' + that.container + '_columns').slideToggle(); }))
262
+ )
263
+ .append($('<div/>').attr('id', that.container + '_new_form_container'))
264
+ .append($('<div/>').attr('id', that.container + '_columns').append(columns))
265
+ .append($('<div/>').attr('id', that.container + '_table_container').append(table))
266
+ .append($('<div/>').attr('id', that.container + '_pager').append(pager_div))
267
+ .append($('<div/>').attr('id', that.container + '_message'))
268
+ .append(controls);
269
+ $('#' + that.container + '_columns').hide();
270
+ }
271
+
272
+ if (that.quick_edit_field)
273
+ {
274
+ $.each(that.models, function(i, m) {
275
+ $.each(that.fields, function(j, field) {
276
+ if (field.show && field.name == that.quick_edit_field)
277
+ {
278
+ var attrib = $.extend({}, field);
279
+ attrib['value'] = field.value(m);
280
+ attrib['fixed_placeholder'] = false;
281
+ //if (field.text)
282
+ // attrib['text'] = field.text(m);
283
+ new ModelBinder({
284
+ name: 'Model',
285
+ id: m.id,
286
+ update_url: that.update_url(m.id),
287
+ authenticity_token: that.form_authenticity_token,
288
+ attributes: [attrib]
289
+ });
290
+ }
291
+ });
292
+ });
293
+ }
294
+ if (that.quick_edit_model_id)
295
+ {
296
+ var m = that.model_for_id(that.quick_edit_model_id);
297
+ $.each(that.fields, function(j, field) {
298
+ if (field.show && field.editable)
299
+ {
300
+ var attrib = $.extend({}, field);
301
+ attrib['value'] = field.value(m);
302
+ attrib['fixed_placeholder'] = false;
303
+ attrib['after_update'] = function() { that.refresh_single(m.id); };
304
+ new ModelBinder({
305
+ name: 'Model',
306
+ id: m.id,
307
+ update_url: that.update_url(m.id),
308
+ authenticity_token: that.form_authenticity_token,
309
+ attributes: [attrib]
310
+ });
311
+ }
312
+ });
313
+ }
314
+ },
315
+
316
+ table_headers: function()
317
+ {
318
+ var that = this;
319
+ var tr = $('<tr/>');
320
+
321
+ if (this.allow_bulk_edit || this.allow_bulk_delete || this.allow_duplicate)
322
+ tr.append($('<th/>').html('&nbsp;'));
323
+
324
+ $.each(this.fields, function(i, field) {
325
+ if (field.show)
326
+ {
327
+ var s = field.sort ? field.sort : field.name;
328
+ var arrow = that.pager.options.sort == s ? (parseInt(that.pager.options.desc) == 1 ? ' &uarr;' : ' &darr;') : '';
329
+ var link = that.pager_hash({
330
+ sort: s,
331
+ desc: (that.pager.options.sort == s ? (parseInt(that.pager.options.desc) == 1 ? '0' : '1') : '0')
332
+ });
333
+
334
+ var input = $('<input/>').attr('type', 'checkbox').attr('id', 'quick_edit_' + field.name).val(field.name)
335
+ .change(function() {
336
+ that.quick_edit_field = $(this).prop('checked') ? $(this).val() : false;
337
+ that.refresh();
338
+ });
339
+ if (field.name == that.quick_edit_field)
340
+ input.prop('checked', 'true');
341
+ tr.append($('<th/>')
342
+ .append(input).append('<br/>')
343
+ .append($('<a/>')
344
+ .attr('id', 'quick_edit_' + field.name).val(field.name)
345
+ .attr('href', link)
346
+ .data('sort', s)
347
+ .html(field.nice_name + arrow)
348
+ )
349
+ );
350
+ }
351
+ });
352
+ return tr;
353
+ },
354
+
355
+ table_row: function(m)
356
+ {
357
+ var that = this;
358
+
359
+ var tr = $('<tr/>').attr('id', 'model_row_' + m.id);
360
+
361
+ if (that.allow_bulk_edit || that.allow_bulk_delete || that.allow_duplicate)
362
+ {
363
+ var checkbox = $('<input/>').attr('type', 'checkbox').attr('id', 'model_' + m.id)
364
+ .click(function(e) {
365
+ e.stopPropagation();
366
+ var model_id = $(this).attr('id').replace('model_', '');
367
+ if (model_id == 'NaN')
368
+ alert("Error: invalid model id.");
369
+ else
370
+ {
371
+ model_id = parseInt(model_id);
372
+ var checked = $(this).prop('checked');
373
+ var i = that.model_ids.indexOf(model_id);
374
+ if (checked && i == -1) that.model_ids.push(model_id);
375
+ if (!checked && i > -1) that.model_ids.splice(i, 1);
376
+ }
377
+ });
378
+ if (that.model_ids.indexOf(m.id) > -1)
379
+ checkbox.prop('checked', 'true');
380
+ tr.append($('<td/>').append(checkbox));
381
+ }
382
+
383
+ if (!that.quick_edit_field)
384
+ {
385
+ tr.click(function(e) {
386
+ var model_id = $(this).attr('id').replace('model_row_', '');
387
+ that.row_click_handler(model_id, e);
388
+ });
389
+ }
390
+
391
+ $.each(that.fields, function(j, field) {
392
+ if (field.show)
393
+ {
394
+ var td = $('<td/>');
395
+ if (field.editable && (that.quick_edit_model_id == m.id || that.quick_edit_field == field.name))
396
+ td.append($('<div/>').attr('id', 'model_' + m.id + '_' + field.name));
397
+ else
398
+ td.html(field.text ? field.text(m) : field.value(m));
399
+ tr.append(td);
400
+ }
401
+ });
402
+ return tr;
403
+ },
404
+
405
+ column_checkboxes: function()
406
+ {
407
+ var that = this;
408
+ var div = $('<div/>').attr('id', that.container + '_columns');
409
+ $.each(this.fields, function(i, field) {
410
+ var input = $('<input/>')
411
+ .attr('type', 'checkbox')
412
+ .attr('id', 'field_' + field.name)
413
+ .click(function(e) {
414
+ var field_name = $(this).attr('id').replace('field_', '');
415
+ var checked = $(this).prop('checked');
416
+ $.each(that.fields, function(j, f) {
417
+ if (f.name == field_name)
418
+ {
419
+ f.show = checked;
420
+ that.print();
421
+ }
422
+ });
423
+ });
424
+ if (field.show)
425
+ input.prop('checked', 'true');
426
+
427
+ div.append($('<div/>').addClass('label_with_checkbox')
428
+ .append(input)
429
+ .append($('<label/>').attr('for', 'field_' + field.name).html(field.nice_name))
430
+ );
431
+ });
432
+ return div;
433
+ },
434
+
435
+ bulk_edit: function()
436
+ {
437
+ var that = this;
438
+ if (this.model_ids.length == 0)
439
+ {
440
+ $('#message').html("<p class='note error'>Please select at least one row.</p>");
441
+ return;
442
+ }
443
+ var div = $('<div/>')
444
+ .append($('<h2/>').html('Bulk Edit Jobs'))
445
+ .append($('<p/>').html('Any change you make the fields below will apply to all the selected rows.'));
446
+ $.each(this.fields, function(i, field) {
447
+ if (field.bulk_edit == true)
448
+ div.append($('<p/>').append($('<div/>').attr('id', 'bulkmodel_1_' + field.name)));
449
+ });
450
+ div.append($('<input/>').attr('type','button').val('Finished').click(function() { $('#message').empty(); }));
451
+ $('#message').empty().append(div);
452
+
453
+ var params = this.model_ids.map(function(model_id) { return 'model_ids[]=' + model_id; }).join('&');
454
+ var attribs = [];
455
+ $.each(this.fields, function(i, field) {
456
+ if (field.bulk_edit == true)
457
+ {
458
+ var attrib = $.extend({}, field);
459
+ attrib['value'] = '';
460
+ attrib['after_update'] = function() { that.refresh(); };
461
+ attrib['width'] = 600;
462
+ attribs.push(attrib);
463
+ }
464
+ });
465
+
466
+ m = new ModelBinder({
467
+ name: 'BulkModel',
468
+ id: 1,
469
+ update_url: that.bulk_update_url + '?' + params,
470
+ authenticity_token: this.form_authenticity_token,
471
+ attributes: attribs
472
+ });
473
+ },
474
+
475
+ bulk_delete: function(confirm)
476
+ {
477
+ var that = this;
478
+ if (this.model_ids.length == 0)
479
+ {
480
+ $('#message').html("<p class='note error'>Please select at least one row.</p>");
481
+ return;
482
+ }
483
+ if (!confirm)
484
+ {
485
+ var p = $('<p/>').addClass('note').addClass('warning')
486
+ .append('Are you sure you want to delete the selected rows? ')
487
+ .append($('<input/>').attr('type','button').val('Yes').click(function() { that.bulk_delete(true); }))
488
+ .append($('<input/>').attr('type','button').val('No').click(function() { $('#message').empty(); }));
489
+ $('#message').empty().append(p);
490
+ return;
491
+ }
492
+ var params = this.model_ids.map(function(model_id) { return 'model_ids[]=' + model_id; }).join('&');
493
+ $('#' + this.container).html("<p class='loading'>Refreshing...</p>");
494
+ $.ajax({
495
+ url: that.bulk_delete_url,
496
+ type: 'delete',
497
+ data: {
498
+ model_ids: that.model_ids
499
+ },
500
+ success: function(resp) {
501
+ $('#message').empty();
502
+ that.refresh();
503
+ }
504
+ });
505
+ },
506
+
507
+ model_for_id: function(model_id)
508
+ {
509
+ for (var i=0; i<this.models.length; i++)
510
+ if (this.models[i].id == model_id)
511
+ return this.models[i];
512
+ return false;
513
+ },
514
+
515
+ duplicate: function(count)
516
+ {
517
+ var that = this;
518
+ if (this.model_ids.length == 0)
519
+ {
520
+ var p = $('<p/>').addClass('note error').html("Please select a row.");
521
+ $('#message').empty().append(p);
522
+ return;
523
+ }
524
+ if (this.model_ids.length > 1)
525
+ {
526
+ var p = $('<p/>').addClass('note error').html("Please select a single row.");
527
+ $('#message').empty().append(p);
528
+ return;
529
+ }
530
+ if (!count)
531
+ {
532
+ var p = $('<p/>').addClass('note')
533
+ .append('How many times do you want this duplicated?')
534
+ .append($('<input/>').attr('type', 'text').attr('id', 'count').css('width', '50'))
535
+ .append('<br />')
536
+ .append($('<input/>').attr('type', 'button').val('Cancel').click(function(e) { $('#message').empty(); })).append(' ')
537
+ .append($('<input/>').attr('type', 'button').val('Duplicate').click(function(e) { that.duplicate($('#count').val()); return false; }));
538
+ $('#message').empty().append(p);
539
+ return;
540
+ }
541
+ $('#message').html("<p class='loading'>Duplicating...</p>");
542
+ $.ajax({
543
+ url: that.duplicate_url(that.model_ids[0]),
544
+ type: 'post',
545
+ data: { count: count },
546
+ success: function(resp) {
547
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
548
+ if (resp.success) { $('#message').empty(); that.refresh(); }
549
+ }
550
+ });
551
+ },
552
+
553
+ pager_div: function(summary)
554
+ {
555
+ var that = this;
556
+ var p = this.pager;
557
+
558
+ // Set default parameter values if not present
559
+ if (!p.options.items_per_page) p.options.items_per_page = 10
560
+ if (!p.options.page) p.options.page = 1
561
+
562
+ var page = parseInt(p.options.page);
563
+
564
+ // Max links to show (must be odd)
565
+ var total_links = 5;
566
+ var prev_page = page - 1;
567
+ var next_page = page + 1;
568
+ var total_pages = Math.ceil(parseFloat(p.options.item_count)/parseFloat(p.options.items_per_page));
569
+ var start = 1;
570
+ var stop = 1;
571
+
572
+ if (total_pages < total_links)
573
+ {
574
+ start = 1;
575
+ stop = total_pages;
576
+ }
577
+ else
578
+ {
579
+ start = page - Math.floor(total_links/2);
580
+ if (start < 1) start = 1;
581
+ stop = start + total_links - 1
582
+
583
+ if (stop > total_pages)
584
+ {
585
+ stop = total_pages;
586
+ start = stop - total_links;
587
+ if (start < 1) start = 1;
588
+ }
589
+ }
590
+
591
+ var div = $('<div/>').addClass('pager');
592
+ if (summary)
593
+ div.append($('<p/>').html("Results: showing page " + page + " of " + total_pages));
594
+
595
+ if (total_pages > 1)
596
+ {
597
+ var div2 = $('<div/>').addClass('page_links');
598
+ if (page > 1)
599
+ div2.append($('<a/>').attr('href', this.pager_hash({ page: prev_page })).html('Previous').click(function(e) { that.hash_click(e, this); }));
600
+ for (i=start; i<=stop; i++)
601
+ {
602
+ if (page != i)
603
+ div2.append($('<a/>').attr('href', this.pager_hash({ page: i })).html(i).click(function(e) { that.hash_click(e, this); }));
604
+ else
605
+ div2.append($('<span/>').addClass('current_page').html(i));
606
+ }
607
+ if (page < total_pages)
608
+ div2.append($('<a/>').attr('href', this.pager_hash({ page: next_page })).html('Next').click(function(e) { that.hash_click(e, this); }));
609
+ div.append(div2);
610
+ }
611
+ return div;
612
+ },
613
+
614
+ hash_click: function(e, el) {
615
+ e.preventDefault();
616
+ e.stopPropagation();
617
+ window.location.hash = $(el).attr('href').substr(1);
618
+ this.refresh();
619
+ },
620
+
621
+ pager_params: function(h)
622
+ {
623
+ var that = this;
624
+ var p = $.extend({}, this.pager.params);
625
+ if (this.pager.options)
626
+ {
627
+ if (this.pager.options.sort) p.sort = this.pager.options.sort;
628
+ if (this.pager.options.desc) p.desc = this.pager.options.desc ? 1 : 0;
629
+ if (this.pager.options.page) p.page = this.pager.options.page;
630
+ }
631
+ if (h)
632
+ {
633
+ for (var i in h)
634
+ {
635
+ //console.log('' + i + ' = ' + h[i]);
636
+ //console.log(typeof(h[i]));
637
+ //console.log('-------------------');
638
+ if (typeof(h[i]) == 'boolean')
639
+ p[i] = h[i] ? 1 : 0;
640
+ else
641
+ p[i] = h[i];
642
+ }
643
+ }
644
+ return p;
645
+ },
646
+
647
+ pager_hash: function(h)
648
+ {
649
+ var p = this.pager_params(h);
650
+ var qs = [];
651
+ $.each(p, function(k,v) { qs.push('' + k + '=' + encodeURIComponent(v)); });
652
+ return '#' + qs.join('&');
653
+ },
654
+
655
+ /****************************************************************************/
656
+
657
+ new_model_link: function()
658
+ {
659
+ var that = this;
660
+ return $('<a/>').attr('href', '#').html(that.new_model_text).click(function(e) { e.preventDefault(); that.new_form(); });
661
+ },
662
+
663
+ new_form: function()
664
+ {
665
+ var that = this;
666
+ if (!$('#' + that.container + '_new_form_container').is(':empty'))
667
+ {
668
+ $('#' + that.container + '_new_form_container').slideUp(function() {
669
+ $('#' + that.container + '_new_form_container').empty();
670
+ });
671
+ return;
672
+ }
673
+
674
+ var form = $('<form/>').attr('id', 'new_form')
675
+ .append($('<input/>').attr('type', 'hidden').attr('name', 'authenticity_token').val(that.form_authenticity_token));
676
+ $.each(this.new_model_fields, function(i, f) {
677
+ form.append($('<p/>').append($('<input/>').attr('type', 'text').attr('name', f.name).attr('placeholder', f.nice_name).css('width', '' + f.width + 'px')));
678
+ });
679
+ form
680
+ .append($('<div/>').attr('id', 'new_message'))
681
+ .append($('<p>')
682
+ .append($('<input/>').attr('type', 'button').val('Cancel').click(function(e) { $('#' + that.container + '_new_form_container').empty(); }))
683
+ .append(' ')
684
+ .append($('<input/>').attr('type', 'submit').val('Add').click(function(e) { that.add_model(); return false; }))
685
+ );
686
+ $('#' + that.container + '_new_form_container').hide().empty().append(
687
+ $('<div/>').addClass('note').css('margin-bottom', '10px')
688
+ .append($('<h2/>').css('margin-top', 0).css('padding-top', 0).html(that.new_model_text))
689
+ .append(form)
690
+ ).slideDown();
691
+ },
692
+
693
+ add_model: function()
694
+ {
695
+ var that = this;
696
+ $('#new_message').html("<p class='loading'>Adding...</p>");
697
+ $.ajax({
698
+ url: this.add_url,
699
+ type: 'post',
700
+ data: $('#new_form').serialize(),
701
+ success: function(resp) {
702
+ if (resp.error) $('#new_message').html("<p class='note error'>" + resp.error + "</p>");
703
+ if (resp.redirect || resp.refresh) that.refresh();
704
+ }
705
+ });
706
+ },
707
+
708
+
709
+ };