lots of changes to xosHelper
[plstackapi.git] / planetstack / core / xoslib / static / js / xoslib / xosHelper.js
1 XOSApplication = Marionette.Application.extend({
2     detailBoxId: "#detailBox",
3     errorBoxId: "#errorBox",
4     errorCloseButtonId: "#close-error-box",
5     successBoxId: "#successBox",
6     successCloseButtonId: "#close-success-box",
7     errorTemplate: "#xos-error-template",
8     successTemplate: "#xos-success-template",
9
10     hideError: function(result) {
11         $(this.errorBoxId).hide();
12         $(this.successBoxId).hide();
13     },
14
15     showSuccess: function(result) {
16          $(this.successBoxId).show();
17          $(this.successBoxId).html(_.template($(this.successTemplate).html())(result));
18          $(this.successCloseButtonId).unbind().bind('click', function() {
19              $(this.successBoxId).hide();
20          });
21     },
22
23     showError: function(result) {
24          $(this.errorBoxId).show();
25          $(this.errorBoxId).html(_.template($(this.errorTemplate).html())(result));
26          $(this.errorCloseButtonId).unbind().bind('click', function() {
27              $(this.errorBoxId).hide();
28          });
29     },
30 });
31
32 /* XOSDetailView
33       extend with:
34          app - MarionetteApplication
35          template - template (See XOSHelper.html)
36 */
37
38 XOSDetailView = Marionette.ItemView.extend({
39             tagName: "div",
40
41             events: {"click button.js-submit": "submitClicked",
42                      "change input": "inputChanged"},
43
44             events: {"click button.js-submit": "submitClicked",
45                      "change input": "inputChanged"},
46
47             /* inputChanged is watching the onChange events of the input controls. We
48                do this to track when this view is 'dirty', so we can throw up a warning\r
49                if the user tries to change his slices without saving first.\r
50             */\r
51 \r
52             inputChanged: function(e) {\r
53                 this.dirty = true;\r
54             },\r
55 \r
56             saveError: function(model, result, xhr) {\r
57                 this.app.showError(result);\r
58             },\r
59 \r
60             saveSuccess: function(model, result, xhr) {\r
61                 this.app.showSuccess({status: xhr.xhr.status, statusText: xhr.xhr.statusText});\r
62             },
63
64             submitClicked: function(e) {
65                 this.app.hideError();\r
66                 e.preventDefault();\r
67                 var data = Backbone.Syphon.serialize(this);\r
68                 var thisView = this;\r
69                 this.model.save(data, {error: function(model, result, xhr) { thisView.saveError(model, result, xhr); },\r
70                                        success: function(model, result, xhr) { thisView.saveSuccess(model, result, xhr); }});\r
71                 this.dirty = false;\r
72             },
73
74             showLinkedItems: function() {
75                     index=0;\r
76                     for (relatedName in this.model.collection.relatedCollections) {\r
77                         relatedField = this.model.collection.relatedCollections[relatedName];\r
78 \r
79                         relatedListViewClassName = relatedName + "ListView";\r
80                         if (this.app[relatedListViewClassName] == undefined) {\r
81                             console.log("warning: " + relatedListViewClassName + " not found");\r
82                         }\r
83                         relatedListViewClass = this.app[relatedListViewClassName].extend({collection: xos[relatedName].filterBy(relatedField,this.model.id)});\r
84                         this.app["linkedObjs" + (index+1)].show(new relatedListViewClass());\r
85                         index = index + 1;\r
86                     }\r
87 \r
88                     while (index<4) {\r
89                         this.app["linkedObjs" + (index+1)].empty();\r
90                         index = index + 1;\r
91                     }\r
92               },
93 });
94
95 /* XOSItemView
96       This is for items that will be displayed as table rows.
97       extend with:
98          app - MarionetteApplication
99          template - template (See XOSHelper.html)
100          detailClass - class of detail view, probably an XOSDetailView
101 */
102
103 XOSItemView = Marionette.ItemView.extend({
104              tagName: 'tr',
105              className: 'test-tablerow',
106
107              events: {"click": "changeItem"},
108
109              changeItem: function(e) {\r
110                     this.app.hideError();\r
111                     e.preventDefault();\r
112                     e.stopPropagation();\r
113 \r
114                     this.app.navigateToModel(this.app, this.detailClass, this.detailNavLink, this.model);\r
115              },\r
116 });
117
118 /* XOSListView:
119       extend with:
120          app - MarionetteApplication
121          childView - class of ItemView, probably an XOSItemView
122          template - template (see xosHelper.html)
123          collection - collection that holds these objects
124          title - title to display in template
125 */
126
127 XOSListView = Marionette.CompositeView.extend({
128              childViewContainer: 'tbody',\r
129 \r
130              initialize: function() {\r
131                  this.listenTo(this.collection, 'change', this._renderChildren)
132
133                  // Because many of the templates use idToName(), we need to
134                  // listen to the collections that hold the names for the ids
135                  // that we want to display.
136                  for (i in this.collection.foreignCollections) {
137                      foreignName = this.collection.foreignCollections[i];
138                      if (xos[foreignName] == undefined) {
139                          console.log("Failed to find xos class " + foreignName);
140                      }
141                      this.listenTo(xos[foreignName], 'change', this._renderChildren);
142                      this.listenTo(xos[foreignName], 'sort', this._renderChildren);
143                  }
144              },
145
146              templateHelpers: function() {
147                 return { title: this.title };
148              },\r
149 });
150
151 /* Give an id, the name of a collection, and the name of a field for models
152    within that collection, lookup the id and return the value of the field.
153 */
154
155 idToName = function(id, collectionName, fieldName) {
156     linkedObject = xos[collectionName].get(id);
157     if (linkedObject == undefined) {
158         return "#" + id;
159     } else {
160         return linkedObject.attributes[fieldName];
161     }
162 };
163
164 /* Constructs lists of <option> html blocks for items in a collection.
165
166    selectedId = the id of an object that should be selected, if any
167    collectionName = name of collection
168    fieldName = name of field within models of collection that will be displayed
169 */
170
171 idToOptions = function(selectedId, collectionName, fieldName) {
172     result=""
173     for (index in xos[collectionName].models) {
174         linkedObject = xos[collectionName].models[index];
175         linkedId = linkedObject["id"];
176         linkedName = linkedObject.attributes[fieldName];
177         if (linkedId == selectedId) {
178             selected = " selected";
179         } else {
180             selected = "";
181         }
182         result = result + '<option value="' + linkedId + '"' + selected + '>' + linkedName + '</option>';
183     }
184     return result;
185 };
186
187 /* Constructs an html <select> and the <option>s to go with it.
188
189    variable = variable name to return to form
190    selectedId = the id of an object that should be selected, if any
191    collectionName = name of collection
192    fieldName = name of field within models of collection that will be displayed
193 */
194
195 idToSelect = function(variable, selectedId, collectionName, fieldName) {
196     result = '<select name="' + variable + '">' +
197              idToOptions(selectedId, collectionName, fieldName) +
198              '</select>';
199     return result;
200 }
201