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://github.com/NCEAS/eml/blob/master/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; } );