/* global define */
define(['underscore', 'jquery', 'backbone', 'models/metadata/eml211/EMLMethods', 'models/metadata/eml211/EMLText',
'text!templates/metadata/EMLMethods.html'],
function(_, $, Backbone, EMLMethods, EMLText, EMLMethodsTemplate){
/**
* @class EMLMethodsView
* @classdesc The EMLMethods renders the content of an EMLMethods model
* @classcategory Views/Metadata
* @extends Backbone.View
*/
var EMLMethodsView = Backbone.View.extend(
/** @lends EMLMethodsView.prototype */{
type: "EMLMethodsView",
tagName: "div",
className: "row-fluid eml-methods",
editTemplate: _.template(EMLMethodsTemplate),
initialize: function(options){
options = options || {};
this.isNew = options.isNew || (options.model? false : true);
this.model = options.model || new EMLMethods();
this.edit = options.edit || false;
this.$el.data({ model: this.model });
},
events: {
"change" : "updateModel",
"keyup .method-step.new" : "addNewMethodStep",
"click .remove" : "removeMethodStep",
"mouseover .remove" : "previewRemove",
"mouseout .remove" : "previewRemove"
},
render: function() {
//Save the view and model on the element
this.$el.data({
model: this.model,
view: this
})
.attr("data-category", "methods");
if (this.edit) {
this.$el.html(this.editTemplate({
methodStepDescription: _(this.model.get('methodStepDescription')).map(function(step) { return step.toString()} ),
studyExtentDescription: this.model.get('studyExtentDescription'),
samplingDescription: this.model.get('samplingDescription')
}));
}
return this;
},
renderTextArea: function(textModel, data) {
if (typeof data === 'undefined') return;
var text,
isNew;
if (!textModel || typeof textModel === 'undefined') {
text = '';
isNew = true;
} else {
text = textModel.get('text').toString();
isNew = false;
}
var el = $(document.createElement('textarea'))
.attr('rows', '7')
.attr('data-attribute', data.category)
.attr('data-type', data.type)
.addClass("method-step").addClass(data.classes || "")
.text(text);
if (isNew) {
$(el).addClass('new')
}
return el;
},
updateModel: function(e){
if(!e) return false;
var updatedInput = $(e.target);
//Get the attribute that was changed
var changedAttr = updatedInput.attr("data-attribute");
if(!changedAttr) return false;
// Get the EMLText type (parent element)
var textType = updatedInput.attr("data-type");
if (!textType) return false;
//Get the current value
var currentValue = this.model.get(changedAttr);
// Method Step Descriptions are ordered arrays, so update them with special rules
if (changedAttr == "methodStepDescription") {
// Get the DOM position so we know which one to update
var position = this.$(".method-step").index(updatedInput);
// Stop if, for some odd reason, the position isn't found
if (position === -1) {
return;
}
//If there is already an EMLText model created, then update it
if( typeof currentValue[position] == "object" && currentValue[position].type == "EMLText"){
currentValue[position].setText(updatedInput.val());
}
else{
//Create a new EMLText model
var newTextModel = new EMLText({
type: textType,
parentModel: this.model
});
//Update the model with the textarea value
newTextModel.setText(updatedInput.val());
//Insert this new model into the correct position
currentValue[position] = newTextModel;
}
// Trigger the change event manually because, without this, the change event
// never fires.
this.model.trigger('change:' + changedAttr);
}
//All other attributes on this model can be updated the same way
else {
//Get the EMLText model to update
var textModelToUpdate = this.model.get(changedAttr);
//Double-check that this is an EMLText model, then update it
if( textModelToUpdate && typeof textModelToUpdate == "object" && textModelToUpdate.type == "EMLText"){
textModelToUpdate.setText(updatedInput.val());
}
//If there's no value set on this attribute yet, create a new EMLText model
else if(!textModelToUpdate){
//Create a new EMLText model
var newTextModel = new EMLText({
type: textType,
parentModel: this.model
});
//Update the model with the textarea value
newTextModel.setText(updatedInput.val());
//Set the EMLText model on the EMLMethods model
this.model.set(changedAttr, newTextModel);
}
}
//Add this model to the parent EML model when it is valid
if(this.model.isValid()){
this.model.get("parentModel").set("methods", this.model);
}
//Show the remove button
$(e.target).parents(".step-container").find(".remove").show();
},
/*
* Add a new method step
*/
addNewMethodStep: function(){
// Add new textareas as needed
var newStep = this.$(".method-step.new"),
nextStepNum = this.$(".method-step").length + 1,
methodStepContainer = $(document.createElement("div")).addClass("step-container");
newStep.removeClass("new");
//Put it all together
newStep.parent(".step-container")
.after(methodStepContainer.append(
$(document.createElement("h5"))
.append("Step ", $(document.createElement("span")).addClass("step-num").text(nextStepNum)),
this.renderTextArea(null, {
category: "methodStepDescription",
type: "description",
classes: "new"
}),
$(document.createElement("i")).addClass("icon icon-remove remove hidden")
));
},
/*
* Remove this method step
*/
removeMethodStep: function(e){
//Get the index of this step
var stepEl = $(e.target).parent(".step-container").find(".method-step"),
index = this.$(".method-step").index(stepEl),
view = this;
//Remove this step from the model
this.model.set("methodStepDescription", _.without(this.model.get("methodStepDescription"), this.model.get("methodStepDescription")[index]));
//If this was the last step to be removed, and the rest of the EMLMethods
// model is empty, then remove the model from the parent EML model
if( this.model.isEmpty() ){
//Get the parent EML model
var parentEML = this.model.get("parentModel");
//Make sure this model type is EML211
if( parentEML && parentEML.type == "EML" ){
//If the methods are an array,
if( Array.isArray(parentEML.get("methods")) ){
//remove this EMLMethods model from the array
parentEML.set( "methods", _.without(parentEML.get("methods"), this.model) );
}
else{
//If the methods attribute is set to this EMLMethods model,
// then just set it back to it's default
if( parentEML.get("methods") == this.model )
parentEML.set("methods", parentEML.defaults().methods);
}
}
}
//Remove the step elements from the page
stepEl.parent(".step-container").slideUp("fast", function(){
this.remove();
//Bump down all the step numbers
var stepNums = view.$(".step-num");
for(var i=index; i < stepNums.length; i++){
$(stepNums[i]).text(i+1);
}
});
},
previewRemove: function(e){
$(e.target).parents(".step-container").toggleClass("remove-preview");
}
});
return EMLMethodsView;
});