/
EMLGeoCoverageView.js
253 lines (209 loc) · 10.8 KB
/
EMLGeoCoverageView.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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/* global define */
define(['underscore', 'jquery', 'backbone',
'models/metadata/eml211/EMLGeoCoverage',
'text!templates/metadata/EMLGeoCoverage.html'],
function (_, $, Backbone, EMLGeoCoverage, EMLGeoCoverageTemplate) {
/*
The EMLGeoCoverage renders the content of an EMLGeoCoverage model
*/
var EMLGeoCoverageView = Backbone.View.extend({
type: "EMLGeoCoverageView",
tagName: "div",
className: "row-fluid eml-geocoverage",
attributes: {
"data-category": "geoCoverage"
},
editTemplate: _.template(EMLGeoCoverageTemplate),
initialize: function (options) {
if (!options)
var options = {};
this.isNew = options.isNew || (options.model ? false : true);
this.model = options.model || new EMLGeoCoverage();
this.edit = options.edit || false;
},
events: {
"change": "updateModel",
"mouseover .remove": "toggleRemoveClass",
"mouseout .remove": "toggleRemoveClass"
},
render: function (e) {
//Save the view and model on the element
this.$el.data({
model: this.model,
view: this
});
this.$el.html(this.editTemplate({
edit: this.edit,
model: this.model.toJSON()
}));
if (this.isNew) {
this.$el.addClass("new");
}
return this;
},
/**
* Updates the model.
* If this is called from the user switching between latitude and longitude boxes,
* we check to see if the input was valid and display any errors if we need to.
*
* @function updateModel
* @param e The event
*/
updateModel: function (e) {
if (!e) return false;
e.preventDefault();
//Get the attribute and value
var element = $(e.target),
value = element.val(),
attribute = element.attr("data-attribute");
//Get the attribute that was changed
if (!attribute) return false;
var emlModel = this.model.getParentEML();
if(emlModel){
value = emlModel.cleanXMLText(value);
}
//Are the NW and SE points the same? i.e. is this a single point and not a box?
var isSinglePoint = (this.model.get("north") != null && this.model.get("north") == this.model.get("south")) &&
(this.model.get("west") != null && this.model.get("west") == this.model.get("east")),
hasEmptyInputs = this.$("[data-attribute='north']").val() == "" ||
this.$("[data-attribute='south']").val() == "" ||
this.$("[data-attribute='west']").val() == "" ||
this.$("[data-attribute='east']").val() == "";
//Update the model
if (value == "")
this.model.set(attribute, null);
else
this.model.set(attribute, value);
//If the NW and SE points are the same point...
if (isSinglePoint && hasEmptyInputs) {
/* If the user updates one of the empty number inputs, then we can assume they do not
* want a single point and are attempting to enter a second point. So we should empty the
* value from the model for the corresponding coordinate
* For example, if the UI shows a lat,long pair of NW: [10] [30] SE: [ ] [ ] then the model
* values would be N: 10, W: 30, S: 10, E: 30
* if the user updates that to: NW: [10] [30] SE: [5] [ ]
* then we want to remove the "east" value of "30", so the model would be: N: 10, W: 30, S: 5, E: null
*/
if (attribute == "north" && this.$("[data-attribute='west']").val() == "")
this.model.set("west", null);
else if (attribute == "south" && this.$("[data-attribute='east']").val() == "")
this.model.set("east", null);
else if (attribute == "east" && this.$("[data-attribute='south']").val() == "")
this.model.set("south", null);
else if (attribute == "west" && this.$("[data-attribute='north']").val() == "")
this.model.set("north", null);
/*
* If the user removes one of the latitude or longitude values, reset the opposite point
*/
else if (((attribute == "north" && this.model.get("north") == null) ||
(attribute == "west" && this.model.get("west") == null)) &&
(this.$("[data-attribute='south']").val() == "" &&
this.$("[data-attribute='east']").val() == "")) {
this.model.set("south", null);
this.model.set("east", null);
} else if (((attribute == "south" && this.model.get("south") == null) ||
(attribute == "east" && this.model.get("east") == null)) &&
(this.$("[data-attribute='north']").val() == "" && this.$("[data-attribute='west']").val() == "")) {
this.model.set("north", null);
this.model.set("west", null);
}
/* Otherwise, if the non-empty number inputs are updated,
* we simply update the corresponding value in the other point
*/
else if (attribute == "north" && this.model.get("north") != null)
this.model.set("south", value);
else if (attribute == "south" && this.model.get("south") != null)
this.model.set("north", value);
else if (attribute == "west" && this.model.get("west") != null)
this.model.set("east", value);
else if (attribute == "east" && this.model.get("east") != null)
this.model.set("west", value);
}
else {
//Find out if we are missing a complete NW or SE point
var isMissingNWPoint = (this.model.get("north") == null && this.model.get("west") == null),
isMissingSEPoint = (this.model.get("south") == null && this.model.get("east") == null);
// If there is a full NW point but no SE point, we can assume the user wants a single point and
// so we will copy the NW values to the SE
if (this.model.get("north") != null && this.model.get("west") != null && isMissingSEPoint) {
this.model.set("south", this.model.get("north"));
this.model.set("east", this.model.get("west"));
}
// Same for when there is a SE point but no NW point
else if (this.model.get("south") != null && this.model.get("east") != null && isMissingNWPoint) {
this.model.set("north", this.model.get("south"));
this.model.set("west", this.model.get("east"));
}
}
// Validate the coordinate boxes
//this.validateCoordinates(e);
//If this model is part of the EML inside the root data package, mark the package as changed
if (this.model.get("parentModel")) {
if (this.model.get("parentModel").type == "EML" && _.contains(MetacatUI.rootDataPackage.models, this.model.get("parentModel"))) {
MetacatUI.rootDataPackage.packageModel.set("changed", true);
}
}
this.validate();
},
/**
* Checks to see if any error messages need to be removed. If not, then it performs validation
* across the row and displays any errors. This id called when the user clicks out of an edit box
* on to the page.
*
* @function validate
* @param e The event
* @param options
*/
validate: function (e, options) {
//Query for the EMlGeoCoverageView element that the user is actively interacting with
var activeGeoCovEl = $(document.activeElement).parents(".eml-geocoverage");
//If the user is not actively in this view, then exit
if (activeGeoCovEl.length && activeGeoCovEl[0] == this.el)
return;
//If the model is valid, then remove error styling and exit
if( this.model.isValid() ) {
this.$(".error").removeClass("error");
this.$el.removeClass("error");
this.$(".notification").empty();
this.model.trigger("valid");
return;
}
else{
this.showValidation();
}
},
/*
* Resets the error messaging and displays the current error messages for this model
* This function is used by the EML211EditorView during the package validation process
*/
showValidation: function(){
this.$(".error").removeClass("error");
this.$el.removeClass("error");
this.$(".notification").empty();
var errorMessages = "";
for( field in this.model.validationError ){
this.$("[data-attribute='" + field + "']").addClass("error");
errorMessages += this.model.validationError[field] + " ";
}
this.$(".notification").text(errorMessages).addClass("error");
},
/**
* Highlight what will be removed when the remove icon is hovered over
*
* @function toggleRemoveClass
*/
toggleRemoveClass: function () {
this.$el.toggleClass("remove-preview");
},
/**
* Unmarks this view as new
*
* @function notNew
*/
notNew: function () {
this.$el.removeClass("new");
this.isNew = false;
}
});
return EMLGeoCoverageView;
});