modeljs 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +143 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/modeljs/attribute/checkbox-multiple.js +72 -0
- data/app/assets/javascripts/modeljs/attribute/checkbox.js +32 -0
- data/app/assets/javascripts/modeljs/attribute/date-time.js +30 -0
- data/app/assets/javascripts/modeljs/attribute/file.js +88 -0
- data/app/assets/javascripts/modeljs/attribute/hidden.js +19 -0
- data/app/assets/javascripts/modeljs/attribute/image.js +105 -0
- data/app/assets/javascripts/modeljs/attribute/password.js +36 -0
- data/app/assets/javascripts/modeljs/attribute/radio.js +60 -0
- data/app/assets/javascripts/modeljs/attribute/rich-text.js +40 -0
- data/app/assets/javascripts/modeljs/attribute/select.js +121 -0
- data/app/assets/javascripts/modeljs/attribute/texarea.js +42 -0
- data/app/assets/javascripts/modeljs/attribute/textjs.js +63 -0
- data/app/assets/javascripts/modeljs/attribute/time.js +31 -0
- data/app/assets/javascripts/modeljs/attribute/video.js +95 -0
- data/app/assets/javascripts/modeljs/attribute.js +69 -0
- data/app/assets/javascripts/modeljs/form/embedded.js +13 -0
- data/app/assets/javascripts/modeljs/form.js +257 -0
- data/app/assets/javascripts/modeljs/model.js +543 -0
- data/app/assets/stylesheets/modeljs/modeljs.css +199 -0
- data/lib/modeljs/engine.rb +4 -0
- data/lib/modeljs/version.rb +3 -0
- data/lib/modeljs.rb +5 -0
- data/lib/tasks/modeljs_tasks.rake +0 -0
- metadata +119 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
|
2
|
+
Model.Attribute.Select = Model.Attribute.extend({
|
3
|
+
|
4
|
+
text: '',
|
5
|
+
multiple: false,
|
6
|
+
|
7
|
+
needs_options: function()
|
8
|
+
{
|
9
|
+
return true;
|
10
|
+
},
|
11
|
+
|
12
|
+
view: function()
|
13
|
+
{
|
14
|
+
var html = this.text && this.text.length > 0 ? this.text : this.empty_text;
|
15
|
+
//return $('<a/>')
|
16
|
+
// .attr('title', 'Click to edit')
|
17
|
+
// .attr('href', 'javascript:{};')
|
18
|
+
// .addClass('model_attribute_select')
|
19
|
+
// .html(html);
|
20
|
+
return $('<div/>')
|
21
|
+
.html(html);
|
22
|
+
},
|
23
|
+
|
24
|
+
form: function()
|
25
|
+
{
|
26
|
+
var form = $('<form/>')
|
27
|
+
var select = $('<select></select>')
|
28
|
+
.attr('id', this.base)
|
29
|
+
.attr('name', this.base);
|
30
|
+
|
31
|
+
if (this.multiple)
|
32
|
+
{
|
33
|
+
select.attr('multiple', 'multiple');
|
34
|
+
select.attr('size', '9');
|
35
|
+
}
|
36
|
+
|
37
|
+
var this2 = this;
|
38
|
+
var options = Model.get_attribute_options(this.model.name, this.name);
|
39
|
+
$.each(options, function(i, option)
|
40
|
+
{
|
41
|
+
if (option.children != null) // Option group
|
42
|
+
{
|
43
|
+
var optgroup = $('<optgroup></optgroup>');
|
44
|
+
optgroup.attr('label', option.title);
|
45
|
+
|
46
|
+
$.each(option.children, function(j, option2)
|
47
|
+
{
|
48
|
+
var opt = $('<option></option>')
|
49
|
+
.attr('text', option2.text)
|
50
|
+
.val(option2.value);
|
51
|
+
|
52
|
+
if (!this2.multiple)
|
53
|
+
opt.attr('selected', (option2.value == this2.value));
|
54
|
+
else
|
55
|
+
{
|
56
|
+
opt.attr('selected', false);
|
57
|
+
for (var k=0; k<this2.value.length; k++)
|
58
|
+
if (option2.value == this2.value[k])
|
59
|
+
{
|
60
|
+
opt.attr('selected', true);
|
61
|
+
break;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
optgroup.append(opt);
|
65
|
+
});
|
66
|
+
|
67
|
+
select.append(optgroup);
|
68
|
+
}
|
69
|
+
else
|
70
|
+
{
|
71
|
+
var opt = $('<option></option>')
|
72
|
+
.val(option.value)
|
73
|
+
.text(option.text);
|
74
|
+
|
75
|
+
if (!this2.multiple)
|
76
|
+
{
|
77
|
+
opt.attr('selected', (option.value == this2.value));
|
78
|
+
}
|
79
|
+
else
|
80
|
+
{
|
81
|
+
opt.attr('selected', false);
|
82
|
+
for (var j=0; j<this2.value.length; j++)
|
83
|
+
if (option.value == this2.value[j])
|
84
|
+
{
|
85
|
+
opt.attr('selected', true);
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
select.append(opt);
|
90
|
+
}
|
91
|
+
});
|
92
|
+
form.append(select);
|
93
|
+
if (this.multiple)
|
94
|
+
{
|
95
|
+
form.append("<br/>");
|
96
|
+
form.append(
|
97
|
+
$('<input/>')
|
98
|
+
.attr('type', 'button')
|
99
|
+
.val('Clear')
|
100
|
+
.addClass('update_btn')
|
101
|
+
.click(function() { $('#' + this.base).selectedIndex = -1; })
|
102
|
+
);
|
103
|
+
}
|
104
|
+
|
105
|
+
return form;
|
106
|
+
},
|
107
|
+
|
108
|
+
form_value: function()
|
109
|
+
{
|
110
|
+
if (!this.multiple)
|
111
|
+
return $('#' + this.base + ' option:selected').val();
|
112
|
+
|
113
|
+
var select = $('#' + this.base);
|
114
|
+
val = [];
|
115
|
+
$('#' + this.base + ' option:selected').each(function(i, opt) {
|
116
|
+
val[val.length] = $(opt).val();
|
117
|
+
});
|
118
|
+
return val;
|
119
|
+
}
|
120
|
+
|
121
|
+
});
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
Model.Attribute.Textarea = Model.Attribute.extend({
|
3
|
+
|
4
|
+
show_controls: true,
|
5
|
+
normal_text: false,
|
6
|
+
width: 200,
|
7
|
+
height: 100,
|
8
|
+
|
9
|
+
view: function()
|
10
|
+
{
|
11
|
+
html = this.empty_text;
|
12
|
+
if (this.text && this.text.length > 0) html = this.text;
|
13
|
+
else if (this.value && this.value.length > 0) html = this.value;
|
14
|
+
//return $('<a/>')
|
15
|
+
// .attr('title', 'Click to edit')
|
16
|
+
// .attr('href', 'javascript:{};')
|
17
|
+
// .css({
|
18
|
+
// display: 'block',
|
19
|
+
// width: this.width
|
20
|
+
// })
|
21
|
+
// .html(html);
|
22
|
+
return $('<div/>')
|
23
|
+
.css({
|
24
|
+
display: 'block',
|
25
|
+
width: this.width
|
26
|
+
})
|
27
|
+
.html(html);
|
28
|
+
},
|
29
|
+
|
30
|
+
form: function()
|
31
|
+
{
|
32
|
+
return $('<form/>')
|
33
|
+
.append($('<textarea/>')
|
34
|
+
.attr('id', this.base)
|
35
|
+
.attr('name', this.base)
|
36
|
+
.val(this.value)
|
37
|
+
.css('width', this.width)
|
38
|
+
.css('height', this.height)
|
39
|
+
);
|
40
|
+
}
|
41
|
+
|
42
|
+
});
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
Model.Attribute.Text = Model.Attribute.extend({
|
3
|
+
|
4
|
+
show_reminder: true,
|
5
|
+
|
6
|
+
view: function()
|
7
|
+
{
|
8
|
+
var html = false;
|
9
|
+
if (typeof(this.value) == 'string')
|
10
|
+
html = this.value && this.value.length > 0 ? this.value : this.empty_text;
|
11
|
+
else if (typeof(this.value) == 'number')
|
12
|
+
html = this.value != null ? this.value : this.empty_text;
|
13
|
+
else
|
14
|
+
html = this.value;
|
15
|
+
|
16
|
+
//return $('<a/>')
|
17
|
+
// .attr('title', 'Click to edit')
|
18
|
+
// .attr('href', 'javascript:{};')
|
19
|
+
// .html(html);
|
20
|
+
return $('<div/>')
|
21
|
+
.html(html);
|
22
|
+
},
|
23
|
+
|
24
|
+
form: function()
|
25
|
+
{
|
26
|
+
var this2 = this;
|
27
|
+
var input = $('<input/>')
|
28
|
+
.attr('type', 'text')
|
29
|
+
.attr('id', this.base)
|
30
|
+
.attr('name', this.base)
|
31
|
+
.val(this.value);
|
32
|
+
if (this.show_reminder)
|
33
|
+
input.keyup(function (){ this2.flash_reminder(); })
|
34
|
+
if (this.css)
|
35
|
+
input.css(this.css);
|
36
|
+
var form = $('<form/>').append(input);
|
37
|
+
if (this.show_reminder)
|
38
|
+
form.append($('<span/>').attr('id', this.base + '_reminder').css('font-size', '75%'));
|
39
|
+
|
40
|
+
return form;
|
41
|
+
},
|
42
|
+
|
43
|
+
flash_reminder: function()
|
44
|
+
{
|
45
|
+
$('#' + this.base + '_reminder')
|
46
|
+
.html(' (Enter to update, Escape to cancel)')
|
47
|
+
.delay(1000)
|
48
|
+
.fadeOut({ done: function() { $(this).empty().show(); }});
|
49
|
+
},
|
50
|
+
|
51
|
+
post_form_display: function()
|
52
|
+
{
|
53
|
+
// Put the focus at the end of the string
|
54
|
+
$('#' + this.base).focus();
|
55
|
+
val = $('#' + this.base).val();
|
56
|
+
$('#' + this.base).val('');
|
57
|
+
$('#' + this.base).val(val);
|
58
|
+
|
59
|
+
if (this.show_reminder)
|
60
|
+
this.flash_reminder();
|
61
|
+
}
|
62
|
+
|
63
|
+
});
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
Model.Attribute.Time = Model.Attribute.extend({
|
3
|
+
|
4
|
+
view: function()
|
5
|
+
{
|
6
|
+
var html = this.value && this.value.length > 0 ? this.value : this.empty_text;
|
7
|
+
return $('<a/>')
|
8
|
+
.attr('title', 'Click to edit')
|
9
|
+
.attr('href', 'javascript:{};')
|
10
|
+
.addClass('model_attribute_text')
|
11
|
+
.html(html);
|
12
|
+
},
|
13
|
+
|
14
|
+
form: function()
|
15
|
+
{
|
16
|
+
return $('<form/>')
|
17
|
+
.append($('<input/>')
|
18
|
+
.attr('type', 'text')
|
19
|
+
.attr('id', this.base)
|
20
|
+
.attr('name', this.base)
|
21
|
+
.val(this.value)
|
22
|
+
.addClass('text_box')
|
23
|
+
);
|
24
|
+
},
|
25
|
+
|
26
|
+
post_form_display: function()
|
27
|
+
{
|
28
|
+
$('#' + this.base).timepicker({ ampm: true });
|
29
|
+
}
|
30
|
+
|
31
|
+
});
|
@@ -0,0 +1,95 @@
|
|
1
|
+
|
2
|
+
Model.Attribute.Video = Model.Attribute.extend({
|
3
|
+
|
4
|
+
show_reminder: true,
|
5
|
+
thumb_width: 320,
|
6
|
+
thumb_height: 240,
|
7
|
+
|
8
|
+
view: function()
|
9
|
+
{
|
10
|
+
var html = false;
|
11
|
+
if (typeof(this.value) == 'string')
|
12
|
+
html = this.value && this.value.length > 0 ? this.value : this.empty_text;
|
13
|
+
else if (typeof(this.value) == 'number')
|
14
|
+
html = this.value != null ? this.value : this.empty_text;
|
15
|
+
else
|
16
|
+
html = this.value;
|
17
|
+
var div = $('<div/>').html(html);
|
18
|
+
var iframe = this.video_iframe(this.value);
|
19
|
+
if (iframe)
|
20
|
+
div.append($('<br/>')).append(iframe);
|
21
|
+
return div;
|
22
|
+
},
|
23
|
+
|
24
|
+
form: function()
|
25
|
+
{
|
26
|
+
var this2 = this;
|
27
|
+
var input = $('<input/>')
|
28
|
+
.attr('type', 'text')
|
29
|
+
.attr('id', this.base)
|
30
|
+
.attr('name', this.base)
|
31
|
+
.val(this.value);
|
32
|
+
if (this.show_reminder)
|
33
|
+
input.keyup(function (){ this2.flash_reminder(); })
|
34
|
+
if (this.css)
|
35
|
+
input.css(this.css);
|
36
|
+
var form = $('<form/>').append(input);
|
37
|
+
if (this.show_reminder)
|
38
|
+
form.append($('<span/>').attr('id', this.base + '_reminder').css('font-size', '75%'));
|
39
|
+
|
40
|
+
var iframe = this.video_iframe(this.value);
|
41
|
+
if (iframe)
|
42
|
+
form.append($('<br/>')).append(iframe);
|
43
|
+
|
44
|
+
return form;
|
45
|
+
},
|
46
|
+
|
47
|
+
flash_reminder: function()
|
48
|
+
{
|
49
|
+
$('#' + this.base + '_reminder')
|
50
|
+
.html(' (Enter to update, Escape to cancel)')
|
51
|
+
.delay(1000)
|
52
|
+
.fadeOut({ done: function() { $(this).empty().show(); }});
|
53
|
+
},
|
54
|
+
|
55
|
+
post_form_display: function()
|
56
|
+
{
|
57
|
+
// Put the focus at the end of the string
|
58
|
+
$('#' + this.base).focus();
|
59
|
+
val = $('#' + this.base).val();
|
60
|
+
$('#' + this.base).val('');
|
61
|
+
$('#' + this.base).val(val);
|
62
|
+
|
63
|
+
if (this.show_reminder)
|
64
|
+
this.flash_reminder();
|
65
|
+
},
|
66
|
+
|
67
|
+
video_iframe: function()
|
68
|
+
{
|
69
|
+
if (this.value == null || this.value.length == 0)
|
70
|
+
return false;
|
71
|
+
|
72
|
+
if (this.value.match(/youtube\.com/))
|
73
|
+
{
|
74
|
+
var v = this.value.replace("youtube.com/watch?v=", '');
|
75
|
+
return $('<iframe/>')
|
76
|
+
.attr('type', 'text/html')
|
77
|
+
.attr('width', this.thumb_width)
|
78
|
+
.attr('height', this.thumb_height)
|
79
|
+
.attr('frameborder', '0')
|
80
|
+
.attr('src', "http://www.youtube.com/embed/" + v + "?autoplay=0");
|
81
|
+
}
|
82
|
+
if (this.value.match(/vimeo\.com/))
|
83
|
+
{
|
84
|
+
var v = this.value.replace("vimeo.com/", '');
|
85
|
+
return $('<iframe/>')
|
86
|
+
.attr('type', 'text/html')
|
87
|
+
.attr('width', this.thumb_width)
|
88
|
+
.attr('height', this.thumb_height)
|
89
|
+
.attr('frameborder', '0')
|
90
|
+
.attr('src', "http://player.vimeo.com/video/" + v);
|
91
|
+
}
|
92
|
+
return false;
|
93
|
+
}
|
94
|
+
|
95
|
+
});
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
Model.Attribute = Class.extend({
|
3
|
+
name: '',
|
4
|
+
nice_name: '',
|
5
|
+
value: '',
|
6
|
+
model: false,
|
7
|
+
base: '', // model.name + '_' + model.id + '_' + attribute.name
|
8
|
+
type: false,
|
9
|
+
container: false,
|
10
|
+
controls: false,
|
11
|
+
show_controls: false,
|
12
|
+
message: false,
|
13
|
+
empty_text: '',
|
14
|
+
update_url: false, // If this attribute has a special update URL
|
15
|
+
custom_form: false, // If the attribute needs a custom form (used in file and image)
|
16
|
+
css: false,
|
17
|
+
|
18
|
+
init: function(params)
|
19
|
+
{
|
20
|
+
for (var thing in params)
|
21
|
+
this[thing] = params[thing];
|
22
|
+
this.set_base(this.base);
|
23
|
+
if (!this.nice_name) this.nice_name = this.name.replace('_', ' ').capitalize();
|
24
|
+
},
|
25
|
+
|
26
|
+
set_base: function(base)
|
27
|
+
{
|
28
|
+
this.base = base;
|
29
|
+
if (!this.container) this.container = this.base + '_container';
|
30
|
+
if (!this.controls) this.controls = this.base + '_controls';
|
31
|
+
if (!this.message) this.message = this.base + '_message';
|
32
|
+
},
|
33
|
+
|
34
|
+
// Whether or not the attribute needs to go get options via ajax
|
35
|
+
needs_options: function() { return false; },
|
36
|
+
|
37
|
+
// Returns the viewable representation of the attribute.
|
38
|
+
view: function() { return false; },
|
39
|
+
|
40
|
+
// Returns a form without update or cancel buttons (Assumes options already populated)
|
41
|
+
form: function() { return false; },
|
42
|
+
|
43
|
+
// Returns the current value in the visible form.
|
44
|
+
form_value: function() { return $('#' + this.base).val(); },
|
45
|
+
|
46
|
+
// Returns the values form the form that will be sent to ajax_update
|
47
|
+
form_values: function() {
|
48
|
+
var vals = {};
|
49
|
+
vals[this.name] = this.form_value();
|
50
|
+
return vals;
|
51
|
+
},
|
52
|
+
|
53
|
+
// Runs after the view or form is displayed on the screen.
|
54
|
+
post_view_display: function() {},
|
55
|
+
post_form_display: function() { $('#' + this.base).focus(); },
|
56
|
+
|
57
|
+
// Notes
|
58
|
+
loading: function(str) { this.show_message('loading_small', str); },
|
59
|
+
note: function(str) { this.show_message('note_small' , str); },
|
60
|
+
success: function(str) { this.show_message('note_small success' , str); },
|
61
|
+
error: function(str) { this.show_message('note_small error' , str); },
|
62
|
+
show_message: function(class_names, str) {
|
63
|
+
$('#' + this.message).empty().removeClass('loading_small');
|
64
|
+
$('#' + this.message).addClass(class_names).html(str);
|
65
|
+
},
|
66
|
+
|
67
|
+
// If the attribute needs to handle any finished uploads
|
68
|
+
upload_finished: function(e, data) {}
|
69
|
+
});
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
Class: Model.Form
|
3
|
+
Author: William Barry (william@nine.is)
|
4
|
+
Description: Abstract form class to encapsulate add and edit forms for models.
|
5
|
+
*/
|
6
|
+
|
7
|
+
Model.Form.Embedded = Class.extend({
|
8
|
+
|
9
|
+
add: function() { return false; },
|
10
|
+
edit: function() { return false; },
|
11
|
+
listing: function() { return false; },
|
12
|
+
|
13
|
+
});
|
@@ -0,0 +1,257 @@
|
|
1
|
+
/*
|
2
|
+
Class: Model.Form
|
3
|
+
Author: William Barry (william@nine.is)
|
4
|
+
Description: Abstract form class to encapsulate add and edit forms for models.
|
5
|
+
*/
|
6
|
+
|
7
|
+
Model.Form = Class.extend({
|
8
|
+
|
9
|
+
class_name: 'Model.Form',
|
10
|
+
model: false,
|
11
|
+
message: false,
|
12
|
+
adding_message: null,
|
13
|
+
deleting_message: null,
|
14
|
+
delete_message: null,
|
15
|
+
|
16
|
+
// Listing info
|
17
|
+
listing_models: false,
|
18
|
+
|
19
|
+
init: function(model, params)
|
20
|
+
{
|
21
|
+
this.model = model;
|
22
|
+
if (params)
|
23
|
+
for (var thing in params)
|
24
|
+
this[thing] = params[thing];
|
25
|
+
|
26
|
+
if (!this.message ) this.message = model.name + '_message';
|
27
|
+
if (!this.adding_message ) this.adding_message = 'Adding ' + this.model.name + '...';
|
28
|
+
if (!this.deleting_message) this.deleting_message = 'Deleting ' + this.model.name + '...';
|
29
|
+
if (!this.delete_message ) this.delete_message = "Are you sure you want to delete the " + this.model.name + "? This can't be undone.";
|
30
|
+
},
|
31
|
+
|
32
|
+
// Returns the form for adding the model or false for an embedded form.
|
33
|
+
add: function()
|
34
|
+
{
|
35
|
+
var m = this.model;
|
36
|
+
var tbody = $('<tbody/>');
|
37
|
+
$(m.attributes).each(function(i, a) {
|
38
|
+
if (a.type == 'hidden')
|
39
|
+
return;
|
40
|
+
tbody.append($('<tr/>')
|
41
|
+
.append($('<td/>').css('vertical-align', 'top').html(a.nice_name + ':'))
|
42
|
+
.append($('<td/>').css('vertical-align', 'top').attr('id', m.name + '_' + m.id + '_' + a.name + '_container')
|
43
|
+
.append(a.form().children())
|
44
|
+
)
|
45
|
+
);
|
46
|
+
});
|
47
|
+
var form = $('<form/>')
|
48
|
+
.attr('id', 'new_' + m.name + '_form')
|
49
|
+
.submit(function() { return false; })
|
50
|
+
.append($('<table/>').append(tbody))
|
51
|
+
.append($('<div/>').attr('id', this.message_div))
|
52
|
+
.append($('<p/>')
|
53
|
+
.append($('<input/>').attr('type', 'submit').val('Add ' + m.name).click(function() { m.ajax_add(); }))
|
54
|
+
.append($('<input/>').attr('type', 'button').val('Back').click(function() { window.location = m.listing_url; }))
|
55
|
+
);
|
56
|
+
return form;
|
57
|
+
},
|
58
|
+
|
59
|
+
// Runs after the add form has been displayed
|
60
|
+
post_add_display: function() {},
|
61
|
+
|
62
|
+
// Returns the form for editing a model or false for an embedded form.
|
63
|
+
edit: function()
|
64
|
+
{
|
65
|
+
var m = this.model;
|
66
|
+
|
67
|
+
var this2 = this;
|
68
|
+
var tbody = $('<tbody/>');
|
69
|
+
$(m.attributes).each(function(i, a) {
|
70
|
+
if (a.type == 'hidden')
|
71
|
+
return;
|
72
|
+
tbody.append($('<tr/>')
|
73
|
+
.append($('<td/>').css('vertical-align', 'top').html(a.nice_name + ':'))
|
74
|
+
.append($('<td/>').css('vertical-align', 'top').attr('id', m.name + '_' + m.id + '_' + a.name + '_container'))
|
75
|
+
);
|
76
|
+
});
|
77
|
+
|
78
|
+
var div = $('<div/>')
|
79
|
+
.append($('<table/>').append(tbody))
|
80
|
+
.append($('<div/>').attr('id', this.message))
|
81
|
+
.append($('<p/>')
|
82
|
+
.append($('<input/>').attr('type', 'button').val('Back').click(function() { window.location = m.listing_url; }))
|
83
|
+
.append(' ')
|
84
|
+
.append($('<input/>').attr('type', 'button').val('Delete ' + m.name).click(function() { m.ajax_delete(); }))
|
85
|
+
);
|
86
|
+
return div;
|
87
|
+
},
|
88
|
+
|
89
|
+
// Runs after the edit form has been displayed
|
90
|
+
post_edit_display: function() {},
|
91
|
+
|
92
|
+
listing_view: function()
|
93
|
+
{
|
94
|
+
var tr = $('<tr/>');
|
95
|
+
var m = this.model;
|
96
|
+
$(this.model.attributes).each(function(i, a) {
|
97
|
+
if (a.type == 'hidden') return;
|
98
|
+
tr.append(
|
99
|
+
$('<td/>')
|
100
|
+
.attr('id', m.name + '_' + m.id + '_' + a.name + '_container')
|
101
|
+
.append(a.view())
|
102
|
+
);
|
103
|
+
});
|
104
|
+
return tr;
|
105
|
+
},
|
106
|
+
|
107
|
+
post_listing_view_display: function() {},
|
108
|
+
|
109
|
+
// Returns a listing table of models or false for an embedded listing
|
110
|
+
listing_form: function()
|
111
|
+
{
|
112
|
+
var m = this.model;
|
113
|
+
var count = m.unhidden_attribute_count();
|
114
|
+
var tr = $('<tr/>').attr('id', m.name + '_' + m.id + '_listing_container');
|
115
|
+
$(this.model.attributes).each(function(i, a) {
|
116
|
+
if (a.type == 'hidden')
|
117
|
+
return;
|
118
|
+
var c = '';
|
119
|
+
if (i == 0) c = 'edit_listing_first_cell';
|
120
|
+
else if (i == count-1) c = 'edit_listing_last_cell';
|
121
|
+
else c = 'edit_listing_cell';
|
122
|
+
|
123
|
+
tr.append($('<td/>')
|
124
|
+
.css('vertical-align', 'top')
|
125
|
+
.addClass(c)
|
126
|
+
.attr('id', m.name + '_' + m.id + '_' + a.name + '_container')
|
127
|
+
);
|
128
|
+
});
|
129
|
+
return tr;
|
130
|
+
},
|
131
|
+
|
132
|
+
// Runs after the listing has been displayed
|
133
|
+
post_listing_form_display: function() {},
|
134
|
+
|
135
|
+
listing_view: function()
|
136
|
+
{
|
137
|
+
var m = this.model;
|
138
|
+
var tr = $('<tr/>').attr('id', m.name + '_' + m.id + '_listing_container');
|
139
|
+
$(this.model.attributes).each(function(i, a) {
|
140
|
+
if (a.type == 'hidden')
|
141
|
+
return;
|
142
|
+
tr.append($('<td/>').css('vertical-align', 'top').attr('id', m.name + '_' + m.id + '_' + a.name + '_container'));
|
143
|
+
});
|
144
|
+
return tr;
|
145
|
+
},
|
146
|
+
|
147
|
+
post_listing_view_display: function() {},
|
148
|
+
|
149
|
+
// Gets the latest rows for the listing
|
150
|
+
refresh_listing_models: function(done)
|
151
|
+
{
|
152
|
+
var this2 = this;
|
153
|
+
var obj = Model.parse_url(this.model.listing_url);
|
154
|
+
$.ajax({
|
155
|
+
url: obj.url,
|
156
|
+
type: obj.verb,
|
157
|
+
success: function(models) {
|
158
|
+
this2.refresh_listing_models_helper(models);
|
159
|
+
done();
|
160
|
+
},
|
161
|
+
error: function() {
|
162
|
+
this2.ajax_error('Error');
|
163
|
+
}
|
164
|
+
});
|
165
|
+
},
|
166
|
+
|
167
|
+
refresh_listing_models_helper: function(models)
|
168
|
+
{
|
169
|
+
var this2 = this;
|
170
|
+
this.listing_models = [];
|
171
|
+
$(models).each(function(i, m) {
|
172
|
+
|
173
|
+
var attribs = [];
|
174
|
+
$(m.attributes).each(function(i, a) {
|
175
|
+
|
176
|
+
// Find the original attribute with the same name
|
177
|
+
var attrib = false;
|
178
|
+
$(this2.model.attributes_original).each(function(j, a2) {
|
179
|
+
if (a2.name == a.name)
|
180
|
+
{
|
181
|
+
attrib = $.extend(true, {}, a2);
|
182
|
+
return false;
|
183
|
+
}
|
184
|
+
});
|
185
|
+
|
186
|
+
// Copy new data into the original attribute hash
|
187
|
+
for (var thing in a)
|
188
|
+
attrib[thing] = a[thing];
|
189
|
+
attrib.base = this2.model.name + '_' + m.id + '_' + attrib.name;
|
190
|
+
|
191
|
+
attribs.push(attrib);
|
192
|
+
});
|
193
|
+
var params = {
|
194
|
+
name: this2.model.name,
|
195
|
+
id: m.id,
|
196
|
+
form: this2.class_name,
|
197
|
+
attributes: attribs,
|
198
|
+
create_url: this2.model.create_url,
|
199
|
+
update_url: this2.model.update_url,
|
200
|
+
delete_url: this2.model.delete_url,
|
201
|
+
listing_url: this2.model.listing_url,
|
202
|
+
listing_edit: this2.model.listing_edit,
|
203
|
+
listing_delete: this2.model.listing_delete,
|
204
|
+
listing_empty_text: this2.model.listing_empty_text,
|
205
|
+
is_listing: true
|
206
|
+
};
|
207
|
+
var m2 = new Model(params);
|
208
|
+
this2.listing_models.push(m2);
|
209
|
+
});
|
210
|
+
},
|
211
|
+
|
212
|
+
// Returns the values of the add form that will be sent to model.ajax_add
|
213
|
+
add_values: function()
|
214
|
+
{
|
215
|
+
var m = this.model;
|
216
|
+
var data = {};
|
217
|
+
$(m.attributes).each(function(i, a) {
|
218
|
+
data[a.name] = a.form_value();
|
219
|
+
});
|
220
|
+
return data;
|
221
|
+
},
|
222
|
+
|
223
|
+
// Show a confirmation screen
|
224
|
+
confirm: function(params)
|
225
|
+
{
|
226
|
+
var this2 = this;
|
227
|
+
$('#' + this.message).empty()
|
228
|
+
.append($('<div/>')
|
229
|
+
.addClass('note2 error')
|
230
|
+
.append($('<p/>').append(params.message))
|
231
|
+
.append($('<p/>')
|
232
|
+
.append($('<input />').attr('type', 'button').val('Yes').click(params.yes))
|
233
|
+
.append(" ")
|
234
|
+
.append($('<input />').attr('type', 'button').val('No').click(function() { $('#' + this2.message).empty(); }))
|
235
|
+
)
|
236
|
+
);
|
237
|
+
},
|
238
|
+
|
239
|
+
ajax_success: function(resp)
|
240
|
+
{
|
241
|
+
if (resp.text) $('#' + this.message).empty().append($('<p/>').addClass('note' ).html(resp.text));
|
242
|
+
else if (resp.success) $('#' + this.message).empty().append($('<p/>').addClass('note success').html(resp.success));
|
243
|
+
else if (resp.error) $('#' + this.message).empty().append($('<p/>').addClass('note error' ).html(resp.error));
|
244
|
+
else if (resp.flash) $('#' + this.message).empty().append($('<p/>').html(resp.flash).delay(2000).fadeOut().delay(2000).queue(function() { $(this).remove(); }));
|
245
|
+
else if (resp.redirect) window.location = resp.redirect;
|
246
|
+
else $('#' + this.message).empty();
|
247
|
+
},
|
248
|
+
|
249
|
+
ajax_error: function(str) { this.error(str); },
|
250
|
+
|
251
|
+
// Notes
|
252
|
+
loading: function(str) { this.show_message('loading' , str); },
|
253
|
+
note: function(str) { this.show_message('note' , str); },
|
254
|
+
success: function(str) { this.show_message('note success' , str); },
|
255
|
+
error: function(str) { this.show_message('note error' , str); },
|
256
|
+
show_message: function(class_names, str) { $('#' + this.message).empty().append($('<p/>').addClass(class_names).html(str)); }
|
257
|
+
});
|