if (typeof morpheus === 'undefined') {
morpheus = {};
}
morpheus.Util = function() {
};
morpheus.Util.URL = 'https://www.broadinstitute.org/cancer/software/morpheus/';
morpheus.Util.RIGHT_ARROW = String.fromCharCode(8594);
/**
* Add properties in c2 to c1
*
* @param {Object}
* c1 The object that will inherit from obj2
* @param {Object}
* c2 The object that obj1 inherits from
*/
morpheus.Util.extend = function(c1, c2) {
for ( var key in c2.prototype) {
if (!(key in c1.prototype)) {
c1.prototype[key] = c2.prototype[key];
}
}
};
morpheus.Util.viewPortSize = function() {
return window.getComputedStyle(document.body, ':before').content.replace(
/"/g, '');
};
morpheus.Util.TRACKING_CODE_LOADED = false;
morpheus.Util.loadTrackingCode = function() {
if (typeof window !== 'undefined') {
if (morpheus.Util.TRACKING_CODE_LOADED) {
return;
}
(function(i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function() {
(i[r].q = i[r].q || []).push(arguments);
}, i[r].l = 1 * new Date();
a = s.createElement(o), m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, 'script',
'//www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-53973555-1', 'auto', 'morpheus');
ga('morpheus.send', 'pageview');
morpheus.Util.TRACKING_CODE_LOADED = true;
}
};
morpheus.Util.trackEvent = function(options) {
if (typeof window !== 'undefined') {
if (!morpheus.Util.TRACKING_CODE_LOADED) {
morpheus.Util.loadTrackingCode();
}
if (morpheus.Util.TRACKING_CODE_LOADED) {
ga('morpheus.send', {
hitType : 'event',
eventCategory : options.eventCategory,
eventAction : options.eventAction,
eventLabel : options.eventLabel
});
}
}
};
/**
* Trims leading and trailing whitespace from a string.
*/
morpheus.Util.trim = function(val) {
var len = val.length;
var st = 0;
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < val.length)) ? val.substring(st, len) : val;
};
/**
* Checks whether supplied argument is an array
*/
morpheus.Util.isArray = function(array) {
var types = [ Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array,
Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, ];
// handle native arrays
for (var i = 0, length = types.length; i < length; i++) {
if (array instanceof types[i]) {
return true;
}
}
return false;
};
morpheus.Util.getWindowSearchObject = function() {
var searchObject = {};
var hashObject = {};
if (window.location.search.length > 0) {
searchObject = morpheus.Util.getQueryParams(window.location.search
.substring(1));
}
if (window.location.hash.length > 0) {
hashObject = morpheus.Util.getQueryParams(window.location.hash
.substring(1));
}
return _.extend(hashObject, searchObject);
};
morpheus.Util.getQueryParams = function(s) {
var params = {};
if (!s) {
return params;
}
var search = unescape(s);
var keyValuePairs = search.split('&');
for (var i = 0; i < keyValuePairs.length; i++) {
var pair = keyValuePairs[i].split('=');
var array = params[pair[0]];
if (array === undefined) {
array = [];
params[pair[0]] = array;
}
array.push(pair[1]);
}
return params;
};
morpheus.Util.getScriptPath = function() {
var scripts = document.getElementsByTagName('script');
for (var i = 0; i < scripts.length; i++) {
var src = scripts[i].src;
var index = src.lastIndexOf('/');
if (index !== -1) {
src = src.substring(index);
}
if (src.indexOf('morpheus') !== -1 && src.indexOf('external') === -1) {
return scripts[i].src;
}
}
return scripts.length > 0 ? scripts[0].src : '';
};
morpheus.Util.forceDelete = function(obj) {
try {
var _garbageCollector = (function() {
var ef = URL.createObjectURL(new Blob([ '' ], {
type : 'text/javascript'
})), w = new Worker(ef);
URL.revokeObjectURL(ef);
return w;
})();
_garbageCollector.postMessage(obj, [ obj ]);
} catch (x) {
console.log('Unable to delete');
}
};
morpheus.Util.getFileName = function(fileOrUrl) {
var name = fileOrUrl instanceof File ? fileOrUrl.name : fileOrUrl;
name = '' + name;
var slash = name.lastIndexOf('/');
if (slash !== -1 && slash < name.length - 1) {
// https://s3.amazonaws.com/appdata.cmap.org/icv/dosval/BRD-K45711268_10_UM_24_H/pcl_cell.gct?AWSAccessKeyId=AKIAJZQISWLUKFS3VUKA&Expires=1455761050&Signature=HVle9MvXV3OGRZHOngdm2frqER8%3D
name = name.substring(slash + 1); // get stuff after slash
var question = name.indexOf('?');
if (question !== -1 && name.length > (question + 1)) {
name = name.substring(0, question);
var params = name.substring(question + 1);
var keyValuePairs = decodeURIComponent(params).split('&');
// check for parameters in name
for (var i = 0; i < keyValuePairs.length; i++) {
var pair = keyValuePairs[i].split('=');
if (pair[0] === 'file' || pair[0] === 'name') {
name = pair[1];
break;
}
}
}
}
return name;
};
morpheus.Util.prefixWithZero = function(value) {
return value < 10 ? '0' + value : value;
};
morpheus.Util.getExtension = function(name) {
var dotIndex = name.lastIndexOf('.');
if (dotIndex > 0) {
var suffix = name.substring(dotIndex + 1).toLowerCase();
if (suffix === 'txt' || suffix === 'gz') { // see if file is in
// the form
// name.gct.txt
var newPath = name.substring(0, dotIndex);
var secondDotIndex = newPath.lastIndexOf('.');
if (secondDotIndex > 0) {// see if file has another suffix
var secondSuffix = newPath.substring(secondDotIndex + 1,
newPath.length).toLowerCase();
if (secondSuffix === 'segtab' || secondSuffix === 'seg'
|| secondSuffix === 'maf' || secondSuffix === 'gct'
|| secondSuffix === 'txt' || secondSuffix === 'gmt') {
return secondSuffix;
}
}
}
return suffix;
}
return '';
};
/**
* Gets the base file name. For example, if name is 'test.txt' the method
* returns the string 'test'. If the name is 'test.txt.gz', the method also
* returns the string 'test'.
*
* @param name
* The file name.
* @return The base file name.
*/
morpheus.Util.getBaseFileName = function(name) {
var dotIndex = name.lastIndexOf('.');
if (dotIndex > 0) {
var suffix = name.substring(dotIndex + 1, name.length);
if (suffix === 'gz' || suffix === 'zip' || suffix === 'bz2') {
return morpheus.Util.getBaseFileName(name.substring(0, dotIndex));
}
return name.substring(0, dotIndex);
}
return name;
};
morpheus.Util.seq = function(length) {
var array = [];
for (var i = 0; i < length; i++) {
array.push(i);
}
return array;
};
morpheus.Util.sequ32 = function(length) {
var array = new Uint32Array(length);
for (var i = 0; i < length; i++) {
array[i] = i;
}
return array;
};
/**
* Converts window hash or search to an object that maps keys to an array of
* values. For example ?foo=bar returns {foo:[bar]}
*/
morpheus.Util.paramsToObject = function(hash) {
var search = hash ? window.location.hash : window.location.search;
if (search.length <= 1) {
return {};
}
search = unescape(search);
var keyValuePairs = search.substring(1).split('&');
var result = {};
for (var i = 0, length = keyValuePairs.length; i < length; i++) {
var pair = keyValuePairs[i].split('=');
var values = result[pair[0]];
if (values === undefined) {
values = [];
result[pair[0]] = values;
}
values.push(pair[1]);
}
return result;
};
morpheus.Util.endsWith = function(string, suffix) {
return string.length >= suffix.length
&& string.substr(string.length - suffix.length) === suffix;
};
morpheus.Util.measureSvgText = function(text, classname) {
if (!text || text.length === 0)
return {
height : 0,
width : 0
};
var container = d3.select('body').append('svg');
if (classname) {
container.attr('class', classname);
}
container.append('text').attr({
x : -1000,
y : -1000
}).text(text);
var bbox = container.node().getBBox();
container.remove();
return {
height : bbox.height,
width : bbox.width
};
};
morpheus.Util.IS_MAC = false;
if (typeof navigator !== 'undefined') {
morpheus.Util.IS_MAC = navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) ? true
: false;
}
morpheus.Util.hammer = function(el, recognizers) {
var hammer = new Hammer(el, {
recognizers : []
});
if (_.indexOf(recognizers, 'pan') !== -1) {
hammer.add(new Hammer.Pan({
threshold : 1,
direction : Hammer.DIRECTION_ALL
}));
} else if (_.indexOf(recognizers, 'panh') !== -1) {
hammer.add(new Hammer.Pan({
threshold : 1,
direction : Hammer.DIRECTION_HORIZONTAL
}));
} else if (_.indexOf(recognizers, 'panv') !== -1) {
hammer.add(new Hammer.Pan({
threshold : 1,
direction : Hammer.DIRECTION_VERTICAL
}));
}
if (_.indexOf(recognizers, 'tap') !== -1) {
// var singleTap = new Hammer.Tap({
// event : 'singletap',
// interval : 50
// });
// var doubleTap = new Hammer.Tap({
// event : 'doubletap',
// taps : 2
// });
// doubleTap.recognizeWith(singleTap);
// singleTap.requireFailure([ doubleTap ]);
// hammer.add([ doubleTap, singleTap ]);
hammer.add(new Hammer.Tap());
}
if (_.indexOf(recognizers, 'pinch') !== -1) {
hammer.add(new Hammer.Pinch());
}
if (_.indexOf(recognizers, 'longpress') !== -1) {
hammer.add(new Hammer.Press({
event : 'longpress',
time : 1000
}));
}
if (_.indexOf(recognizers, 'press') !== -1) {
hammer.add(new Hammer.Press());
}
// $(el).on('mousedown', function(e) {
// // e.preventDefault();
// // e.stopPropagation();
// // e.stopImmediatePropagation();
// });
return hammer;
};
morpheus.Util.autocompleteArrayMatcher = function(q, cb, array, fields, max) {
var filteredSet = new morpheus.Set();
// an array that will be populated with substring matches
// regex used to determine if a string starts with substring `q`
var substrRegex = new RegExp('^' + q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
if (fields) {
var nfields = fields.length;
for (var i = 0, n = array.length; i < n; i++) {
var item = array[i];
for (var j = 0; j < nfields; j++) {
var field = fields[j];
var value = item[field];
if (substrRegex.test(value)) {
filteredSet.add(value);
break;
}
}
if (filteredSet.size() === max) {
break;
}
}
} else {
for (var i = 0, n = array.length; i < n; i++) {
var value = array[i];
if (substrRegex.test(value)) {
filteredSet.add(value);
}
if (filteredSet.size() === max) {
break;
}
}
}
cb(filteredSet.values());
};
/**
* @param {Number}
* [options.delay=500] - Delay to short autosuggestions.
* @param {jQuery}
* options.$el - Text box to apply autosuggest to.
* @param {Function}
* options.filter - Callback to invoke to filter a suggested term.
* Invoked with array of tokens and response.
* @param {Function}
* options.select - Callback to invoke when a suggested term is
* selected.
* @param {Boolean}
* [options.multi=true] - Whether to allow more than one search term.
* @param {Boolean}
* [options.suggestWhenEmpty=true] - Whether to autosuggest terms
* when text field is empty.
*
*/
morpheus.Util.autosuggest = function(options) {
var fieldRegExp = /:/g;
options = $.extend({}, {
multi : true,
delay : 500,
suggestWhenEmpty : true,
}, options);
options.$el
// don't navigate away from the field on tab when selecting an item
.on(
'keydown',
function(event) {
if ((event.keyCode === $.ui.keyCode.TAB)
&& $(this).data('ui-autocomplete').menu.active) {
event.preventDefault();
}
}).autocomplete({
minLength : 1,
delay : options.delay,
source : function(request, response) {
// delegate back to autocomplete, but extract the last term
var terms = morpheus.Util.getAutocompleteTokens(request.term);
if (options.suggestWhenEmpty || terms.length > 0) {
options.filter(terms, response);
}
},
focus : function() {
// prevent value inserted on focus
return false;
},
select : function(event, ui) {
if (options.multi) {
var terms = morpheus.Util.getAutocompleteTokens(this.value);
// remove the current input
terms.pop();
// add the selected item
var val = ui.item.value;
// if ((val.indexOf(' ') > 0 && val[0] !== '"')) {
// val = '"' + val + '"'; // quote
// }
// val = val.replace(fieldRegExp, '\\:'); // TODO escape field
// separators
terms.push(val);
this.value = terms.join(' ');
if (options.select) {
options.select();
}
$(this).autocomplete('close');
return false;
} else if (options.select) {
options.select();
$(this).autocomplete('close');
}
if (event.which === 13) {
event.stopImmediatePropagation();
}
}
});
// use html for label instead of default text
options.$el.autocomplete('instance')._renderItem = function(ul, item) {
return $('
').html(item.label).appendTo(ul);
};
if (options.suggestWhenEmpty) {
options.$el.on('focus', function() {
if ($.trim(options.$el.val()) === '') {
options.$el.autocomplete('search', ' ');
}
});
}
options.$el.on('keyup', function(e) {
if (e.which === 13) {
options.$el.autocomplete('close');
} else if (options.suggestWhenEmpty) {
if (options.$el.val() === '') {
options.$el.autocomplete('search', ' ');
}
}
});
};
/**
* @deprecated
*/
morpheus.Util.autocomplete = function($el, filterFunction, selectCb,
singleTerm, autoclose) {
var fieldRegExp = /:/g;
$el
// don't navigate away from the field on tab when selecting an item
.on(
'keydown',
function(event) {
if ((event.keyCode === $.ui.keyCode.TAB)
&& $(this).data('ui-autocomplete').menu.active) {
event.preventDefault();
}
}).autocomplete({
minLength : 1,
delay : 1200,
source : function(request, response) {
// delegate back to autocomplete, but extract the last term
var terms = morpheus.Util.getAutocompleteTokens(request.term);
if (terms.length > 0) {
filterFunction(terms.pop(), response);
}
},
focus : function() {
// prevent value inserted on focus
return false;
},
select : function(event, ui) {
if (!singleTerm) {
var terms = morpheus.Util.getAutocompleteTokens(this.value);
// remove the current input
terms.pop();
// add the selected item
var val = ui.item.value;
if (val.indexOf(' ') > 0 && val[0] !== '"') {
val = '"' + val + '"'; // quote
}
// val = val.replace(fieldRegExp, '\\:'); // escape field
// separators
terms.push(val);
this.value = terms.join(' ');
if (selectCb) {
selectCb();
}
$(this).autocomplete('close');
return false;
} else if (selectCb) {
selectCb();
$(this).autocomplete('close');
}
}
});
// use html for label instead of default text
$el.autocomplete('instance')._renderItem = function(ul, item) {
return $('').html(item.label).appendTo(ul);
};
if (autoclose) {
$el.on('keyup', function(e) {
if (e.which === 13) {
$el.autocomplete('close');
}
});
}
};
morpheus.Util.showDialog = function($el, title, options) {
var $dialog = $('');
$el.appendTo($dialog);
$dialog.appendTo($(document.body));
if (!options) {
options = {};
}
$dialog.dialog({
width : 670,
height : 590,
title : title,
// resizeStop : function(event, ui) {
// var w = parseInt($dialog.width());
// var h = parseInt($dialog.height());
// //var d = Math.min(w, h);
// svg.attr("width", w - 50);
// svg.attr("height", h - 50);
// chart.update();
// },
close : function(event, ui) {
$dialog.remove();
if (options.close) {
options.close();
}
}
});
};
/**
* @param sheet
* An xlsx sheet
* @param delim
* If a delim is specified each row, will contain a string separated
* by delim. Otherwise each row will contain an array.
*/
morpheus.Util.sheetToArray = function(sheet, delim) {
var r = XLSX.utils.decode_range(sheet['!ref']);
var rows = [];
for (var R = r.s.r; R <= r.e.r; ++R) {
var row = [];
for (var C = r.s.c; C <= r.e.c; ++C) {
var val = sheet[XLSX.utils.encode_cell({
c : C,
r : R
})];
if (!val) {
row.push('');
continue;
}
var txt = String(XLSX.utils.format_cell(val));
row.push(txt);
}
rows.push(delim ? row.join(delim) : row);
}
return rows;
};
morpheus.Util.linesToObjects = function(lines) {
var header = lines[0];
var array = [];
var nfields = header.length;
for (var i = 1, length = lines.length; i < length; i++) {
var line = lines[i];
var obj = {};
for (var f = 0; f < nfields; f++) {
var value = line[f];
var field = header[f];
obj[field] = value;
}
array.push(obj);
}
return array;
};
morpheus.Util.xlsxTo2dArray = function(data) {
var workbook = XLSX.read(data, {
type : 'binary',
cellFormula : false,
cellHTML : false
});
var sheetNames = workbook.SheetNames;
var worksheet = workbook.Sheets[sheetNames[0]];
var lines = morpheus.Util.sheetToArray(worksheet);
return lines;
};
morpheus.Util.xlsxTo1dArray = function(data) {
var workbook = XLSX.read(data, {
type : 'binary',
cellFormula : false,
cellHTML : false
});
var sheetNames = workbook.SheetNames;
var worksheet = workbook.Sheets[sheetNames[0]];
var lines = morpheus.Util.sheetToArray(worksheet, '\t');
return lines;
};
morpheus.Util.hashCode = function(val) {
var h = 0;
if (val.length > 0) {
for (var i = 0; i < val.length; i++) {
h = 31 * h + val.charCodeAt(i);
}
}
return h;
};
/**
* Returns a promise that resolves to a string
*/
morpheus.Util.getText = function(urlOrFile) {
var deferred = $.Deferred();
if (_.isString(urlOrFile)) {
$.ajax({
contentType : 'text/plain',
url : urlOrFile,
}).done(function(text, status, xhr) {
// var type = xhr.getResponseHeader('Content-Type');
deferred.resolve(text);
});
} else if (urlOrFile instanceof File) {
var reader = new FileReader();
reader.onload = function(event) {
deferred.resolve(event.target.result);
};
reader.readAsText(urlOrFile);
} else {
// what is urlOrFile?
deferred.resolve(urlOrFile);
}
return deferred.promise();
};
morpheus.Util.createOptions = function(values, none) {
var html = [];
if (none) {
html.push('');
}
_.each(values, function(val) {
html.push('');
});
return html.join('');
};
/**
* Computes the rank using the given index array. The index array can be
* obtained from the morpheus.Util.indexSort method. Does not handle ties.
*
* @param index
* @return The ranks.
*/
morpheus.Util.rankIndexArray = function(index) {
var rank = [];
var n = index.length;
for (var j = 0; j < n; j++) {
rank[index[j]] = j + 1;
}
return rank;
};
morpheus.Util.indexSort = function(array, ascending) {
var pairs = [];
array.forEach(function(value, index) {
pairs.push({
value : value,
index : index
});
});
return morpheus.Util.indexSortPairs(pairs, ascending);
};
morpheus.Util.indexSortPairs = function(array, ascending) {
if (ascending) {
array.sort(function(a, b) {
return (a.value < b.value ? -1 : (a.value === b.value ? 0 : 1));
});
} else {
array.sort(function(a, b) {
return (a.value < b.value ? 1 : (a.value === b.value ? 0 : -1));
});
}
var indices = [];
array.forEach(function(item) {
indices.push(item.index);
});
return indices;
};
morpheus.Util.arrayEquals = function(array1, array2, comparator) {
if (array1 == array2)
return true;
if (array1 == null || array2 == null) {
return false;
}
if (!comparator) {
comparator = function(a, b) {
return a === b;
};
}
var length = array1.length;
if (array2.length !== length) {
return false;
}
for (var i = 0; i < length; i++) {
if (!comparator(array1[i], array2[i])) {
return false;
}
}
return true;
};
morpheus.Util._intFormat = typeof d3 !== 'undefined' ? d3.format(',i')
: function(d) {
return '' + Math.round(d);
};
morpheus.Util.intFormat = function(n) {
return morpheus.Util._intFormat(n);
};
morpheus.Util._nf = typeof d3 !== 'undefined' ? d3.format('.4f') : function(d) {
return '' + d;
};
morpheus.Util.nf = function(n) {
var str = (n < 1 && n > -1 && n.toPrecision !== undefined) ? n
.toPrecision(4) : morpheus.Util._nf(n);
return morpheus.Util.removeTrailingZerosInFraction(str);
};
morpheus.Util.createNumberFormat = function(nfractionDigits) {
var d3Formatter = d3.format('.' + nfractionDigits + 'f');
var f = function(value) {
var str = d3Formatter(value);
return morpheus.Util.removeTrailingZerosInFraction(str);
};
return f;
};
morpheus.Util.formatObject = function(value) {
if (_.isNumber(value)) {
return morpheus.Util.nf(value);
}
return value;
};
morpheus.Util.arrayToString = function(array, sep) {
var s = [];
for (var i = 0, length = array.length; i < length; i++) {
s.push(morpheus.Util.formatObject(array[i]));
}
return s.join(sep);
};
morpheus.Util.wrapNumber = function(value, object) {
var n = new Number(value);
n.toObject = function() {
return object;
};
return n;
};
morpheus.Util.toString = function(value) {
if (value == null) {
return '';
} else if (_.isNumber(value)) {
return morpheus.Util.nf(value);
} else if (morpheus.Util.isArray(value)) {
var s = [];
for (var i = 0, length = value.length; i < length; i++) {
s.push(morpheus.Util.formatObject(value[i]));
}
return s.join(', ');
}
return '' + value;
};
morpheus.Util.removeTrailingZerosInFraction = function(str) {
var index = str.lastIndexOf('.');
if (index !== -1) {
var len = str.length;
var zeros = len;
for (var i = len - 1; i > index; i--, zeros--) {
if (str[i] != '0') {
break;
}
}
if (zeros === (index + 1)) {
return str.substring(0, index);
}
if (zeros < len) {
return str.substring(0, index) + str.substring(index, zeros);
}
}
return str;
};
morpheus.Util.s = function(n) {
return n === 1 ? '' : 's';
};
morpheus.Util.create2dArray = function(rows, columns) {
var array2d = [];
for (var i = 0; i < rows; i++) {
var array = [];
for (var j = 0; j < columns; j++) {
array[j] = NaN;
}
array2d.push(array);
}
return array2d;
};
morpheus.Util.escapeRegex = function(value) {
return value.replace(/[*]/g, '.*')
.replace(/[-[\]{}()+?,\\^$|#\s]/g, '\\$&');
};
morpheus.Util.getAutocompleteTokens = function(text) {
text = $.trim(text);
if (text === '') {
return [];
}
var inQuote = false;
var tokens = [];
var currentToken = [];
for (var i = 0, length = text.length; i < length; i++) {
var c = text[i];
if (c === '"') {
inQuote = !inQuote;
currentToken.push(c);
} else {
if ((c === ' ' || c === '\t') && !inQuote) {
tokens.push(currentToken.join(''));
currentToken = [];
} else {
currentToken.push(c);
}
}
}
tokens.push(currentToken.join(''));
tokens = tokens.map(function(t) {
return $.trim(t);
});
tokens = tokens.filter(function(t) {
return t !== '';
});
return tokens;
};
morpheus.Util.createSearchPredicates = function(options) {
var tokens = options.tokens;
var availableFields = options.fields;
var disableFieldSearch = availableFields == null
|| availableFields.length === 0;
var fieldRegExp = /\\:/g;
var predicates = [];
var defaultIsExactMatch = options.defaultMatchMode === 'exact';
_
.each(
tokens,
function(token) {
var field = null;
var semi = token.indexOf(':');
if (semi > 0) { // field search?
if (disableFieldSearch
|| token.charCodeAt(semi - 1) === 92) { // \:
token = token.replace(fieldRegExp, ':');
} else { // only a field search if field matches
// one of available fields
var possibleToken = $.trim(token
.substring(semi + 1));
// check for "field":"val" and "field:val"
var possibleField = $.trim(token.substring(0,
semi)); // split on :
if (possibleField.length > 0
&& possibleField[0] === '"'
&& possibleField[possibleField.length - 1] === '"') {
possibleField = possibleField.substring(1,
possibleField.length - 1);
} else if (possibleField.length > 0
&& possibleField[0] === '"'
&& possibleToken[possibleToken.length - 1] === '"'
&& possibleToken[0] !== '"') {
possibleField = possibleField.substring(1,
possibleField.length);
possibleToken = '"' + possibleToken;
}
if (availableFields.indexOf(possibleField) !== -1) {
token = possibleToken;
field = possibleField;
}
}
}
var isNot = false;
if (token[0] === '-') { // not predicate
token = token.substring(1);
isNot = true;
}
var predicate;
var range = token.indexOf('..');
if (range !== -1) { // range query
var min = parseFloat(token.substring(0, range));
var max = parseFloat(token.substring(range + 2));
predicate = new morpheus.Util.NumberRangePredicate(
field, min, max);
} else if (token[0] === '"'
&& token[token.length - 1] === '"') { // exact
// match
token = token.substring(1, token.length - 1);
predicate = new morpheus.Util.ExactTermPredicate(
field, token);
} else if (token.indexOf('*') !== -1) { // contains
predicate = new morpheus.Util.RegexPredicate(field,
token);
} else {
predicate = defaultIsExactMatch ? new morpheus.Util.ExactTermPredicate(
field, token)
: new morpheus.Util.RegexPredicate(field,
token);
}
predicates.push(isNot ? new morpheus.Util.NotPredicate(
predicate) : predicate);
});
return predicates;
};
// morpheus.Util.getAutocompleteTokens = function(searchText) {
// searchText = $.trim(searchText);
// var tokens = searchText.match(/"[^"]*"|[^\s,"]+/g);
// if (tokens === null) {
// return [];
// }
// tokens = tokens.map(function(t) {
// var t = $.trim(t);
// return t;
// });
// tokens = tokens.filter(function(e) {
// return e != '' && e != undefined;
// });
// return tokens;
// };
morpheus.Util.createRegExpStringToMatchText = function(text) {
var tokens = morpheus.Util.getAutocompleteTokens(text);
if (tokens.length === 0) {
return null;
}
var regex = [];
_.each(tokens, function(token) {
if (token[0] === '"' && token[token.length - 1] === '"') {
token = token.substring(1, token.length - 1);
regex.push('^' + morpheus.Util.escapeRegex(token) + '$'); // exact
// match
} else {
regex.push(morpheus.Util.escapeRegex(token));
}
});
return '(' + regex.join('|') + ')';
};
morpheus.Util.createRegExpToMatchText = function(text) {
var s = morpheus.Util.createRegExpStringToMatchText(text);
return s == null ? null : new RegExp(s, 'i');
};
morpheus.Util.reorderArray = function(array, index) {
var newArray = [];
for (var i = 0; i < index.length; i++) {
newArray.push(array[index[i]]);
}
return newArray;
};
morpheus.Util.getSearchString = function() {
var s = window.location.search;
return s.length > 1 ? s.substring(1) : '';
};
/**
* Takes an array of strings and splits each string by \t
*
* @return An array of arrays
*/
morpheus.Util.splitLines = function(lines) {
var tab = new RegExp('\t');
var tokens = [];
for (var i = 0, nlines = lines.length; i < nlines; i++) {
var line = lines[i];
if (line === '') {
continue;
}
tokens.push(line.split(tab));
}
return tokens;
};
/**
* @param file
* a File or url
* @return A deferred object that resolves to an array of arrays
*/
morpheus.Util.readLines = function(fileOrUrl) {
var isFile = fileOrUrl instanceof File;
var isString = typeof fileOrUrl === 'string' || fileOrUrl instanceof String;
var name = morpheus.Util.getFileName(fileOrUrl);
var ext = morpheus.Util.getExtension(name);
var deferred = $.Deferred();
if (isString) { // URL
if (ext === 'xlsx') {
var oReq = new XMLHttpRequest();
oReq.open('GET', fileOrUrl, true);
oReq.responseType = 'arraybuffer';
oReq.onload = function(oEvent) {
var arrayBuffer = oReq.response; // Note: not
// oReq.responseText
if (arrayBuffer) {
var data = new Uint8Array(arrayBuffer);
var arr = [];
for (var i = 0; i != data.length; ++i) {
arr[i] = String.fromCharCode(data[i]);
}
var bstr = arr.join('');
var lines = morpheus.Util.xlsxTo1dArray(bstr);
deferred.resolve(lines);
} else {
throw 'not found';
}
};
oReq.send(null);
} else {
$.ajax({
url : fileOrUrl,
}).done(function(text, status, xhr) {
deferred.resolve(morpheus.Util.splitOnNewLine(text));
});
}
} else if (isFile) {
var reader = new FileReader();
reader.onload = function(event) {
deferred.resolve(ext === 'xlsx' ? morpheus.Util
.xlsxTo1dArray(event.target.result) : morpheus.Util
.splitOnNewLine(event.target.result));
};
if (ext === 'xlsx') {
reader.readAsBinaryString(fileOrUrl);
} else {
reader.readAsText(fileOrUrl);
}
} else { // it's already lines?
deferred.resolve(fileOrUrl);
}
return deferred;
};
morpheus.Util.createValueToIndices = function(array, field) {
var map = new morpheus.Map();
_.each(array, function(item) {
var key = item[field];
var values = map.get(key);
if (values === undefined) {
values = [];
map.set(key, values);
}
values.push(item);
});
return map;
};
/**
* Splits a string by the new line character, trimming whitespace
*/
morpheus.Util.splitOnNewLine = function(text, commentChar) {
var commentCharCode = commentChar !== undefined ? commentChar.charCodeAt(0)
: undefined;
var lines = text.split(/\n/);
if (lines.length === 1) {
var tmp = text.split(/\r/); // old school mac?
if (tmp.length > 1) {
lines = tmp;
}
}
var rows = [];
for (var i = 0, nlines = lines.length; i < nlines; i++) {
var line = lines[i].trim();
if (line !== '') {
if (commentCharCode !== undefined) {
if (line.charCodeAt(0) !== commentCharCode) {
rows.push(line);
}
} else {
rows.push(line);
}
}
}
return rows;
};
morpheus.Util.ContainsPredicate = function(field, text) {
this.field = field;
text = text.toLowerCase();
this.text = text;
};
morpheus.Util.ContainsPredicate.prototype = {
accept : function(value) {
return value.toLowerCase
&& value.toLowerCase().indexOf(this.text) !== -1;
},
getText : function() {
return this.text;
},
getField : function() {
return this.field;
},
isNumber : function() {
return false;
},
toString : function() {
return 'ContainsPredicate ' + this.field + ':' + this.text;
}
};
morpheus.Util.ExactTermPredicate = function(field, term) {
this.field = field;
term = term.toLowerCase();
this.text = term;
};
morpheus.Util.ExactTermPredicate.prototype = {
accept : function(value) {
return value.toLowerCase && value.toLowerCase() === this.text;
},
getField : function() {
return this.field;
},
getText : function() {
return this.text;
},
isNumber : function() {
return false;
},
toString : function() {
return 'ExactTermPredicate ' + this.field + ':' + this.text;
}
};
morpheus.Util.RegexPredicate = function(field, text) {
this.field = field;
this.text = text;
this.regex = new RegExp(morpheus.Util.escapeRegex(text), 'i');
};
morpheus.Util.RegexPredicate.prototype = {
accept : function(value) {
return this.regex.test(value);
},
getField : function() {
return this.field;
},
getText : function() {
return this.text;
},
isNumber : function() {
return false;
},
toString : function() {
return 'RegexPredicate ' + this.field + ':' + this.regex;
}
};
morpheus.Util.NumberRangePredicate = function(field, min, max) {
this.field = field;
this.min = min;
this.max = max;
};
morpheus.Util.NumberRangePredicate.prototype = {
accept : function(value) {
return value >= this.min && value <= this.max;
},
getField : function() {
return this.field;
},
getText : function() {
return this.min + '..' + this.max;
},
isNumber : function() {
return true;
},
toString : function() {
return 'NumberRangePredicate ' + this.field + ':' + this.min + '...'
+ this.max;
}
};
morpheus.Util.NotPredicate = function(p) {
this.p = p;
};
morpheus.Util.NotPredicate.prototype = {
accept : function(value) {
return !this.p.accept(value);
},
getField : function() {
return this.p.getField();
},
getText : function() {
return this.p.getText();
},
isNumber : function() {
return this.p.isNumber();
},
toString : function() {
return 'NotPredicate ' + this.p;
}
};