-
-
Notifications
You must be signed in to change notification settings - Fork 27
/
CollectionModel.js
204 lines (165 loc) · 5.94 KB
/
CollectionModel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* global define */
define(["jquery",
"underscore",
"backbone",
"collections/Filters",
"models/DataONEObject",
"models/filters/Filter",
"models/Search"],
function($, _, Backbone, Filters, DataONEObject, Filter, Search) {
var CollectionModel = DataONEObject.extend({
//The default attributes for this model
defaults: function(){
return {
name: null,
label: null,
description: null,
filters: null
}
},
/**
* The default Backbone.Model.initialize() function
*
*/
initialize: function(options){
},
/**
*
*
*/
url: function(){
return MetacatUI.appModel.get("objectServiceUrl") + encodeURIComponent(this.get("id"));
},
/**
* Overrides the default Backbone.Model.fetch() function to provide some custom
* fetch options
*
*/
fetch: function(){
var model = this;
var requestSettings = {
dataType: "xml",
error: function(){
model.trigger("error");
}
}
//Add the authorization header and other AJAX settings
requestSettings = _.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings());
return Backbone.Model.prototype.fetch.call(this, requestSettings);
},
/**
* Overrides the default Backbone.Model.parse() function to parse the custom
* collection XML document
*
* @param {XMLDocument} response - The XMLDocument returned from the fetch() AJAX call
* @return {JSON} The result of the parsed XML, in JSON. To be set directly on the model.
*/
parse: function(json){
//Start the empty JSON object
var modelJSON = {},
collectionNode;
//Iterate over each root XML node to find the collection node
$(response).children().each(function(i, el){
if( el.tagName.indexOf("collection") > -1 ){
collectionNode = el;
return false;
}
});
//If a collection XML node wasn't found, return an empty JSON object
if( typeof collectionNode == "undefined" || !collectionNode )
return {};
//Parse the collection XML and return it
return this.parseCollectionXML(collectionNode);
},
/**
* Parses the collection XML into a JSON object
*
* @param {Element} rootNode - The XML Element that contains all the collection nodes
* @return {JSON} The result of the parsed XML, in JSON. To be set directly on the model.
*/
parseCollectionXML: function( rootNode ){
var modelJSON = {};
//Parse the simple text nodes
modelJSON.name = this.parseTextNode(rootNode, "name");
modelJSON.label = this.parseTextNode(rootNode, "label");
modelJSON.description = this.parseTextNode(rootNode, "description");
modelJSON.searchModel = new Search();
modelJSON.searchModel.set("filters", new Filters());
modelJSON.searchModel.get("filters").createCatalogFilters();
//Parse the collection definition
_.each( $(rootNode).find("definition > filter"), function(filterNode){
//Create a new Filter model
var filterModel = new Filter({
objectDOM: filterNode,
isInvisible: true
});
//Add the filter to the Filters collection
modelJSON.searchModel.get("filters").add(filterModel);
});
return modelJSON;
},
/**
* Gets the text content of the XML node matching the given node name
*
* @param {Element} parentNode - The parent node to select from
* @param {string} nodeName - The name of the XML node to parse
* @param {boolean} isMultiple - If true, parses the nodes into an array
* @return {(string|Array)} - Returns a string or array of strings of the text content
*/
parseTextNode: function( parentNode, nodeName, isMultiple ){
var node = $(parentNode).children(nodeName);
//If no matching nodes were found, return falsey values
if( !node || !node.length ){
//Return an empty array if the isMultiple flag is true
if( isMultiple )
return [];
//Return null if the isMultiple flag is false
else
return null;
}
//If exactly one node is found and we are only expecting one, return the text content
else if( node.length == 1 && !isMultiple ){
return node[0].textContent.trim();
}
//If more than one node is found, parse into an array
else{
return _.map(node, function(node){
return node.textContent.trim() || null;
});
}
},
/**
* Updates collection XML with values in the collection model
*
* @param {XMLDocument} objectDOM the XML element to be updated
* @return {XMLElement} An updated XML element
*/
serializeCollectionXML: function(objectDOM){
// Namespace for the project XML (required for document.createElementNS())
var namespace = "http://ecoinformatics.org/datasetproject-beta";
// Get and update the simple text strings (everything but definition)
// in reverse order because we prepend them consecutively to objectDOM
var collectionTextData = {
description: this.get("description"),
label: this.get("label"),
name: this.get("name")
}
_.map(collectionTextData, function(value, nodeName){
// remove the node if it exists
// use children() and not find() as there are sub-children named label
$(objectDOM).children(nodeName).remove();
// Don't serialize falsey values
if(value){
// Make new sub-node
var collectionSubnodeSerialized = document.createElementNS(namespace, nodeName);
$(collectionSubnodeSerialized).text(value);
// Append new sub-node to the start of the objectDOM
$(objectDOM).prepend(collectionSubnodeSerialized);
}
});
// TODO: serialize filters here
return objectDOM;
}
});
return CollectionModel;
});