define(["jquery", "underscore", "backbone", "models/metadata/eml211/EMLEntity"],
function($, _, Backbone, EMLEntity) {
/**
* @class EMLDataTable
* @classdesc EMLDataTable represents a tabular data entity, corresponding
* with the EML dataTable module.
* @classcategory Models/Metadata/EML211
* @see https://eml.ecoinformatics.org/schema/eml-datatable_xsd
*/
var EMLDataTable = EMLEntity.extend(
/** @lends EMLDataTable.prototype */{
//The class name for this model
type: "EMLDataTable",
/* Attributes of any entity */
defaults: function(){
return _.extend({
/* Attributes from EML */
caseSensitive: null, // The case sensitivity of the table records
numberOfRecords: null, // the number of records in the table
type: "dataTable",
/* Attributes not from EML */
nodeOrder: [ // The order of the top level XML element nodes
"caseSensitive",
"numberOfRecords",
"references"
],
}, EMLEntity.prototype.defaults());
},
/*
* The map of lower case to camel case node names
* needed to deal with parsing issues with $.parseHTML().
* Use this until we can figure out issues with $.parseXML().
*/
nodeNameMap: _.extend({
"casesensitive" : "caseSensitive",
"numberofrecords": "numberOfRecords"
}, EMLEntity.prototype.nodeNameMap),
/* Initialize an EMLDataTable object */
initialize: function(attributes) {
// if options.parse = true, Backbone will call parse()
// Call super() first
this.constructor.__super__.initialize.apply(this, [attributes]);
// EMLDataTable-specific work
this.set("type", "dataTable", {silent: true});
// Register change events
this.on( "change:caseSensitive change:numberOfRecords", EMLEntity.trickleUpChange);
},
/*
* Parse the incoming other entity's XML elements
*/
parse: function(attributes, options) {
var attributes = attributes || {};
// Call super() first
attributes = this.constructor.__super__.parse.apply(this, [attributes, options]);
// EMLDataTable-specific work
var objectXML = attributes.objectXML; // The dataTable XML fragment
var objectDOM; // The W3C DOM of the object XML fragment
var $objectDOM; // The JQuery object of the XML fragment
// Use the updated objectDOM if we have it
if ( attributes.objectDOM ) {
$objectDOM = $(attributes.objectDOM);
} else {
// Hmm, oddly not there, start from scratch =/
$objectDOM = $(objectXML);
}
// Add the caseSensitive
attributes.caseSensitive = $objectDOM.children("caseSensitive").text();
// Add the numberOfRecords
attributes.numberOfRecords = $objectDOM.children("numberOfRecords").text();
// Add the references value
attributes.references = $objectDOM.children("references").text();
return attributes;
},
/* Copy the original XML and update fields in a DOM object */
updateDOM: function(objectDOM) {
var nodeToInsertAfter;
var type = this.get("type") || "dataTable";
if ( ! objectDOM ) {
objectDOM = this.get("objectDOM");
}
var objectXML = this.get("objectXML");
// If present, use the cached DOM
if ( objectDOM ) {
objectDOM = objectDOM.cloneNode(true);
// otherwise, use the cached XML
} else if ( objectXML ){
objectDOM = $(objectXML)[0].cloneNode(true);
// This is new, create it
} else {
objectDOM = document.createElement(type);
}
// Now call the superclass
objectDOM = this.constructor.__super__.updateDOM.apply(this, [objectDOM]);
// And then update the EMLDataTable-specific fields
// Update the caseSensitive field
if ( this.get("caseSensitive") ) {
if ( $(objectDOM).find("caseSensitive").length ) {
$(objectDOM).find("caseSensitive").text(this.get("caseSensitive"));
} else {
nodeToInsertAfter = this.getEMLPosition(objectDOM, "caseSensitive");
if ( ! nodeToInsertAfter ) {
$(objectDOM).append($(document.createElement("casesensitive"))
.text(this.get("caseSensitive"))[0]);
} else {
$(nodeToInsertAfter).after($(document.createElement("casesensitive"))
.text(this.get("caseSensitive"))[0]);
}
}
}
// Update the numberOfRecords field
if ( this.get("numberOfRecords") ) {
if ( $(objectDOM).find("numberOfRecords").length ) {
$(objectDOM).find("numberOfRecords").text(this.get("numberOfRecords"));
} else {
nodeToInsertAfter = this.getEMLPosition(objectDOM, "numberOfRecords");
if ( ! nodeToInsertAfter ) {
$(objectDOM).append($(document.createElement("numberofrecords"))
.text(this.get("numberOfRecords"))[0]);
} else {
$(nodeToInsertAfter).after($(document.createElement("numberofrecords"))
.text(this.get("numberOfRecords"))[0]);
}
}
}
return objectDOM;
},
/* Serialize the EML DOM to XML */
serialize: function() {
var xmlString = "";
// Update the superclass fields in the objectDOM first
var objectDOM = this.constructor.__super__.updateDOM.apply(this, []);
// Then update the subclass fields in the objectDOM
// TODO
this.set("objectXML", xmlString);
return xmlString;
},
/* Validate the datable's required fields */
validate: function(){
var errors = {};
// Require the entity name
if( !this.get("entityName") ) {
errors.entityName = "Please specify an data table name.";
}
//Validate the attributes
var attributeErrors = this.validateAttributes();
if(attributeErrors.length)
errors.attributeList = errors;
// Require the attribute list
/*if( !this.get("attributeList").length ) {
errors.attributeList = "Please describe the table attributes (columns).";
}*/
if( Object.keys(errors).length ){
return errors;
}
else{
return false;
}
},
/*
* Climbs up the model heirarchy until it finds the EML model
*
* @return {EML211 or false} - Returns the EML 211 Model or false if not found
*/
getParentEML: function(){
var emlModel = this.get("parentModel"),
tries = 0;
while (emlModel.type !== "EML" && tries < 6){
emlModel = emlModel.get("parentModel");
tries++;
}
if( emlModel && emlModel.type == "EML")
return emlModel;
else
return false;
}
});
return EMLDataTable;
}
);