gap row detect

by Jimmy Chandra

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<div>
    <p>Given a set of potential grid data, detect where one logical row ends and another begins
        based on the size of the gaps (empty whitespace between the actual rows).</p>
</div>

<div id="container">
	</div>

CSS

#container {
			position: relative;
		}

JavaScript

(function(global, udef) {
		"use strict";

		var traceSwitch = true;

		var trace = function(msg) {
			if (traceSwitch) {
				console.log(msg);
			}
		};
        
        var pad = function(n, width, z) {
            z = z || '0';
            n = n + '';
            return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
        };

		var model1 = {
			textRectangles : [
				{ x1:  10, y1:  10, x2:  50, y2:  20, data: 'Description' },
				{ x1: 300, y1:  10, x2: 350, y2:  20, data: 'Amount AUD' },

				{ x1:  10, y1:  25, x2:  50, y2:  35, data: 'Rotten fish' },
				{ x1: 300, y1:  25, x2: 350, y2:  35, data: '10.00' },
				
				{ x1:  10, y1:  40, x2:  70, y2:  50, data: 'Very very rotten indeed' },

				{ x1:  10, y1:  60, x2:  50, y2:  70, data: 'Broken glass' },
				{ x1: 320, y1:  60, x2: 350, y2:  70, data: '5.00' },

				{ x1:  10, y1:  75, x2:  70, y2:  85, data: 'Very very broken indeed' },

				{ x1:  10, y1:  95, x2:  50, y2: 105, data: 'Smelly shoes' },
				{ x1: 320, y1:  95, x2: 350, y2: 105, data: '7.00' },

				{ x1:  10, y1: 110, x2:  70, y2: 120, data: 'Very very smelly indeed' },

				{ x1: 200, y1: 130, x2: 300, y2: 140, data: 'Subtotal' }
			],
            lineItemRegionTopAnchor : { text: 'Description', partialMatch: false, searchTopToBottom: true },
			lineItemRegionBottomAnchor: { text : 'Subtotal', partialMatch: false, searchTopToBottom: false },
			columns : [
				{ x1:   0, x2: 200 },
				{ x1: 210, x2: 360 }
			]
		};

		var initGridFrom = function(lastColumnData) {
			var grid = [];
			_.each(lastColumnData, function() {
				grid.push([]);
			});
			return grid;
		};
        
        var getSortedRectangles = function(trs, searchTopToBottom) {
            var rs = _.sortBy(trs, function(r) { return pad(r.y1,10) + pad(r.x1,10); });
            if (searchTopToBottom) {
                return rs;
            } else {
                return rs.reverse();
            }
        };
        
        var...