# Code coverage report for lib/NonOverlappingLayout.js

## Statements: 86% (43 / 50) Branches: 75% (21 / 28) Functions: 80% (12 / 15) Lines: 86% (43 / 50) Ignored: none

All files » lib/ » NonOverlappingLayout.js

    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

    1

    1
    2
    2

    2
    314

    314
    314

    2
    310
    310
    310

    2
    30
    314
    314
    314

    2
    28

    1
    1
    1
    1
    1
    1

    1

    1
    1

    1
    28
    30
    26
    26

    28
    2
    2
    2

    1

    1
    1

    1
    1

    1/*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;