all files / src/ NonOverlappingLayout.js

86% Statements 43/50
75% Branches 21/28
80% Functions 12/15
86% Lines 43/50
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93            314×   314× 314×     310× 310× 310×     30× 314× 314× 314×       28×                     28× 30× 26× 26×     28×                                                
/*jslint node: true */
/*jshint laxbreak: true */
'use strict';
 
var _ = require('underscore');
 
var Row = function() {
    var row = this;
    row.rowFeatures = [];
 
    row.featureOverlap = function(feature, d, ftEnd, dEnd) {
        var featureBeginOverlap = (Number(feature.begin) >= Number(d.begin)) &&
            (Number(feature.begin) <= Number(dEnd));
        var featureEndOverlap = (Number(ftEnd) >= Number(d.begin)) && (Number(ftEnd) <= Number(dEnd));
        return featureBeginOverlap || featureEndOverlap;
    };
 
    row.dOverlap = function(feature, d, ftEnd, dEnd) {
        var dBeginOverlap = (Number(d.begin) >= Number(feature.begin)) && (Number(d.begin) <= Number(ftEnd));
        var dEndOverlap = (Number(dEnd) >= Number(feature.begin)) && (Number(dEnd) <= Number(ftEnd));
        return dBeginOverlap || dEndOverlap;
    };
 
    row.containsOverlap = function(feature) {
        return _.some(row.rowFeatures, function(d) {
            var ftEnd = (feature.end) ? feature.end : feature.begin;
            var dEnd = (d.end) ? d.end : d.begin;
            return row.featureOverlap(feature, d, ftEnd, dEnd) || row.dOverlap(feature, d, ftEnd, dEnd);
        });
    };
 
    row.addFeature = function(feature) {
        row.rowFeatures.push(feature);
    };
};
 
var NonOverlappingLayout = function(features, totalHeight) {
    var nonOverlappingLayout = this;
    nonOverlappingLayout.padding = 1;
    nonOverlappingLayout.minHeight = 15;
    nonOverlappingLayout.rowHeight = 0;
    nonOverlappingLayout.rows = [];
 
    nonOverlappingLayout.totalHeight = totalHeight;
 
    nonOverlappingLayout.calculate = function(){
        nonOverlappingLayout.rowHeight = (
            (nonOverlappingLayout.totalHeight / nonOverlappingLayout.rows.length < nonOverlappingLayout.minHeight)
            ? nonOverlappingLayout.totalHeight /nonOverlappingLayout.rows.length : nonOverlappingLayout.minHeight )
            - 2 * nonOverlappingLayout.padding;
    };
 
    _.each(features, function(feature){
        var added = _.some(nonOverlappingLayout.rows, function(row){
            if(!row.containsOverlap(feature)) {
                row.addFeature(feature);
                return true;
            }
        });
        if(!added) {
            var row = new Row();
            row.addFeature(feature);
            nonOverlappingLayout.rows.push(row);
        }
    });
};
 
NonOverlappingLayout.prototype.getYPos = function(feature) {
    var nonOverlappingLayout = this;
    var yPos,
        yOffset = (nonOverlappingLayout.totalHeight /nonOverlappingLayout.rows.length > nonOverlappingLayout.minHeight)
            ? (nonOverlappingLayout.totalHeight - (nonOverlappingLayout.rows.length * nonOverlappingLayout.minHeight))/2
            : 0;
    _.each(nonOverlappingLayout.rows, function(row, i) {
        _.each(row.rowFeatures, function(currFeature){
            if(currFeature === feature) {
                yPos = (i * (nonOverlappingLayout.rowHeight + 2 * nonOverlappingLayout.padding)
                + yOffset);
            }
        });
    });
    return yPos;
};
 
NonOverlappingLayout.prototype.getRows = function() {
    return this.rows;
};
 
NonOverlappingLayout.prototype.getFeatureHeight = function() {
    return this.rowHeight;
};
 
module.exports = NonOverlappingLayout;