1 /** @module utility-functions */ 2 define(['underscore'], function(_) { 3 /** 4 * 5 * Sorting function that deals with alpha and numeric elements. 6 * 7 * @param {String[]} list A list of strings to sort 8 * 9 * @return {String[]} The sorted list of strings 10 * @function naturalSort 11 */ 12 function naturalSort(list) { 13 var numericPart = [], alphaPart = [], result = []; 14 15 // separate the numeric and the alpha elements of the array 16 // Note that NaN and +/- Infinity are not considered numeric elements 17 for (var index = 0; index < list.length; index++) { 18 var valAsFloat = parseFloat(list[index]); 19 if (isNaN(valAsFloat) || !isFinite(valAsFloat)) { 20 alphaPart.push(list[index]); 21 } 22 else { 23 numericPart.push(list[index]); 24 } 25 } 26 27 // ignore casing of the strings, taken from: 28 // http://stackoverflow.com/a/9645447/379593 29 alphaPart.sort(function(a, b) { 30 return a.toLowerCase().localeCompare(b.toLowerCase()); 31 }); 32 33 // sort in ascending order 34 numericPart.sort(function(a, b) {return parseFloat(a) - parseFloat(b)}); 35 36 return result.concat(alphaPart, numericPart); 37 } 38 39 40 /** 41 * 42 * Utility function that splits the lineage into taxonomic levels 43 * and returns the taxonomic level specified 44 * 45 * @param {String} lineage The taxonomic string, with levels seperated by 46 * semicolons. 47 * @param {Integer} levelIndex The taxonomic level to truncate to. 48 * 1 = Kingdom, 2 = Phylum, etc. 49 * 50 * @return {String} The taxonomic string truncated to desired level. 51 * @function truncateLevel 52 */ 53 function truncateLevel(lineage, levelIndex) { 54 if (levelIndex === 0) { 55 return lineage; 56 } 57 var levels = lineage.split(';'); 58 var taxaLabel = ''; 59 for (var i = 0; (i < levelIndex && i < levels.length); i++) { 60 var level = levels[i]; 61 if (level[level.length - 1] == '_') { 62 taxaLabel += ';' + level; 63 }else { 64 taxaLabel = level; 65 } 66 } 67 return taxaLabel; 68 } 69 70 /** 71 * 72 * Utility function to convert an XML DOM documents to a string useful for 73 * unit testing. This code is based on 74 * [this SO answer]{@link http://stackoverflow.com/a/1750890} 75 * 76 * @param {Node} node XML DOM object, usually as created by the document 77 * object. 78 * 79 * @return {String} Representation of the node object. 80 * @function convertXMLToString 81 */ 82 function convertXMLToString(node) { 83 if (typeof(XMLSerializer) !== 'undefined') { 84 var serializer = new XMLSerializer(); 85 return serializer.serializeToString(node); 86 } 87 else if (node.xml) { 88 return node.xml; 89 } 90 } 91 92 /** 93 * 94 * Split list of string values into numeric and non-numeric values 95 * 96 * @param {String[]} values The values to check 97 * @return {Object} Object with two keys, `numeric` and `nonNumeric`. 98 * `numeric` holds an array of all numeric values found. `nonNumeric` holds 99 * an array of the remaining values. 100 */ 101 function splitNumericValues(values) { 102 var numeric = []; 103 var nonNumeric = []; 104 _.each(values, function(element) { 105 // http://stackoverflow.com/a/9716488 106 if (!isNaN(parseFloat(element)) && isFinite(element)) { 107 numeric.push(element); 108 } 109 else { 110 nonNumeric.push(element); 111 } 112 }); 113 return {numeric: numeric, nonNumeric: nonNumeric}; 114 } 115 116 /** 117 * 118 * Escape special characters in a string for use in a regular expression. 119 * Credits go to [this SO answer]{@link http://stackoverflow.com/a/5306111} 120 * 121 * @param {String} regex string to escape for use in a regular expression. 122 * 123 * @return {String} String with escaped characters for use in a regular 124 * expression. 125 * @function escapeRegularExpression 126 */ 127 function escapeRegularExpression(regex) { 128 return regex.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 129 } 130 131 /** 132 * 133 * Clean a string in HTML formatted strings that get created with the 134 * namespace tag in some browsers and not in others. Intended to facilitate 135 * testing. 136 * 137 * @param {String} htmlString string to remove namespace from. 138 * 139 * @return {String} String without namespace. 140 * @function cleanHTML 141 */ 142 function cleanHTML(htmlString) { 143 return htmlString.replace(' xmlns="http://www.w3.org/1999/xhtml"', ''); 144 } 145 146 return {'truncateLevel': truncateLevel, 'naturalSort': naturalSort, 147 'convertXMLToString': convertXMLToString, 148 'escapeRegularExpression': escapeRegularExpression, 149 'cleanHTML': cleanHTML, 'splitNumericValues': splitNumericValues}; 150 }); 151