-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add models, views, collections for Missing Values
- Enables entering missing value codes in the Attribute editor - Works but lacks styling & unit tests Issue #612
- Loading branch information
Showing
7 changed files
with
668 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
"use strict"; | ||
|
||
define(["backbone", "models/metadata/eml211/EMLMissingValueCode"], function ( | ||
Backbone, | ||
EMLMissingValueCode | ||
) { | ||
/** | ||
* @class EMLMissingValueCodes | ||
* @classdesc A collection of EMLMissingValueCodes. | ||
* @classcategory Collections/Metadata/EML | ||
* @since x.x.x | ||
*/ | ||
var EMLMissingValueCodes = Backbone.Collection.extend( | ||
/** @lends EMLMissingValueCodes.prototype */ | ||
{ | ||
/** | ||
* The reference to the model class that this collection is made of. | ||
* @type {Backbone.Model} | ||
*/ | ||
model: EMLMissingValueCode, | ||
|
||
/** | ||
* Parse the incoming XML nodes | ||
* @param {jQuery|Element} objectDOM - The XML DOM element that represents | ||
*/ | ||
parse: function (objectDOM) { | ||
const collection = this; | ||
|
||
if (!objectDOM) return; | ||
const $objectDOM = $(objectDOM); | ||
|
||
// Loop through each missingValueCode node | ||
const opts = { parse: true }; | ||
for (var i = 0; i < $objectDOM.length; i++) { | ||
const missingValueCodeNode = $objectDOM[i]; | ||
// Create a new missingValueCode model & add it to the collection | ||
const attrs = { objectDOM: missingValueCodeNode }; | ||
const missingValueCode = new EMLMissingValueCode(attrs, opts); | ||
collection.add(missingValueCode); | ||
} | ||
|
||
return collection; | ||
}, | ||
|
||
/** | ||
* Update the DOM with the current model state for each model in the | ||
* collection, then return the set of updated DOMs. Warning: this will | ||
* remove any empty models from the collection. | ||
* @returns {Element[]} An array of updated DOM elements | ||
*/ | ||
updateDOM: function () { | ||
this.removeEmptyModels(); | ||
const objectDOMs = this.map((model) => model.updateDOM()); | ||
return objectDOMs; | ||
}, | ||
|
||
/** | ||
* Remove any empty models from the collection | ||
*/ | ||
removeEmptyModels: function () { | ||
this.remove(this.filter((model) => model.isEmpty())); | ||
}, | ||
|
||
/** | ||
* Validate the collection of missing value codes. This will remove any | ||
* empty models from the collection. | ||
* @returns {Array} An array of error messages | ||
*/ | ||
validate: function () { | ||
this.removeEmptyModels(); | ||
const errors = []; | ||
this.forEach((model) => { | ||
if (!model.isValid()) { | ||
errors.push(model.validationError); | ||
} | ||
}); | ||
return errors.length ? errors : null; | ||
}, | ||
} | ||
); | ||
|
||
return EMLMissingValueCodes; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
define(["backbone"], function (Backbone) { | ||
/** | ||
* @class EMLMissingValueCode | ||
* @classdesc A missing value code is a code that is used to indicate | ||
* that a value is missing from the data. | ||
* @see https://eml.ecoinformatics.org/schema/eml-attribute_xsd.html | ||
* @classcategory Models/Metadata/EML211 | ||
* @since x.x.x | ||
*/ | ||
var EMLMissingValueCode = Backbone.Model.extend( | ||
/** @lends EMLMissingValueCode.prototype */ { | ||
/** | ||
* The default attributes for an EMLMissingValueCode model. | ||
* @returns {object} The default attributes | ||
* @property {string} type - The element type in the DOM | ||
* @property {string} code - The missing value code | ||
* @property {string} codeExplanation - The explanation for the missing value code | ||
* @property {string[]} nodeOrder - The order of the EML nodes in this object | ||
*/ | ||
defaults: function () { | ||
return { | ||
type: "missingValueCode", | ||
code: "", | ||
codeExplanation: "", | ||
nodeOrder: ["code", "codeExplanation"], | ||
}; | ||
}, | ||
|
||
/* | ||
* Parse the incoming attribute's XML elements. | ||
*/ | ||
parse: function (attributes, options) { | ||
if (!attributes) return {}; | ||
const objectDOM = attributes.objectDOM || attributes.objectXML; | ||
if (!objectDOM) return {}; | ||
const $objectDOM = $(objectDOM); | ||
|
||
this.defaults().nodeOrder.forEach((node) => { | ||
attributes[node] = $objectDOM.children(node.toLowerCase()).text(); | ||
}); | ||
|
||
attributes.objectDOM = $objectDOM[0]; | ||
return attributes; | ||
}, | ||
|
||
/** | ||
* Create an XML string from the model's attributes. | ||
* @return {string} The XML string | ||
*/ | ||
serialize: function () { | ||
const xml = this.updateDOM().outerHTML; | ||
const nodes = this.get("nodeOrder"); | ||
// replace lowercase node names with camelCase | ||
nodes.forEach((node) => { | ||
xml.replace(`<${node.toLowerCase()}>`, `<${node}>`); | ||
xml.replace(`</${node.toLowerCase()}>`, `</${node}>`); | ||
}); | ||
return xml; | ||
}, | ||
|
||
/** | ||
* Copy the original XML and update fields in a DOM object | ||
* @param {object} objectDOM - The DOM object to update | ||
*/ | ||
updateDOM: function (objectDOM) { | ||
const type = this.get("type") || "missingValueCode"; | ||
if (!objectDOM) { | ||
objectDOM = this.get("objectDOM") || this.get("objectXML"); | ||
} | ||
if (!objectDOM) { | ||
objectDOM = document.createElement(type); | ||
} | ||
const $objectDOM = $(objectDOM); | ||
|
||
this.get("nodeOrder").forEach((nodeName) => { | ||
// Remove any existing nodes | ||
$objectDOM.children(nodeName.toLowerCase()).remove(); | ||
|
||
const newValue = this.get(nodeName)?.trim(); | ||
|
||
// Add the new node | ||
if (newValue) { | ||
const node = document.createElement(nodeName); | ||
$(node).text(newValue); | ||
$objectDOM.append(node); | ||
} | ||
}); | ||
|
||
return $objectDOM[0]; | ||
}, | ||
|
||
/** | ||
* Return true if all of the model's attributes are empty | ||
* @return {boolean} | ||
*/ | ||
isEmpty: function () { | ||
return !this.get("code") && !this.get("codeExplanation"); | ||
}, | ||
|
||
/** | ||
* Validate the model attributes | ||
* @return {object} The validation errors, if any | ||
*/ | ||
validate: function () { | ||
if (this.isEmpty()) return undefined; | ||
|
||
const errors = []; | ||
|
||
// Need a code and an explanation. Both must be non-empty strings. | ||
let code = this.get("code"); | ||
let codeExplanation = this.get("codeExplanation"); | ||
if ( | ||
!code || | ||
!codeExplanation || | ||
typeof code !== "string" || | ||
typeof codeExplanation !== "string" | ||
) { | ||
errors.missingValueCode = | ||
"Missing value code and explanation are required."; | ||
return errors; | ||
} | ||
code = code.trim(); | ||
codeExplanation = codeExplanation.trim(); | ||
this.set("code", code); | ||
this.set("codeExplanation", codeExplanation); | ||
|
||
// Code must be a non-empty string | ||
if (!code || !codeExplanation) { | ||
errors.missingValueCode = | ||
"Missing value code and explanation are required."; | ||
return errors; | ||
} | ||
|
||
return errors.length > 0 ? errors : undefined; | ||
}, | ||
} | ||
); | ||
|
||
return EMLMissingValueCode; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.