<commit_before>define( [
            'dojo/_base/declare',
            'dojo/_base/lang',
            'JBrowse/Model/Range',
            'jszlib/inflate'
        ],
        function( declare, dlang, Range, inflate ) {

var dlog = function(){ console.log.apply(console, arguments); };

var gettable = declare( null, {
    get: function(name) {
        return this[ { start: 'min', end: 'max' }[name] || name ];
    }
});
var Feature = declare( gettable, {} );
var Group = declare( gettable, {} );

var RequestWorker = declare( null,
 /**
  * @lends JBrowse.Store.BigWig.Window.RequestWorker.prototype
  */
 {

    BIG_WIG_TYPE_GRAPH: 1,
    BIG_WIG_TYPE_VSTEP: 2,
    BIG_WIG_TYPE_FSTEP: 3,

    /**
     * Worker object for reading data from a bigwig or bigbed file.
     * Manages the state necessary for traversing the index trees and
     * so forth.
     *
     * Adapted by Robert Buels from bigwig.js in the Dalliance Genome
     * Explorer by Thomas Down.
     * @constructs
     */
    constructor: function( window, chr, min, max, callback ) {
        this.window = window;
        this.blocksToFetch = [];
        this.outstanding = 0;

        this.chr = chr;
        this.min = min;
        this.max = max;
        this.callback = callback;
    },

    cirFobRecur: function(offset, level) {
        this.outstanding += offset.length;

        var maxCirBlockSpan = 4 +  (this.window.cirBlockSize * 32);   // Upper bound on size, based on a completely full leaf node.
        var spans;
        for (var i = 0; i < offset.length; ++i) {
            var blockSpan = new Range(offset[i], Math.min(offset[i] + maxCirBlockSpan, this.window.cirTreeOffset + this.window.cirTreeLength));
            spans = spans ? spans.union( blockSpan ) : blockSpan;
        }

        var fetchRanges = spans.ranges();
        //dlog('fetchRanges: ' + fetchRanges);
        for (var r = 0; r < fetchRanges.length; ++r) {
            var fr = fetchRanges[r];
            this.cirFobStartFetch(offset, fr, level);
        }
    },

    cirFobStartFetch: function(offset, fr, level, attempts) {
        var length = fr.max() - fr.min();
        //dlog('fetching ' + fr.min() + '-' + fr.max() + ' (' + (fr.max() - fr.min()) + ')');
        //console.log('cirfobstartfetch');
        this.window.bwg.data
            .slice(fr.min(), fr.max() - fr.min())
            .fetch( dlang.hitch( this,function(resultBuffer) {
                                     for (var i = 0; i < offset.length; ++i) {
                                         if (fr.contains(offset[i])) {
                                             this.cirFobRecur2(resultBuffer, offset[i] - fr.min(), level);
                                             --this.outstanding;
                                             if (this.outstanding == 0) {
                                                 this.cirCompleted();
                                             }
                                         }
                                     }
                                 }));
    },

    cirFobRecur2: function(cirBlockData, offset, level) {
        var ba = new Int8Array(cirBlockData);
        var sa = new Int16Array(cirBlockData);
        var la = new Int32Array(cirBlockData);

        var isLeaf = ba[offset];
        var cnt = sa[offset/2 + 1];
        // dlog('cir level=' + level + '; cnt=' + cnt);
        offset += 4;

        if (isLeaf != 0) {
            for (var i = 0; i < cnt; ++i) {
                var lo = offset/4;
                var startChrom = la[lo];
                var startBase = la[lo + 1];
                var endChrom = la[lo + 2];
                var endBase = la[lo + 3];
                var blockOffset = (la[lo + 4]<<32) | (la[lo + 5]);
                var blockSize = (la[lo + 6]<<32) | (la[lo + 7]);
                if ((startChrom < this.chr || (startChrom == this.chr && startBase <= this.max)) &&
                    (endChrom   > this.chr || (endChrom == this.chr && endBase >= this.min)))
                {
                    // dlog('Got an interesting block: startBase=' + startBase + '; endBase=' + endBase + '; offset=' + blockOffset + '; size=' + blockSize);
                    this.blocksToFetch.push({offset: blockOffset, size: blockSize});
                }
                offset += 32;
            }
        } else {
            var recurOffsets = [];
            for (var i = 0; i < cnt; ++i) {
                var lo = offset/4;
                var startChrom = la[lo];
                var startBase = la[lo + 1];
                var endChrom = la[lo + 2];
                var endBase = la[lo + 3];
                var blockOffset = (la[lo + 4]<<32) | (la[lo + 5]);
                if ((startChrom < this.chr || (startChrom == this.chr && startBase <= this.max)) &&
                    (endChrom   > this.chr || (endChrom == this.chr && endBase >= this.min)))
                {
                    recurOffsets.push(blockOffset);
                }
                offset += 24;
            }
            if (recurOffsets.length > 0) {
                this.cirFobRecur(recurOffsets, level + 1);
            }
        }
    },

    cirCompleted: function() {
        this.blocksToFetch.sort(function(b0, b1) {
                               return (b0.offset|0) - (b1.offset|0);
                           });

        if (this.blocksToFetch.length == 0) {
            this.callback([]);
        } else {
            this.features = [];
            this.tramp();
        }
    },

    createFeature: function(fmin, fmax, opts) {
        // dlog('createFeature(' + fmin +', ' + fmax + ')');

        if (!opts) {
            opts = {};
        }

        var f = new Feature();
        f.segment = this.window.bwg.idsToChroms[this.chr];
        f.min = fmin;
        f.max = fmax;
        f.type = 'bigwig';

        for (k in opts) {
            f[k] = opts[k];
        }

        this.features.push(f);
    },
    maybeCreateFeature: function(fmin, fmax, opts) {
        if (fmin <= this.max && fmax >= this.min) {
            this.createFeature( fmin, fmax, opts );
        }
    },
    tramp: function() {
        if (this.blocksToFetch.length == 0) {
            //var afterBWG = Date.now();
            // dlog('BWG fetch took ' + (afterBWG - beforeBWG) + 'ms');
            this.callback( this.features );
            return;  // just in case...
        } else {
            var block = this.blocksToFetch[0];
            if (block.data) {
                var ba = new Uint8Array(block.data);

                if (this.window.isSummary) {
                    var sa = new Int16Array(block.data);
                    var la = new Int32Array(block.data);
                    var fa = new Float32Array(block.data);

                    var itemCount = block.data.byteLength/32;
                    for (var i = 0; i < itemCount; ++i) {
                        var chromId =   la[(i*8)];
                        var start =     la[(i*8)+1];
                        var end =       la[(i*8)+2];
                        var validCnt =  la[(i*8)+3];
                        var minVal    = fa[(i*8)+4];
                        var maxVal    = fa[(i*8)+5];
                        var sumData   = fa[(i*8)+6];
                        var sumSqData = fa[(i*8)+7];

                        if (chromId == this.chr) {
                            var summaryOpts = {type: 'bigwig', score: sumData/validCnt};
                            if (this.window.bwg.type == 'bigbed') {
                                summaryOpts.type = 'density';
                            }
                            this.maybeCreateFeature( start, end, summaryOpts);
                        }
                    }
                } else if (this.window.bwg.type == 'bigwig') {
                    var sa = new Int16Array(block.data);
                    var la = new Int32Array(block.data);
                    var fa = new Float32Array(block.data);

                    var chromId = la[0];
                    var blockStart = la[1];
                    var blockEnd = la[2];
                    var itemStep = la[3];
                    var itemSpan = la[4];
                    var blockType = ba[20];
                    var itemCount = sa[11];

                    // dlog('processing bigwig block, type=' + blockType + '; count=' + itemCount);

                    if (blockType == this.BIG_WIG_TYPE_FSTEP) {
                        for (var i = 0; i < itemCount; ++i) {
                            var score = fa[i + 6];
                            this.maybeCreateFeature( blockStart + (i*itemStep), blockStart + (i*itemStep) + itemSpan, {score: score});
                        }
                    } else if (blockType == this.BIG_WIG_TYPE_VSTEP) {
                        for (var i = 0; i < itemCount; ++i) {
                            var start = la[(i*2) + 6];
                            var score = fa[(i*2) + 7];
                            this.maybeCreateFeature( start, start + itemSpan, {score: score});
                        }
                    } else if (blockType == this.BIG_WIG_TYPE_GRAPH) {
                        for (var i = 0; i < itemCount; ++i) {
                            var start = la[(i*3) + 6] + 1;
                            var end   = la[(i*3) + 7];
                            var score = fa[(i*3) + 8];
                            if (start > end) {
                                start = end;
                            }
                            this.maybeCreateFeature( start, end, {score: score});
                        }
                    } else {
                        dlog('Currently not handling bwgType=' + blockType);
                    }
                } else if (this.window.bwg.type == 'bigbed') {
                    var offset = 0;
                    while (offset < ba.length) {
                        var chromId = (ba[offset+3]<<24) | (ba[offset+2]<<16) | (ba[offset+1]<<8) | (ba[offset+0]);
                        var start = (ba[offset+7]<<24) | (ba[offset+6]<<16) | (ba[offset+5]<<8) | (ba[offset+4]);
                        var end = (ba[offset+11]<<24) | (ba[offset+10]<<16) | (ba[offset+9]<<8) | (ba[offset+8]);
                        offset += 12;
                        var rest = '';
                        while (true) {
                            var ch = ba[offset++];
                            if (ch != 0) {
                                rest += String.fromCharCode(ch);
                            } else {
                                break;
                            }
                        }

                        var featureOpts = {};

                        var bedColumns = rest.split('\t');
                        if (bedColumns.length > 0) {
                            featureOpts.label = bedColumns[0];
                        }
                        if (bedColumns.length > 1) {
                            featureOpts.score = stringToInt(bedColumns[1]);
                        }
                        if (bedColumns.length > 2) {
                            featureOpts.orientation = bedColumns[2];
                        }
                        if (bedColumns.length > 5) {
                            var color = bedColumns[5];
                            if (this.window.BED_COLOR_REGEXP.test(color)) {
                                featureOpts.override_color = 'rgb(' + color + ')';
                            }
                        }

                        if (bedColumns.length < 9) {
                            if (chromId == this.chr) {
                                this.maybeCreateFeature( start + 1, end, featureOpts);
                            }
                        } else if (chromId == this.chr && start <= this.max && end >= this.min) {
                            // Complex-BED?
                            // FIXME this is currently a bit of a hack to do Clever Things with ensGene.bb

                            var thickStart = bedColumns[3]|0;
                            var thickEnd   = bedColumns[4]|0;
                            var blockCount = bedColumns[6]|0;
                            var blockSizes = bedColumns[7].split(',');
                            var blockStarts = bedColumns[8].split(',');

                            featureOpts.type = 'bb-transcript';
                            var grp = new Group();
                            grp.id = bedColumns[0];
                            grp.type = 'bb-transcript';
                            grp.notes = [];
                            featureOpts.groups = [grp];

                            if (bedColumns.length > 10) {
                                var geneId = bedColumns[9];
                                var geneName = bedColumns[10];
                                var gg = new Group();
                                gg.id = geneId;
                                gg.label = geneName;
                                gg.type = 'gene';
                                featureOpts.groups.push(gg);
                            }

                            var spans = null;
                            for (var b = 0; b < blockCount; ++b) {
                                var bmin = (blockStarts[b]|0) + start;
                                var bmax = bmin + (blockSizes[b]|0);
                                var span = new Range(bmin, bmax);
                                if (spans) {
                                    spans = spans.union( span );
                                } else {
                                    spans = span;
                                }
                            }

                            var tsList = spans.ranges();
                            for (var s = 0; s < tsList.length; ++s) {
                                var ts = tsList[s];
                                this.createFeature( ts.min() + 1, ts.max(), featureOpts);
                            }

                            if (thickEnd > thickStart) {
                                var tl = spans.intersection( new Range(thickStart, thickEnd) );
                                if (tl) {
                                    featureOpts.type = 'bb-translation';
                                    var tlList = tl.ranges();
                                    for (var s = 0; s < tlList.length; ++s) {
                                        var ts = tlList[s];
                                        this.createFeature( ts.min() + 1, ts.max(), featureOpts);
                                    }
                                }
                            }
                        }
                    }
                } else {
                    dlog("Don't know what to do with " + this.window.bwg.type);
                }
                this.blocksToFetch.splice(0, 1);
                this.tramp();
            } else {
                var fetchStart = block.offset;
                var fetchSize = block.size;
                var bi = 1;
                while (bi < this.blocksToFetch.length && this.blocksToFetch[bi].offset == (fetchStart + fetchSize)) {
                    fetchSize += this.blocksToFetch[bi].size;
                    ++bi;
                }

                //dlog('other thing');
                this.window.bwg.data
                    .slice(fetchStart, fetchSize)
                    .fetch(dlang.hitch( this, function(result) {
                                            var offset = 0;
                                            var bi = 0;
                                            while (offset < fetchSize) {
                                                var fb = this.blocksToFetch[bi];

                                                var data;
                                                if (this.window.bwg.uncompressBufSize > 0) {
                                                    // var beforeInf = Date.now();
                                                    data = inflate(result, offset + 2, fb.size - 2);
                                                    // var afterInf = Date.now();
                                                    // dlog('inflate: ' + (afterInf - beforeInf) + 'ms');
                                                } else {
                                                    var tmp = new Uint8Array(fb.size);    // FIXME is this really the best we can do?
                                                    arrayCopy(new Uint8Array(result, offset, fb.size), 0, tmp, 0, fb.size);
                                                    data = tmp.buffer;
                                                }
                                                fb.data = data;

                                                offset += fb.size;
                                                ++bi;
                                            }
                                            this.tramp();
                                        }));
            }
        }
    }
});

return RequestWorker;

});<commit_msg>fix Wiggle backend returning 1-based data.  fix off-by-one errors in WIG export<commit_after>define( [
            'dojo/_base/declare',
            'dojo/_base/lang',
            'JBrowse/Model/Range',
            'jszlib/inflate'
        ],
        function( declare, dlang, Range, inflate ) {

var dlog = function(){ console.log.apply(console, arguments); };

var gettable = declare( null, {
    get: function(name) {
        return this[ { start: 'min', end: 'max' }[name] || name ];
    }
});
var Feature = declare( gettable, {} );
var Group = declare( gettable, {} );

var RequestWorker = declare( null,
 /**
  * @lends JBrowse.Store.BigWig.Window.RequestWorker.prototype
  */
 {

    BIG_WIG_TYPE_GRAPH: 1,
    BIG_WIG_TYPE_VSTEP: 2,
    BIG_WIG_TYPE_FSTEP: 3,

    /**
     * Worker object for reading data from a bigwig or bigbed file.
     * Manages the state necessary for traversing the index trees and
     * so forth.
     *
     * Adapted by Robert Buels from bigwig.js in the Dalliance Genome
     * Explorer by Thomas Down.
     * @constructs
     */
    constructor: function( window, chr, min, max, callback ) {
        this.window = window;
        this.blocksToFetch = [];
        this.outstanding = 0;

        this.chr = chr;
        this.min = min;
        this.max = max;
        this.callback = callback;
    },

    cirFobRecur: function(offset, level) {
        this.outstanding += offset.length;

        var maxCirBlockSpan = 4 +  (this.window.cirBlockSize * 32);   // Upper bound on size, based on a completely full leaf node.
        var spans;
        for (var i = 0; i < offset.length; ++i) {
            var blockSpan = new Range(offset[i], Math.min(offset[i] + maxCirBlockSpan, this.window.cirTreeOffset + this.window.cirTreeLength));
            spans = spans ? spans.union( blockSpan ) : blockSpan;
        }

        var fetchRanges = spans.ranges();
        //dlog('fetchRanges: ' + fetchRanges);
        for (var r = 0; r < fetchRanges.length; ++r) {
            var fr = fetchRanges[r];
            this.cirFobStartFetch(offset, fr, level);
        }
    },

    cirFobStartFetch: function(offset, fr, level, attempts) {
        var length = fr.max() - fr.min();
        //dlog('fetching ' + fr.min() + '-' + fr.max() + ' (' + (fr.max() - fr.min()) + ')');
        //console.log('cirfobstartfetch');
        this.window.bwg.data
            .slice(fr.min(), fr.max() - fr.min())
            .fetch( dlang.hitch( this,function(resultBuffer) {
                                     for (var i = 0; i < offset.length; ++i) {
                                         if (fr.contains(offset[i])) {
                                             this.cirFobRecur2(resultBuffer, offset[i] - fr.min(), level);
                                             --this.outstanding;
                                             if (this.outstanding == 0) {
                                                 this.cirCompleted();
                                             }
                                         }
                                     }
                                 }));
    },

    cirFobRecur2: function(cirBlockData, offset, level) {
        var ba = new Int8Array(cirBlockData);
        var sa = new Int16Array(cirBlockData);
        var la = new Int32Array(cirBlockData);

        var isLeaf = ba[offset];
        var cnt = sa[offset/2 + 1];
        // dlog('cir level=' + level + '; cnt=' + cnt);
        offset += 4;

        if (isLeaf != 0) {
            for (var i = 0; i < cnt; ++i) {
                var lo = offset/4;
                var startChrom = la[lo];
                var startBase = la[lo + 1];
                var endChrom = la[lo + 2];
                var endBase = la[lo + 3];
                var blockOffset = (la[lo + 4]<<32) | (la[lo + 5]);
                var blockSize = (la[lo + 6]<<32) | (la[lo + 7]);
                if ((startChrom < this.chr || (startChrom == this.chr && startBase <= this.max)) &&
                    (endChrom   > this.chr || (endChrom == this.chr && endBase >= this.min)))
                {
                    // dlog('Got an interesting block: startBase=' + startBase + '; endBase=' + endBase + '; offset=' + blockOffset + '; size=' + blockSize);
                    this.blocksToFetch.push({offset: blockOffset, size: blockSize});
                }
                offset += 32;
            }
        } else {
            var recurOffsets = [];
            for (var i = 0; i < cnt; ++i) {
                var lo = offset/4;
                var startChrom = la[lo];
                var startBase = la[lo + 1];
                var endChrom = la[lo + 2];
                var endBase = la[lo + 3];
                var blockOffset = (la[lo + 4]<<32) | (la[lo + 5]);
                if ((startChrom < this.chr || (startChrom == this.chr && startBase <= this.max)) &&
                    (endChrom   > this.chr || (endChrom == this.chr && endBase >= this.min)))
                {
                    recurOffsets.push(blockOffset);
                }
                offset += 24;
            }
            if (recurOffsets.length > 0) {
                this.cirFobRecur(recurOffsets, level + 1);
            }
        }
    },

    cirCompleted: function() {
        this.blocksToFetch.sort(function(b0, b1) {
                               return (b0.offset|0) - (b1.offset|0);
                           });

        if (this.blocksToFetch.length == 0) {
            this.callback([]);
        } else {
            this.features = [];
            this.tramp();
        }
    },

    createFeature: function(fmin, fmax, opts) {
        // dlog('createFeature(' + fmin +', ' + fmax + ')');

        if (!opts) {
            opts = {};
        }

        var f = new Feature();
        f.segment = this.window.bwg.idsToChroms[this.chr];
        f.min = fmin;
        f.max = fmax;
        f.type = 'bigwig';

        for (k in opts) {
            f[k] = opts[k];
        }

        this.features.push(f);
    },
    maybeCreateFeature: function(fmin, fmax, opts) {
        if (fmin <= this.max && fmax >= this.min) {
            this.createFeature( fmin, fmax, opts );
        }
    },
    tramp: function() {
        if (this.blocksToFetch.length == 0) {
            //var afterBWG = Date.now();
            // dlog('BWG fetch took ' + (afterBWG - beforeBWG) + 'ms');
            this.callback( this.features );
            return;  // just in case...
        } else {
            var block = this.blocksToFetch[0];
            if (block.data) {
                var ba = new Uint8Array(block.data);

                if (this.window.isSummary) {
                    var sa = new Int16Array(block.data);
                    var la = new Int32Array(block.data);
                    var fa = new Float32Array(block.data);

                    var itemCount = block.data.byteLength/32;
                    for (var i = 0; i < itemCount; ++i) {
                        var chromId =   la[(i*8)];
                        var start =     la[(i*8)+1];
                        var end =       la[(i*8)+2];
                        var validCnt =  la[(i*8)+3];
                        var minVal    = fa[(i*8)+4];
                        var maxVal    = fa[(i*8)+5];
                        var sumData   = fa[(i*8)+6];
                        var sumSqData = fa[(i*8)+7];

                        if (chromId == this.chr) {
                            var summaryOpts = {type: 'bigwig', score: sumData/validCnt};
                            if (this.window.bwg.type == 'bigbed') {
                                summaryOpts.type = 'density';
                            }
                            this.maybeCreateFeature( start, end, summaryOpts);
                        }
                    }
                } else if (this.window.bwg.type == 'bigwig') {
                    var sa = new Int16Array(block.data);
                    var la = new Int32Array(block.data);
                    var fa = new Float32Array(block.data);

                    var chromId = la[0];
                    var blockStart = la[1];
                    var blockEnd = la[2];
                    var itemStep = la[3];
                    var itemSpan = la[4];
                    var blockType = ba[20];
                    var itemCount = sa[11];

                    // dlog('processing bigwig block, type=' + blockType + '; count=' + itemCount);

                    if (blockType == this.BIG_WIG_TYPE_FSTEP) {
                        for (var i = 0; i < itemCount; ++i) {
                            var score = fa[i + 6];
                            this.maybeCreateFeature( blockStart + (i*itemStep), blockStart + (i*itemStep) + itemSpan, {score: score});
                        }
                    } else if (blockType == this.BIG_WIG_TYPE_VSTEP) {
                        for (var i = 0; i < itemCount; ++i) {
                            var start = la[(i*2) + 6];
                            var score = fa[(i*2) + 7];
                            this.maybeCreateFeature( start, start + itemSpan, {score: score});
                        }
                    } else if (blockType == this.BIG_WIG_TYPE_GRAPH) {
                        for (var i = 0; i < itemCount; ++i) {
                            var start = la[(i*3) + 6];
                            var end   = la[(i*3) + 7];
                            var score = fa[(i*3) + 8];
                            if (start > end) {
                                start = end;
                            }
                            this.maybeCreateFeature( start, end, {score: score});
                        }
                    } else {
                        dlog('Currently not handling bwgType=' + blockType);
                    }
                } else if (this.window.bwg.type == 'bigbed') {
                    var offset = 0;
                    while (offset < ba.length) {
                        var chromId = (ba[offset+3]<<24) | (ba[offset+2]<<16) | (ba[offset+1]<<8) | (ba[offset+0]);
                        var start = (ba[offset+7]<<24) | (ba[offset+6]<<16) | (ba[offset+5]<<8) | (ba[offset+4]);
                        var end = (ba[offset+11]<<24) | (ba[offset+10]<<16) | (ba[offset+9]<<8) | (ba[offset+8]);
                        offset += 12;
                        var rest = '';
                        while (true) {
                            var ch = ba[offset++];
                            if (ch != 0) {
                                rest += String.fromCharCode(ch);
                            } else {
                                break;
                            }
                        }

                        var featureOpts = {};

                        var bedColumns = rest.split('\t');
                        if (bedColumns.length > 0) {
                            featureOpts.label = bedColumns[0];
                        }
                        if (bedColumns.length > 1) {
                            featureOpts.score = stringToInt(bedColumns[1]);
                        }
                        if (bedColumns.length > 2) {
                            featureOpts.orientation = bedColumns[2];
                        }
                        if (bedColumns.length > 5) {
                            var color = bedColumns[5];
                            if (this.window.BED_COLOR_REGEXP.test(color)) {
                                featureOpts.override_color = 'rgb(' + color + ')';
                            }
                        }

                        if (bedColumns.length < 9) {
                            if (chromId == this.chr) {
                                this.maybeCreateFeature( start, end, featureOpts);
                            }
                        } else if (chromId == this.chr && start <= this.max && end >= this.min) {
                            // Complex-BED?
                            // FIXME this is currently a bit of a hack to do Clever Things with ensGene.bb

                            var thickStart = bedColumns[3]|0;
                            var thickEnd   = bedColumns[4]|0;
                            var blockCount = bedColumns[6]|0;
                            var blockSizes = bedColumns[7].split(',');
                            var blockStarts = bedColumns[8].split(',');

                            featureOpts.type = 'bb-transcript';
                            var grp = new Group();
                            grp.id = bedColumns[0];
                            grp.type = 'bb-transcript';
                            grp.notes = [];
                            featureOpts.groups = [grp];

                            if (bedColumns.length > 10) {
                                var geneId = bedColumns[9];
                                var geneName = bedColumns[10];
                                var gg = new Group();
                                gg.id = geneId;
                                gg.label = geneName;
                                gg.type = 'gene';
                                featureOpts.groups.push(gg);
                            }

                            var spans = null;
                            for (var b = 0; b < blockCount; ++b) {
                                var bmin = (blockStarts[b]|0) + start;
                                var bmax = bmin + (blockSizes[b]|0);
                                var span = new Range(bmin, bmax);
                                if (spans) {
                                    spans = spans.union( span );
                                } else {
                                    spans = span;
                                }
                            }

                            var tsList = spans.ranges();
                            for (var s = 0; s < tsList.length; ++s) {
                                var ts = tsList[s];
                                this.createFeature( ts.min(), ts.max(), featureOpts);
                            }

                            if (thickEnd > thickStart) {
                                var tl = spans.intersection( new Range(thickStart, thickEnd) );
                                if (tl) {
                                    featureOpts.type = 'bb-translation';
                                    var tlList = tl.ranges();
                                    for (var s = 0; s < tlList.length; ++s) {
                                        var ts = tlList[s];
                                        this.createFeature( ts.min(), ts.max(), featureOpts);
                                    }
                                }
                            }
                        }
                    }
                } else {
                    dlog("Don't know what to do with " + this.window.bwg.type);
                }
                this.blocksToFetch.splice(0, 1);
                this.tramp();
            } else {
                var fetchStart = block.offset;
                var fetchSize = block.size;
                var bi = 1;
                while (bi < this.blocksToFetch.length && this.blocksToFetch[bi].offset == (fetchStart + fetchSize)) {
                    fetchSize += this.blocksToFetch[bi].size;
                    ++bi;
                }

                //dlog('other thing');
                this.window.bwg.data
                    .slice(fetchStart, fetchSize)
                    .fetch(dlang.hitch( this, function(result) {
                                            var offset = 0;
                                            var bi = 0;
                                            while (offset < fetchSize) {
                                                var fb = this.blocksToFetch[bi];

                                                var data;
                                                if (this.window.bwg.uncompressBufSize > 0) {
                                                    // var beforeInf = Date.now();
                                                    data = inflate(result, offset + 2, fb.size - 2);
                                                    // var afterInf = Date.now();
                                                    // dlog('inflate: ' + (afterInf - beforeInf) + 'ms');
                                                } else {
                                                    var tmp = new Uint8Array(fb.size);    // FIXME is this really the best we can do?
                                                    arrayCopy(new Uint8Array(result, offset, fb.size), 0, tmp, 0, fb.size);
                                                    data = tmp.buffer;
                                                }
                                                fb.data = data;

                                                offset += fb.size;
                                                ++bi;
                                            }
                                            this.tramp();
                                        }));
            }
        }
    }
});

return RequestWorker;

});<|endoftext|>


<commit_before>"use strict";

// module Partial.Unsafe

exports.unsafePartial = function(f) {
    return f({});
};
<commit_msg>Remove unnecessary object creation.<commit_after>"use strict";

// module Partial.Unsafe

exports.unsafePartial = function(f) {
    return f();
};
<|endoftext|>


<commit_before>function showTaskOverview(groupNum){

	var task_id = getEventJSONIndex(groupNum);
	var eventObj = flashTeamsJSON["events"][task_id];
	var title = eventObj["title"];

	//uniq_u is null for author, we use this to decide whether to show the edit link next to project overview
	var uniq_u=getParameterByName('uniq');

	//modal label
	var label = title;
	$('#task_modal_Label').html(label);

	//modal content
	//var taskOverviewContent = '

' + description + '

';
	var taskOverviewContent = getTaskOverviewContent(groupNum);
	//$('#taskOverview').html(taskOverviewContent);
	$('#task-text').html(taskOverviewContent);

	if(in_progress != true && (uniq_u == "" || memberType == "pc" || memberType == "client") ) {
		$("#edit-save-task").css('display', '');
		$("#edit-save-task").attr('onclick', 'editTaskOverview(true,'+groupNum+')');
		$("#edit-save-task").html('Edit');

	}
	else{
		$("#edit-save-task").css('display', 'none');
		$("#hire-task").css('display','none');
		$("#delete").css('display','none');
	}

}

function editTaskOverview(popover,groupNum){

	var task_id = getEventJSONIndex(groupNum);
	var eventObj = flashTeamsJSON["events"][task_id];
	var title = eventObj["title"];

	if(popover==true){
		$('#task-edit-link').hide();

		//label
		label = '<input type ="text" name="eventName" id="eventName' + '" placeholder="'+title+'" >'
		$('#task_modal_Label').html(label);

        //content
        var taskOverviewForm = getTaskOverviewForm(groupNum);
		/*var taskOverviewForm = '<form name="taskOverviewForm" id="taskOverviewForm" style="margin-bottom: 5px;">'
					+'<textarea type="text"" id="descriptionInput" rows="6" placeholder="Task description ...">'+description+'</textarea>'
					+ 'Cancel'
					+'</form>';*/
		$('#task-text').html(taskOverviewForm);

		$("#edit-save-task").attr('onclick', 'saveTaskOverview('+groupNum+')');
		$("#edit-save-task").html('Save');

        $("#inputs").tagsinput();
        $("#outputs").tagsinput();
	}

}

function getTaskOverviewForm(groupNum){

var task_id = getEventJSONIndex(groupNum);
	var eventObj = flashTeamsJSON["events"][task_id];

	 var totalMinutes = eventObj["duration"];
    var groupNum = eventObj["id"];
    var title = eventObj["title"];
    var startHr = eventObj["startHr"];
    var startMin = eventObj["startMin"];
    var notes = eventObj["notes"];
    var inputs = eventObj["inputs"];
    if(!inputs) inputs = "";
    var outputs = eventObj["outputs"];
    if(!outputs) outputs = "";
    var numHours = Math.floor(totalMinutes/60);
    var minutesLeft = totalMinutes%60;
    var dri_id = eventObj.dri;
    var PC_id = eventObj.pc;
/*'<form name="taskOverviewForm" id="taskOverviewForm" style="margin-bottom: 5px;">'
					+'<textarea type="text"" id="descriptionInput" rows="6" placeholder="Task description ...">'+description+'</textarea>'
					+ 'Cancel'
					+'</form>';*/

var form ='<form name="taskOverviewForm" id="taskOverviewForm" style="margin-bottom: 5px;">'
        + '
'
        + 'Event Start:
'
        + 'Hours: <input type="number" id="startHr" placeholder="' + startHr
            + '" min="0" style="width:35px">         '
        + 'Minutes: <input type="number" id="startMin" placeholder="' + startMin
            + '" min="0" step="15" max="45" style="width:35px">
'
        + 'Total Runtime:
'
        + 'Hours: <input type = "number" id="hours" placeholder="'
            +numHours+'" min="0" style="width:35px"/>         '
        + 'Minutes: <input type = "number" id = "minutes" placeholder="'+minutesLeft
            +'" style="width:35px" min="0" step="15" max="45"/>
'
        + 'Members

'
            + writeEventMembers(eventObj)  +'
'

        + '
Project Coordinator
<select class="pcInput"'
            +' name="pcName" id="pcEvent"'
			+ 'onchange="getPC('+groupNum + ')">'+ writePCMembers(groupNum,PC_id) +'</select>'

        + '
Directly-Responsible Individual
<select class="driInput"'
            +' name="driName" id="driEvent"'
			+ 'onchange="getDRI('+groupNum + ')">'+ writeDRIMembers(groupNum,dri_id) +'</select>'

        + '
Notes:
<textarea rows="3" id="notes">' + notes + '</textarea>'
        + '
<input type="text" value="' + inputs + '" placeholder="Add input" id="inputs" />
'
        + '
<input type="text" value="' + outputs + '" placeholder="Add output" id="outputs" />

'
        + 'Cancel'
        + '</form>';

        return form;

}

function getTaskOverviewContent(groupNum){
	var task_id = getEventJSONIndex(groupNum);
	var ev = flashTeamsJSON["events"][task_id];

    var hrs = Math.floor(ev.duration/60);
    var mins = ev.duration % 60;

    var content = 'Event Start:
'
        + ev.startHr + ':'
        + ev.startMin.toFixed(0) + '
'
        +'Total Runtime:
'
        + hrs + ' hrs ' + mins + ' mins
';

    if(ev.inputs) {
        content += 'Inputs:
';
        var inputs = ev.inputs.split(",");
        for(var i=0;i<inputs.length;i++){
            content += inputs[i];
            content += "
";
        }
    }

    if(ev.outputs) {
        content += 'Outputs:
';
        var outputs = ev.outputs.split(",");
        for(var i=0;i<outputs.length;i++){
            content += outputs[i];
            content += "
";
        }
    }

    var num_members = ev.members.length;
    if(num_members > 0){
        content += 'Members:
';
        for (var j=0;j<num_members;j++){
            var member = getMemberById(ev.members[j]);
            content += member.role;
            content += '
';
        }
    }

    if (ev.pc != "" && ev.pc != undefined){
        var pc_id = parseInt (ev.pc);
        var mem = null;

        for (var i = 0; i<flashTeamsJSON["members"].length; i++){

            if(flashTeamsJSON["members"][i].id == pc_id){
                mem = flashTeamsJSON["members"][i].role;
                break;
            }
        }
          if(mem && mem != undefined){
            content += 'Project Coordinator:
';
            content += mem;
            content += '
';
        }
    }

     if (ev.dri != "" && ev.dri != undefined){
        var dri_id = parseInt (ev.dri);
        var mem = null;

        for (var i = 0; i<flashTeamsJSON["members"].length; i++){

            if(flashTeamsJSON["members"][i].id == dri_id){
                mem = flashTeamsJSON["members"][i].role;
                break;
            }
        }

        if(mem && mem != undefined){
            content += 'Directly-Responsible Individual:
';
            content += mem;
            content += '
';
        }
    }

    if (ev.content != ""){
        content += 'Notes:
';
        content += ev.notes;
        content += '
';
    }

    if (ev.outputQs){
        outputQs = ev.outputQs;
        content += "
"
        content += "Documentation Questions
";
        var eventOutputs = ev.outputs;
        if (eventOutputs != null && eventOutputs != "") {
            eventOutputs = ev.outputs.split(",");
        }
        for (i = 0; i < eventOutputs.length; i++){
            content += "" + eventOutputs[i] + "";
            for (j = 0; j < 3; j++){
                content += "
" + outputQs[eventOutputs[i]][j][0] + ":
 " + outputQs[eventOutputs[i]][j][1] + "
";
            }
        }
    }

    return content;
}

function saveTaskOverview(groupNum){
	var task_id = getEventJSONIndex(groupNum);
	var ev = flashTeamsJSON["events"][task_id];

    if($("#eventName").val() !="")
        ev.title = $("#eventName").val();

    //Get Start Time
    var startHour = $("#startHr").val();
    if (startHour == "") startHour = parseInt($("#startHr").attr("placeholder"));
    var startMin = $("#startMin").val();

    if (startMin == "") startMin = parseInt($("#startMin").attr("placeholder"));
    //newX
    startHour = parseInt(startHour);
    startMin = parseInt(startMin);
    var newX = (startHour * 100) + (startMin/15*25);
    newX = newX - (newX%(STEP_WIDTH)) - DRAGBAR_WIDTH/2;

    var eventNotes = $("#notes").val();
    var driId = getDRI(groupNum);
    var pcId = getPC(groupNum);

    var indexOfJSON = getEventJSONIndex(groupNum);
    var ev = flashTeamsJSON["events"][indexOfJSON];

    removeAllMemberCircles(ev);

    //Update members of event
    flashTeamsJSON["events"][indexOfJSON].members = [];
    for (var i = 0; i<flashTeamsJSON["members"].length; i++) {
        var member = flashTeamsJSON["members"][i];
        var memberId = member.id;
        var checkbox = $("#event" + groupNum + "member" + i + "checkbox")[0];
        if (checkbox == undefined) continue;
        if (checkbox.checked == true) {
            ev.members.push(memberId); //Update JSON
        }
    }

    //Update width
    var newHours = $("#hours").val();
    var newMin = $("#minutes").val();
    if (newHours == "") newHours = parseInt($("#hours")[0].placeholder);
    if (newMin == "") newMin = parseInt($("#minutes" )[0].placeholder);
    newMin = Math.round(parseInt(newMin)/15) * 15;

    //cannot have events shorter than 30 minutes
    if (newHours == 0 && newMin == 15){
        newMin = 30;
    }
    var newWidth = (newHours * 100) + (newMin/15*25);

    //Update JSON
    var indexOfJSON = getEventJSONIndex(groupNum);

    ev.notes = eventNotes;
    ev.dri = driId;
    ev.pc = pcId;
    ev.startHr = parseInt(startHour);
    ev.startMin = Math.round(parseInt(startMin)/15) * 15;
    ev.startTime = ev.startHr*60 + ev.startMin;
    ev.duration = durationForWidth(newWidth);
    ev.x = newX;
    ev.inputs = $('#inputs').val();
    ev.outputs = $('#outputs' ).val();

    drawEvent(ev, 0);

    updateStatus();
    //showTaskOverview(groupNum);
      $('#task_modal').modal('hide');
}<commit_msg>documentation questions all added to first task modal<commit_after>function showTaskOverview(groupNum){

	var task_id = getEventJSONIndex(groupNum);
	var eventObj = flashTeamsJSON["events"][task_id];
	var title = eventObj["title"];

	//uniq_u is null for author, we use this to decide whether to show the edit link next to project overview
	var uniq_u=getParameterByName('uniq');

	//modal label
	var label = title;
	$('#task_modal_Label').html(label);

	//modal content
	//var taskOverviewContent = '

' + description + '

';
	var taskOverviewContent = getTaskOverviewContent(groupNum);
	//$('#taskOverview').html(taskOverviewContent);
	$('#task-text').html(taskOverviewContent);

	if(in_progress != true && (uniq_u == "" || memberType == "pc" || memberType == "client") ) {
		$("#edit-save-task").css('display', '');
		$("#edit-save-task").attr('onclick', 'editTaskOverview(true,'+groupNum+')');
		$("#edit-save-task").html('Edit');

	}
	else{
		$("#edit-save-task").css('display', 'none');
		$("#hire-task").css('display','none');
		$("#delete").css('display','none');
	}

}

function editTaskOverview(popover,groupNum){

	var task_id = getEventJSONIndex(groupNum);
	var eventObj = flashTeamsJSON["events"][task_id];
	var title = eventObj["title"];

	if(popover==true){
		$('#task-edit-link').hide();

		//label
		label = '<input type ="text" name="eventName" id="eventName' + '" placeholder="'+title+'" >'
		$('#task_modal_Label').html(label);

        //content
        var taskOverviewForm = getTaskOverviewForm(groupNum);
		/*var taskOverviewForm = '<form name="taskOverviewForm" id="taskOverviewForm" style="margin-bottom: 5px;">'
					+'<textarea type="text"" id="descriptionInput" rows="6" placeholder="Task description ...">'+description+'</textarea>'
					+ 'Cancel'
					+'</form>';*/
		$('#task-text').html(taskOverviewForm);

		$("#edit-save-task").attr('onclick', 'saveTaskOverview('+groupNum+')');
		$("#edit-save-task").html('Save');

        $("#inputs").tagsinput();
        $("#outputs").tagsinput();
	}

}

function getTaskOverviewForm(groupNum){

var task_id = getEventJSONIndex(groupNum);
	var eventObj = flashTeamsJSON["events"][task_id];

	 var totalMinutes = eventObj["duration"];
    var groupNum = eventObj["id"];
    var title = eventObj["title"];
    var startHr = eventObj["startHr"];
    var startMin = eventObj["startMin"];
    var notes = eventObj["notes"];
    var inputs = eventObj["inputs"];
    if(!inputs) inputs = "";
    var outputs = eventObj["outputs"];
    if(!outputs) outputs = "";
    var numHours = Math.floor(totalMinutes/60);
    var minutesLeft = totalMinutes%60;
    var dri_id = eventObj.dri;
    var PC_id = eventObj.pc;
/*'<form name="taskOverviewForm" id="taskOverviewForm" style="margin-bottom: 5px;">'
					+'<textarea type="text"" id="descriptionInput" rows="6" placeholder="Task description ...">'+description+'</textarea>'
					+ 'Cancel'
					+'</form>';*/

var form ='<form name="taskOverviewForm" id="taskOverviewForm" style="margin-bottom: 5px;">'
        + '
'
        + 'Event Start:
'
        + 'Hours: <input type="number" id="startHr" placeholder="' + startHr
            + '" min="0" style="width:35px">         '
        + 'Minutes: <input type="number" id="startMin" placeholder="' + startMin
            + '" min="0" step="15" max="45" style="width:35px">
'
        + 'Total Runtime:
'
        + 'Hours: <input type = "number" id="hours" placeholder="'
            +numHours+'" min="0" style="width:35px"/>         '
        + 'Minutes: <input type = "number" id = "minutes" placeholder="'+minutesLeft
            +'" style="width:35px" min="0" step="15" max="45"/>
'
        + 'Members

'
            + writeEventMembers(eventObj)  +'
'

        + '
Project Coordinator
<select class="pcInput"'
            +' name="pcName" id="pcEvent"'
			+ 'onchange="getPC('+groupNum + ')">'+ writePCMembers(groupNum,PC_id) +'</select>'

        + '
Directly-Responsible Individual
<select class="driInput"'
            +' name="driName" id="driEvent"'
			+ 'onchange="getDRI('+groupNum + ')">'+ writeDRIMembers(groupNum,dri_id) +'</select>'

        + '
Notes:
<textarea rows="3" id="notes">' + notes + '</textarea>'
        + '
<input type="text" value="' + inputs + '" placeholder="Add input" id="inputs" />
'
        + '
<input type="text" value="' + outputs + '" placeholder="Add output" id="outputs" />

'
        + 'Cancel'
        + '</form>';

        return form;

}

function getTaskOverviewContent(groupNum){
	var task_id = getEventJSONIndex(groupNum);
	var ev = flashTeamsJSON["events"][task_id];

    var hrs = Math.floor(ev.duration/60);
    var mins = ev.duration % 60;

    var content = 'Event Start:
'
        + ev.startHr + ':'
        + ev.startMin.toFixed(0) + '
'
        +'Total Runtime:
'
        + hrs + ' hrs ' + mins + ' mins
';

    if(ev.inputs) {
        content += 'Inputs:
';
        var inputs = ev.inputs.split(",");
        for(var i=0;i<inputs.length;i++){
            content += inputs[i];
            content += "
";
        }
    }

    if(ev.outputs) {
        content += 'Outputs:
';
        var outputs = ev.outputs.split(",");
        for(var i=0;i<outputs.length;i++){
            content += outputs[i];
            content += "
";
        }
    }

    var num_members = ev.members.length;
    if(num_members > 0){
        content += 'Members:
';
        for (var j=0;j<num_members;j++){
            var member = getMemberById(ev.members[j]);
            content += member.role;
            content += '
';
        }
    }

    if (ev.pc != "" && ev.pc != undefined){
        var pc_id = parseInt (ev.pc);
        var mem = null;

        for (var i = 0; i<flashTeamsJSON["members"].length; i++){

            if(flashTeamsJSON["members"][i].id == pc_id){
                mem = flashTeamsJSON["members"][i].role;
                break;
            }
        }
          if(mem && mem != undefined){
            content += 'Project Coordinator:
';
            content += mem;
            content += '
';
        }
    }

     if (ev.dri != "" && ev.dri != undefined){
        var dri_id = parseInt (ev.dri);
        var mem = null;

        for (var i = 0; i<flashTeamsJSON["members"].length; i++){

            if(flashTeamsJSON["members"][i].id == dri_id){
                mem = flashTeamsJSON["members"][i].role;
                break;
            }
        }

        if(mem && mem != undefined){
            content += 'Directly-Responsible Individual:
';
            content += mem;
            content += '
';
        }
    }

    if (ev.content != ""){
        content += 'Notes:
';
        content += ev.notes;
        content += '
';
    }

    if (ev.outputQs){
        outputQs = ev.outputQs;
        content += "
"
        content += "Documentation Questions
";
        var eventOutputs = ev.outputs;
        if (eventOutputs != null && eventOutputs != "") {
            eventOutputs = ev.outputs.split(",");
        }
        for (i = 0; i < eventOutputs.length; i++){
            content += "" + eventOutputs[i] + "";
            for (j = 0; j < outputQs[eventOutputs[i]].length; j++){
                content += "
" + outputQs[eventOutputs[i]][j][0] + ":
 " + outputQs[eventOutputs[i]][j][1] + "
";
            }
        }
    }

    if (ev.docQs){
        docQs = ev.docQs;
        for (i = 0; i < docQs.length; i++){
            content += "" + docQs[i][0] + ": ";
            content += "
" + docQs[i][1] + "
";
        }
    }

    return content;
}

function saveTaskOverview(groupNum){
	var task_id = getEventJSONIndex(groupNum);
	var ev = flashTeamsJSON["events"][task_id];

    if($("#eventName").val() !="")
        ev.title = $("#eventName").val();

    //Get Start Time
    var startHour = $("#startHr").val();
    if (startHour == "") startHour = parseInt($("#startHr").attr("placeholder"));
    var startMin = $("#startMin").val();

    if (startMin == "") startMin = parseInt($("#startMin").attr("placeholder"));
    //newX
    startHour = parseInt(startHour);
    startMin = parseInt(startMin);
    var newX = (startHour * 100) + (startMin/15*25);
    newX = newX - (newX%(STEP_WIDTH)) - DRAGBAR_WIDTH/2;

    var eventNotes = $("#notes").val();
    var driId = getDRI(groupNum);
    var pcId = getPC(groupNum);

    var indexOfJSON = getEventJSONIndex(groupNum);
    var ev = flashTeamsJSON["events"][indexOfJSON];

    removeAllMemberCircles(ev);

    //Update members of event
    flashTeamsJSON["events"][indexOfJSON].members = [];
    for (var i = 0; i<flashTeamsJSON["members"].length; i++) {
        var member = flashTeamsJSON["members"][i];
        var memberId = member.id;
        var checkbox = $("#event" + groupNum + "member" + i + "checkbox")[0];
        if (checkbox == undefined) continue;
        if (checkbox.checked == true) {
            ev.members.push(memberId); //Update JSON
        }
    }

    //Update width
    var newHours = $("#hours").val();
    var newMin = $("#minutes").val();
    if (newHours == "") newHours = parseInt($("#hours")[0].placeholder);
    if (newMin == "") newMin = parseInt($("#minutes" )[0].placeholder);
    newMin = Math.round(parseInt(newMin)/15) * 15;

    //cannot have events shorter than 30 minutes
    if (newHours == 0 && newMin == 15){
        newMin = 30;
    }
    var newWidth = (newHours * 100) + (newMin/15*25);

    //Update JSON
    var indexOfJSON = getEventJSONIndex(groupNum);

    ev.notes = eventNotes;
    ev.dri = driId;
    ev.pc = pcId;
    ev.startHr = parseInt(startHour);
    ev.startMin = Math.round(parseInt(startMin)/15) * 15;
    ev.startTime = ev.startHr*60 + ev.startMin;
    ev.duration = durationForWidth(newWidth);
    ev.x = newX;
    ev.inputs = $('#inputs').val();
    ev.outputs = $('#outputs' ).val();

    drawEvent(ev, 0);

    updateStatus();
    //showTaskOverview(groupNum);
      $('#task_modal').modal('hide');
}<|endoftext|>


<commit_before>$( window ).load(function() {
  if(typeof ga === "undefined"){
    ga = function(){};
  }

  $.fn.dataTable.ext.errMode = "throw"; // See https://github.com/npct/pct-shiny/issues/419

  var toggle_panel = function(panelId, link){
    var panel = $(panelId);
    // Commment toggling as the toggle function is being handled by shinyjs
    //panel.toggle();
    if(panel.is(":visible")){
      $(link).html('Show');
    }else{
      $(link).html('Hide');
    }
  };

  $('#toggle_panel').click(function(){ toggle_panel('#input_panel', this); });
  $('#toggle_trip_menu').click(function(){ toggle_panel('#trip_menu', this); });
  $('#toggle_map_legend').click(function(){ toggle_panel('#map_legend', this); });

  $('select').addClass("form-control");
  var url_updater = function(l_map, old_region){
    var grp = l_map.layerManager.getLayerGroup("region_name");
    var current_region;
    if(grp && grp.getLayers()[0]) {
      current_region = grp.getLayers()[0].options.layerId;
    }
    if(!!old_region && !!current_region && old_region != current_region){
      var new_url = (history.state !== null) ? current_region : "../" + current_region;
      history.pushState(history.state || location.href, current_region, new_url);
      setTimeout(url_updater, 500, l_map, current_region);
    } else {
      setTimeout(url_updater, 500, l_map, current_region || old_region);
    }
  };

  var initMap = function(){
    if($(map).data('leaflet-map')){
      // l_map is the leaflet map object see http://leafletjs.com/reference.html
      var l_map = $(map).data('leaflet-map');
      L.control.scale().addTo(l_map);
      url_updater(l_map, undefined);

      $('select, input').each(function() {
        $(this).change(function(e){
          ga('send', 'event', 'controls', e.target.id , e.target.value);
        });
      });
    }
    else {
      setTimeout(initMap, 100);
    }
  };
  initMap();

  $('a[data-toggle=tab]').each(function() {
    $(this).click(function(){
      ga('send', 'event', 'nav', $(this).data('value'));
    });
  });
});
<commit_msg>DT init has changed, only set error after init<commit_after>$( window ).load(function() {
  if(typeof ga === "undefined"){
    ga = function(){};
  }
  $(".datatables").on("init.dt", function () {
    // See https://github.com/npct/pct-shiny/issues/419
    $.fn.dataTableExt.errMode = function(settings, tn, msg) { console.log(msg); };
  });

  var toggle_panel = function(panelId, link){
    var panel = $(panelId);
    // Commment toggling as the toggle function is being handled by shinyjs
    //panel.toggle();
    if(panel.is(":visible")){
      $(link).html('Show');
    }else{
      $(link).html('Hide');
    }
  };

  $('#toggle_panel').click(function(){ toggle_panel('#input_panel', this); });
  $('#toggle_trip_menu').click(function(){ toggle_panel('#trip_menu', this); });
  $('#toggle_map_legend').click(function(){ toggle_panel('#map_legend', this); });

  $('select').addClass("form-control");
  var url_updater = function(l_map, old_region){
    var grp = l_map.layerManager.getLayerGroup("region_name");
    var current_region;
    if(grp && grp.getLayers()[0]) {
      current_region = grp.getLayers()[0].options.layerId;
    }
    if(!!old_region && !!current_region && old_region != current_region){
      var new_url = (history.state !== null) ? current_region : "../" + current_region;
      history.pushState(history.state || location.href, current_region, new_url);
      setTimeout(url_updater, 500, l_map, current_region);
    } else {
      setTimeout(url_updater, 500, l_map, current_region || old_region);
    }
  };

  var initMap = function(){
    if($(map).data('leaflet-map')){
      // l_map is the leaflet map object see http://leafletjs.com/reference.html
      var l_map = $(map).data('leaflet-map');
      L.control.scale().addTo(l_map);
      url_updater(l_map, undefined);
      $('select, input').each(function() {
        $(this).change(function(e){
          ga('send', 'event', 'controls', e.target.id , e.target.value);
        });
      });
    }
    else {
      setTimeout(initMap, 100);
    }
  };
  initMap();

  $('a[data-toggle=tab]').each(function() {
    $(this).click(function(){
      ga('send', 'event', 'nav', $(this).data('value'));
    });
  });
});
<|endoftext|>


<commit_before>var GUI=new function(){var g=this;var c=[];var a="#guidat{color:#fff;position:fixed;width:280px;z-index:200;opacity:.97;top:0;left:100%;margin-left:-300px;background-color:#fff;-moz-transition:margin-top .2s ease-out;-webkit-transition:margin-top .2s ease-out;transition:margin-top .2s ease-out;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.3);-moz-box-shadow:0 0 10px rgba(0,0,0,0.3);box-shadow:0 0 10px rgba(0,0,0,0.3)}#guidat,#guidat input{font:9.5px Lucida Grande,sans-serif}#guidat-controllers{height:300px;overflow-y:auto;overflow-x:hidden;background-color:rgba(0,0,0,0.1)}#guidat-toggle{text-decoration:none;cursor:pointer;color:#fff;background-color:#222;text-align:center;display:block;padding:5px}#guidat-toggle:hover{background-color:#000}.guidat-controller{padding:3px;height:25px;clear:left;border-bottom:1px solid #222;background-color:#111}.guidat-controller,.guidat-controller input,.guidat-slider-bg,.guidat-slider-fg{-moz-transition:background-color .15s linear;-webkit-transition:background-color .15s linear;transition:background-color .15s linear}.guidat-controller.boolean:hover,.guidat-controller.function:hover{background-color:#000}.guidat-controller input{float:right;outline:none;border:0;padding:4px;margin-top:2px;background-color:#222}.guidat-controller input:hover{background-color:#444}.guidat-controller input:focus{background-color:#555}.guidat-controller.number{border-left:5px solid #00aeff}.guidat-controller.string{border-left:5px solid #1ed36f}.guidat-controller.string input{border:0;color:#1ed36f;margin-right:2px;width:148px}.guidat-controller.boolean{border-left:5px solid #54396e}.guidat-controller.function{border-left:5px solid #e61d5f}.guidat-controller.number input[type=text]{width:35px;margin-left:5px;margin-right:2px;color:#00aeff}#guidat .guidat-controller.boolean input{margin-top:6px;margin-right:2px;font-size:20px}.guidat-controller:last-child{border-bottom:none;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.5);box-shadow:0 1px 3px rgba(0,0,0,0.5)}.guidat-propertyname{padding:5px;padding-top:7px;cursor:default;display:inline-block}.guidat-slider-bg:hover,.guidat-slider-bg.active{background-color:#444}.guidat-slider-bg:hover .guidat-slider-fg,.guidat-slider-bg.active .guidat-slider-fg{background-color:#52c8ff}.guidat-slider-bg{background-color:#222;cursor:ew-resize;width:40%;margin-top:2px;float:right;height:21px}.guidat-slider-fg{background-color:#00aeff;height:20px}";this.add=function(){if(!h){i("Make sure to call GUI.start() in the window.onload function");return}var n=arguments[0];var l=arguments[1];if(d(n,l)){i('Controller for "'+l+'" already added.');return}var q=n[l];if(q==undefined){i(n+' either has no property "'+l+'", or the property is inaccessible.');return}var p=typeof q;var o=j[p];if(o==undefined){i('Cannot create controller for data type "'+p+'"');return}var m=o.apply(this,arguments);if(!m){i('Error creating controller for "'+l+'".');return}b.appendChild(m.domElement);c.push(m);return m};var j={number:function(){return k(NumberController,arguments)},string:function(){return k(StringController,arguments)},"boolean":function(){return k(BooleanController,arguments)},"function":function(){return k(FunctionController,arguments)},};var d=function(m,l){for(var n in c){if(c[n].object==m&&c[n].propertyName==l){return true}}return false};var i=function(l){if(typeof console.log=="function"){console.error("[GUI ERROR] "+l)}};var k=function(m,l){function n(){return m.apply(this,l)}n.prototype=m.prototype;return new n()};this.domElement=null;var b;var h=false;var f=false;var e=300;this.start=function(){var l=document.createElement("style");l.setAttribute("type","text/css");l.innerHTML=a;document.getElementsByTagName("head")[0].appendChild(l);this.domElement=document.createElement("div");this.domElement.setAttribute("id","guidat");b=document.createElement("div");b.setAttribute("id","guidat-controllers");toggleButton=document.createElement("a");toggleButton.setAttribute("id","guidat-toggle");toggleButton.setAttribute("href","#");toggleButton.innerHTML="Show Controls";toggleButton.addEventListener("click",function(m){g.toggle();m.preventDefault()},false);this.domElement.appendChild(b);this.domElement.appendChild(toggleButton);this.domElement.style.marginTop=-e+"px";document.body.appendChild(this.domElement);h=true};this.toggle=function(){if(f){this.hide()}else{this.show()}};this.show=function(){this.domElement.style.marginTop=0+"px";toggleButton.innerHTML="Hide Controls";f=true};this.hide=function(){this.domElement.style.marginTop=-e+"px";toggleButton.innerHTML="Show Controls";f=false}};var Slider=function(a,e,j,c,i){var e=e;var j=j;var c=c;var h=false;var f=this;var k,l;this.domElement=document.createElement("div");this.fg=document.createElement("div");this.domElement.setAttribute("class","guidat-slider-bg");this.fg.setAttribute("class","guidat-slider-fg");this.domElement.appendChild(this.fg);var b=function(m,p,n,q,o){var m=q+(o-q)*((m-p)/(n-p));if(m<q){m=q}else{if(m>o){m=o}}return m};var g=function(m){var n=curtop=0;if(m.offsetParent){do{n+=m.offsetLeft;curtop+=m.offsetTop}while(m=m.offsetParent);return[n,curtop]}};this.__defineSetter__("value",function(n){var m=b(n,e,j,0,100);this.fg.style.width=m+"%"});var d=function(m){if(!h){return}var o=g(f.domElement);var n=b(m.pageX,o[0],o[0]+f.domElement.offsetWidth,e,j);n=Math.round(n/c)*c;a.updateValue(n)};this.domElement.addEventListener("mousedown",function(m){h=true;k=l=m.pageX;f.domElement.setAttribute("class","guidat-slider-bg active");f.fg.setAttribute("class","guidat-slider-fg active");d(m)},false);document.addEventListener("mouseup",function(m){f.domElement.setAttribute("class","guidat-slider-bg");f.fg.setAttribute("class","guidat-slider-fg");h=false},false);document.addEventListener("mousemove",d,false);this.value=i};var Controller=function(){var a=null;this.setName=function(b){this.propertyNameElement.innerHTML=b};this.setValue=function(b){this.object[this.propertyName]=b;if(a!=null){a.call(this,b)}};this.getValue=function(){return this.object[this.propertyName]};this.onChange=function(b){a=b};this.makeUnselectable=function(b){b.onselectstart=function(){return false};b.style.MozUserSelect="none";b.style.KhtmlUserSelect="none";b.unselectable="on"};this.makeSelectable=function(b){b.onselectstart=function(){};b.style.MozUserSelect="auto";b.style.KhtmlUserSelect="auto";b.unselectable="off"};this.domElement=document.createElement("div");this.domElement.setAttribute("class","guidat-controller "+this.type);this.object=arguments[0];this.propertyName=arguments[1];this.propertyNameElement=document.createElement("span");this.propertyNameElement.setAttribute("class","guidat-propertyname");this.setName(this.propertyName);this.domElement.appendChild(this.propertyNameElement);this.makeUnselectable(this.domElement)};var BooleanController=function(){this.type="boolean";Controller.apply(this,arguments);var b=this;var a=document.createElement("input");a.setAttribute("type","checkbox");this.domElement.addEventListener("click",function(c){a.checked=!a.checked;c.preventDefault();b.setValue(a.checked)},false);a.addEventListener("mouseup",function(c){a.checked=!a.checked},false);this.domElement.style.cursor="pointer";this.propertyNameElement.style.cursor="pointer";this.domElement.appendChild(a)};BooleanController.prototype=new Controller();BooleanController.prototype.constructor=BooleanController;var FunctionController=function(){this.type="function";var a=this;Controller.apply(this,arguments);this.domElement.addEventListener("click",function(){a.object[a.propertyName].call(a.object)},false);this.domElement.style.cursor="pointer";this.propertyNameElement.style.cursor="pointer"};FunctionController.prototype=new Controller();FunctionController.prototype.constructor=FunctionController;var NumberController=function(){this.type="number";Controller.apply(this,arguments);var f=this;var a=false;var g=false;var i=py=0;var e=arguments[2];var j=arguments[3];var d=arguments[4];if(!d){if(e&&j){d=(j-e)*0.01}else{d=1}}var c=document.createElement("input");c.setAttribute("id",this.propertyName);c.setAttribute("type","text");c.setAttribute("value",this.getValue());if(d){c.setAttribute("step",d)}this.domElement.appendChild(c);var b;if(e!=undefined&&j!=undefined){b=new Slider(this,e,j,d,this.getValue());this.domElement.appendChild(b.domElement)}c.addEventListener("blur",function(k){var l=parseFloat(this.value);if(!isNaN(l)){f.updateValue(l)}else{this.value=f.getValue()}},false);c.addEventListener("mousewheel",function(k){k.preventDefault();this.updateValue(f.getValue()+Math.abs(k.wheelDeltaY)/k.wheelDeltaY*d);return false},false);c.addEventListener("mousedown",function(k){py=i=k.pageY;g=true;document.addEventListener("mousemove",h,false)},false);document.addEventListener("mouseup",function(k){document.removeEventListener("mousemove",h,false);f.makeSelectable(GUI.domElement);f.makeSelectable(c);if(g&&!a){c.focus();c.select()}a=false;g=false},false);if(navigator.appVersion.indexOf("chrome")!=-1){document.addEventListener("mouseout",function(k){document.removeEventListener("mousemove",h,false)},false)}var h=function(m){a=true;m.preventDefault();f.makeUnselectable(GUI.domElement);f.makeUnselectable(c);py=i;i=m.pageY;var k=py-i;var l=f.getValue()+k*d;f.updateValue(l);return false};this.updateValue=function(k){k=parseFloat(k);if(e!=undefined&&k<=e){k=e}else{if(j!=undefined&&k>=j){k=j}}f.setValue(k);c.value=f.getValue();if(b){b.value=f.getValue()}}};NumberController.prototype=new Controller();NumberController.prototype.constructor=NumberController;var StringController=function(){this.type="string";var c=this;Controller.apply(this,arguments);var b=document.createElement("input");var a=this.getValue();b.setAttribute("value",a);b.setAttribute("spellcheck","false");this.domElement.addEventListener("mouseup",function(){b.focus();b.select()},false);b.addEventListener("keyup",function(){c.setValue(b.value)},false);this.domElement.appendChild(b)};StringController.prototype=new Controller();StringController.prototype.constructor=StringController;<commit_msg>removed gui.min.js from branch and synced with versions branch<commit_after><|endoftext|>


<commit_before>
var venacava = require('./venacava.js')
, Core = venacava.Core
, Model = venacava.Model
, redis = require('redis')
, assert = require('assert')
, EventEmitter = require('events').EventEmitter
;

var redisClient = function () {
    return redis.createClient();
};

var randomId = function () {
    return 'test' + Math.floor(Math.random() * 1000000);
};

describe('instance', function () {

    var redis
    , newModel = function (proto) {
	return new Model(redis, proto);
    }
    ;

    before(function(done) {
	redis = redisClient();
	return done();
    });

    it('should be constructable', function () {
	assert(newModel({}), 'unable to create a new model');
    });

    describe('#create', function () {

	it('should exist and create a new instance', function () {
	    assert(newModel({}).create({}));
	});

	describe('-> instance', function () {

	    it('should should have a core', function () {
		var instance = newModel({}).create({});
		assert(instance.hasOwnProperty('core'), 'new instance did not have a core.');
		assert.equal(typeof instance.core, 'object', 'new instance core was not an object');
	    });

	    it('should have initial values equal to the creation arguments', function () {
		var attrs = {x: 1}
		, instance = newModel({}).create(attrs)
		;
		assert.deepEqual(instance.core.toJSON(), attrs, 'initial core did not have provided attributes.');
	    });

	    describe(':defaults', function () {
		it('should have default values from instance creation', function () {
		    var attrs = {x: 1}
		    , instance = newModel({
			defaults: attrs
		    }).create({})
		    ;
		    assert.deepEqual(instance.core.toJSON(), attrs, 'initial core did not have default attributes.');
		});

		it ('should override defaults with creation parameter', function () {
		    var attrs = {x: 2}
		    , instance = newModel({
			defaults: {
			    x: 1
			    , y: 1
			}
		    }).create(attrs)
		    ;
		    assert.deepEqual(instance.core.toJSON(), {
			x: 2
			, y: 1
		    }, 'initial core defaults were not overriden by creation argument.');
		    assert.deepEqual(attrs, {x: 2}, 'creation argument was mutated');
		});
	    });

	    describe(':initialize', function () {

		it('should be called on creation', function (done) {
		    newModel({
			initialize: function () {
			    return done();
			}
		    }).create({});
		});

		it('should be called with an initialized core', function (done) {
		    var attrs = {x: 1};
		    newModel({
			defaults: attrs
			, initialize: function () {
			    assert.equal(typeof this.core, 'object', 'initialze called with a core which was not an object');
			    assert.deepEqual(this.core.toJSON(), attrs, 'core was not properly initialized before initialize method was called');
			    return done();
			}
		    }).create({});
		});

		it('should be called synchronously', function () {
		    var instance = newModel({
			initialize: function () {
			    this.initialized = true;
			}
		    }).create({});
		    assert(instance.initialized, 'create callback called before initialize');
		});
	    });

	    describe(':methods', function () {
		it('should exist on created instances', function () {
		    var instance = newModel({
			method: function (arg) {
			    assert(this.core, 'method was not called with a context containing the core.');
			    assert.equal(arg, 1, 'method was not called with arguments');
			}
		    }).create({});
		    assert(instance.method, 'instance was not created with the defined method');
		    assert.equal(typeof instance.method, 'function', 'instance was not created with the defined method as a function');
		    instance.method(1)
		});
	    });

	});

    // 	describe(':async', function () {
    // 	    it('should be provided', function (done) {
    // 		newModel({}).create({}, done);
    // 	    });

    // 	    it('should be called after the core has been stored', function (done) {
    // 		var attrs = {x: 1};
    // 		newModel({}).create(attrs, function (err, instance) {
    // 		    assert.ifError(err);
    // 		    var dupCore = new Core(instance.core.channel, redis);
    // 		    dupCore.fetch(function (err) {
    // 			assert.ifError(err);
    // 			assert.deepEqual(dupCore.toJSON(), attrs);
    // 			return done();
    // 		    });
    // 		});
    // 	    });

    // 	    it('should be called after initialization', function (done) {
    // 		var instance = newModel({
    // 		    initialize: function () {
    // 			this.initialized = true;
    // 		    }
    // 		}).create({}, function () {
    // 		    assert(this.initialized, 'create callback called before initialize');
    // 		});
    // 	    });
    // 	});

    });

    describe('#get', function () {
	it('should retrieve an object with a core of the same channel', function () {
	    var model = newModel({});
	    model.create({}, function (err, instance) {
		assert.ifError(err);
		var dup = model.get(instance.core.channel);
		assert.equal(dup.core.channel, instance.core.channel, 'fetched channel was not correct.');
	    });
	});
    });

    describe(':initialize', function () {
	it('should not be called by fetch', function () {
	    var model = newModel({
		initialize: function () {
		    this.initialized = true;
		}
	    });
	    model.create({}, function (err, instance) {
		var dup = model.get(instance.core.channel);
		assert(!dup.initialized);
	    });
	});
    });

    describe(':methods', function () {
	it('should exist on gotten instances', function () {
	    var model = newModel({
		method: function (arg) {
		    assert(this.core, 'method was not called with a context containing the core.');
		    assert.equal(arg, 1, 'method was not called with arguments');
		}
	    });

	    var instance = model.create({})
	    , dup = model.get(instance.core.channel)
	    ;
	    assert(dup.method, 'instance was not gotten with the defined method');
	    assert.equal(typeof dup.method, 'function', 'instance was not gotten with the defined method as a function');
	    dup.method(1)
	});
    });
});
<commit_msg>Add tests for models to have a proto property.<commit_after>
var venacava = require('./venacava.js')
, Core = venacava.Core
, Model = venacava.Model
, redis = require('redis')
, assert = require('assert')
, EventEmitter = require('events').EventEmitter
;

var redisClient = function () {
    return redis.createClient();
};

var randomId = function () {
    return 'test' + Math.floor(Math.random() * 1000000);
};

describe('Model', function () {

    var redis
    , newModel = function (proto) {
	return new Model(redis, proto);
    }
    ;

    before(function(done) {
	redis = redisClient();
	return done();
    });

    it('should be constructable', function () {
	assert(newModel({}), 'unable to create a new model');
    });

    describe('#proto', function () {
	it('should exist', function () {
	    assert(newModel({}).proto, 'model did not have a proto property.');
	});

	it('should have the functions from the construction argument', function () {
	    assert(newModel({
		method: function () {}
	    }).proto.method, 'model proto did not have the argument\'s');
	});
    });

    describe('#create', function () {

	it('should exist and create a new instance', function () {
	    assert(newModel({}).create({}));
	});

	describe('-> instance', function () {

	    it('should should have a core', function () {
		var instance = newModel({}).create({});
		assert(instance.hasOwnProperty('core'), 'new instance did not have a core.');
		assert.equal(typeof instance.core, 'object', 'new instance core was not an object');
	    });

	    it('should have initial values equal to the creation arguments', function () {
		var attrs = {x: 1}
		, instance = newModel({}).create(attrs)
		;
		assert.deepEqual(instance.core.toJSON(), attrs, 'initial core did not have provided attributes.');
	    });

	    describe(':defaults', function () {
		it('should have default values from instance creation', function () {
		    var attrs = {x: 1}
		    , instance = newModel({
			defaults: attrs
		    }).create({})
		    ;
		    assert.deepEqual(instance.core.toJSON(), attrs, 'initial core did not have default attributes.');
		});

		it ('should override defaults with creation parameter', function () {
		    var attrs = {x: 2}
		    , instance = newModel({
			defaults: {
			    x: 1
			    , y: 1
			}
		    }).create(attrs)
		    ;
		    assert.deepEqual(instance.core.toJSON(), {
			x: 2
			, y: 1
		    }, 'initial core defaults were not overriden by creation argument.');
		    assert.deepEqual(attrs, {x: 2}, 'creation argument was mutated');
		});
	    });

	    describe(':initialize', function () {

		it('should be called on creation', function (done) {
		    newModel({
			initialize: function () {
			    return done();
			}
		    }).create({});
		});

		it('should be called with an initialized core', function (done) {
		    var attrs = {x: 1};
		    newModel({
			defaults: attrs
			, initialize: function () {
			    assert.equal(typeof this.core, 'object', 'initialze called with a core which was not an object');
			    assert.deepEqual(this.core.toJSON(), attrs, 'core was not properly initialized before initialize method was called');
			    return done();
			}
		    }).create({});
		});

		it('should be called synchronously', function () {
		    var instance = newModel({
			initialize: function () {
			    this.initialized = true;
			}
		    }).create({});
		    assert(instance.initialized, 'create callback called before initialize');
		});
	    });

	    describe(':methods', function () {
		it('should exist on created instances', function () {
		    var instance = newModel({
			method: function (arg) {
			    assert(this.core, 'method was not called with a context containing the core.');
			    assert.equal(arg, 1, 'method was not called with arguments');
			}
		    }).create({});
		    assert(instance.method, 'instance was not created with the defined method');
		    assert.equal(typeof instance.method, 'function', 'instance was not created with the defined method as a function');
		    instance.method(1)
		});
	    });

	});

    // 	describe(':async', function () {
    // 	    it('should be provided', function (done) {
    // 		newModel({}).create({}, done);
    // 	    });

    // 	    it('should be called after the core has been stored', function (done) {
    // 		var attrs = {x: 1};
    // 		newModel({}).create(attrs, function (err, instance) {
    // 		    assert.ifError(err);
    // 		    var dupCore = new Core(instance.core.channel, redis);
    // 		    dupCore.fetch(function (err) {
    // 			assert.ifError(err);
    // 			assert.deepEqual(dupCore.toJSON(), attrs);
    // 			return done();
    // 		    });
    // 		});
    // 	    });

    // 	    it('should be called after initialization', function (done) {
    // 		var instance = newModel({
    // 		    initialize: function () {
    // 			this.initialized = true;
    // 		    }
    // 		}).create({}, function () {
    // 		    assert(this.initialized, 'create callback called before initialize');
    // 		});
    // 	    });
    // 	});

    });

    describe('#get', function () {
	it('should retrieve an object with a core of the same channel', function () {
	    var model = newModel({});
	    model.create({}, function (err, instance) {
		assert.ifError(err);
		var dup = model.get(instance.core.channel);
		assert.equal(dup.core.channel, instance.core.channel, 'fetched channel was not correct.');
	    });
	});
    });

    describe(':initialize', function () {
	it('should not be called by fetch', function () {
	    var model = newModel({
		initialize: function () {
		    this.initialized = true;
		}
	    });
	    model.create({}, function (err, instance) {
		var dup = model.get(instance.core.channel);
		assert(!dup.initialized);
	    });
	});
    });

    describe(':methods', function () {
	it('should exist on gotten instances', function () {
	    var model = newModel({
		method: function (arg) {
		    assert(this.core, 'method was not called with a context containing the core.');
		    assert.equal(arg, 1, 'method was not called with arguments');
		}
	    });

	    var instance = model.create({})
	    , dup = model.get(instance.core.channel)
	    ;
	    assert(dup.method, 'instance was not gotten with the defined method');
	    assert.equal(typeof dup.method, 'function', 'instance was not gotten with the defined method as a function');
	    dup.method(1)
	});
    });
});
<|endoftext|>


<commit_before>/*
This file gives functions to aid in drawing texts and symbols on the canvas in
the correct locations on the scaled bookkeeping image.
*/

var scale;
var canvas;
var context;
var width;
var height;
var canvasReady;
var fontFamily;
var fontSize;
var startingData;
var startingJSON;

/*
Prepares the canvas to be drawn on by storing the canvas object, context, width,
and height as well as sets canvasReady to true.
*/
function init()
{
    scale = 3;
    canvas = document.getElementById("myCanvas");
    fontFamily = "Arial";

    width = canvas.width;
    height = canvas.height;
    canvas.width = width * scale;
    canvas.height = height * scale;

    context = canvas.getContext("2d");
    fontSize = 12;
    context.font = "12px Arial";
    context.fillStyle = "black";
    canvasReady = true;

    canvas.addEventListener('mousedown', function(event) {
    openMenu();
        }, false);

    var test = '{"teamA":"TEAM A", "teamB":"TEAM B", "aLineup":[1,2,3,4,5,6,7], "bLineup":[7,6,5,4,3,2,1], "timeoutCap":2, "aServe":false, "module":"../Javascript/modules/CIF_module3.1.js"}';
    setStartingData(test, 'nourl');
}

/*
Inputs the starting match data.
*/
function setStartingData(data, url)
{
    startingJSON = data;
    startingData = JSON.parse(data);

    if(startingData.input)
	loadGameData(startingData.input);

    var script = document.createElement('script');
    script.onload = function() {
	    drawText(.05,.05,'test');
      onStart();

    };
    if(url == "nourl")
        script.src = startingData.module;
    else
        script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);

}

/*
Draws text based on percentages from the left and top of the screen.
xPercent: horizontal percentage from the left.
yPercent: vertical percentage from the top.
text: text being drawn.
*/
function drawText(xPercent, yPercent, text)
{
    if(!canvasReady)
        return;
    var xLocation = xPercent * width * scale;
    var yLocation = yPercent * height * scale;
    context.fillText(text, xLocation, yLocation);
}

/*
Draws text based on percentages from the left and top of the screen with a circle around the text.
xPercent: horizontal percentage from the left.
yPercent: vertical percentage from the top.
text: text being drawn.
*/
function circleText(xPercent, yPercent, text)
{
    if(!canvasReady)
        return;
    drawText(xPercent, yPercent, text);
    var xLocation = xPercent * width * scale;
    var yLocation = yPercent * height * scale;

    var fontWidth = context.measureText(text).width * 2;
    var fontHeight = context.measureText("M").width * 2;
    drawEllipse(xLocation - (fontWidth / 4), yLocation - (fontHeight / 1.5), fontWidth, fontHeight);
}

/*
Draws text based on percentages from the left and top of the screen with a triangle around the text.
xPercent: horizontal percentage from the left.
yPercent: vertical percentage from the top.
text: text being drawn.
*/
function triangleText(xPercent, yPercent, text)
{
    if(!canvasReady)
        return;
    var xLocation = xPercent * width * scale;
    var yLocation = yPercent * height * scale;
    context.fillText(text, xLocation, yLocation);

    var fontWidth = context.measureText(text).width * 2;
    var fontHeight = context.measureText("M").width * 2;
    drawTriangle(xLocation - (fontWidth / 4), yLocation - (fontHeight / 1.25), fontWidth, fontHeight);
}

function measureText(text)
{
    if(!canvasReady)
        return -1;
    return context.measureText(text).width;
}

function clearRect(xPercent, yPercent, xPercent2, yPercent2)
{
    if(!canvasReady)
        return;
    var dx = xPercent2 - xPercent;
    var dy = yPercent2 - yPercent;
    context.clearRect(xPercent * width * scale, yPercent * height * scale, dx * scale * width, dy * height * scale);
}

/*
Increases the density scale by 1.
*/
function sharpen()
{
    scale++;
    setFontSize(scale * fontSize);
}

/*
Decreases the density scale by 1.
*/
function blur()
{
    scale--;
    setFontSize(scale * fontSize);
}

/*
Sets the size of the context's font.
size: the new font size (should be a number).
*/
function setFontSize(size)
{
    fontSize = size;
    context.font = size + "px " + fontFamily;
}

/*
Sets the color of the context's font.
color: the new color.
*/
function setFontColor(color)
{
    context.fillStyle = color;
}

/*
Draws an ellipse based on a rectangular boundary.
x: left of bounds.
y: top of bounds.
width: width of the bounding rectangle.
height: height of the bounding rectangle.
*/
function drawEllipse(x, y, width, height) {

    context.beginPath();
    context.moveTo(x + (width / 2), y);

    context.bezierCurveTo(
    x + width, y, x + width, y + height, x + (width / 2), y + height);

    context.bezierCurveTo(
    x, y + height, x, y, x + (width/2), y);

    context.stroke();
    context.closePath();
}

function drawTriangle(x, y, width, height) {

    context.beginPath();

    context.moveTo(x + (width/2), y);

    context.lineTo(x, y + height);
    context.lineTo(x + width, y + height);
    context.lineTo(x + (width/2), y);

    context.stroke();
    context.closePath();
}
<commit_msg>Update VBCanvasTest2.0.js<commit_after>/*
This file gives functions to aid in drawing texts and symbols on the canvas in
the correct locations on the scaled bookkeeping image.
*/

var scale;
var canvas;
var context;
var width;
var height;
var canvasReady;
var fontFamily;
var fontSize;
var startingData;
var startingJSON;

/*
Prepares the canvas to be drawn on by storing the canvas object, context, width,
and height as well as sets canvasReady to true.
*/
function init()
{
    scale = 3;
    canvas = document.getElementById("myCanvas");
    fontFamily = "Arial";

    width = canvas.width;
    height = canvas.height;
    canvas.width = width * scale;
    canvas.height = height * scale;

    context = canvas.getContext("2d");
    fontSize = 12;
    context.font = "12px Arial";
    context.fillStyle = "black";
    canvasReady = true;

    canvas.addEventListener('mousedown', function(event) {
    openMenu();
        }, false);

    var test = '{"teamA":"TEAM A", "teamB":"TEAM B", "aLineup":[1,2,3,4,5,6,7], "bLineup":[7,6,5,4,3,2,1], "timeoutCap":2, "aServe":false, "module":"../Javascript/modules/CIF_module3.2.js"}';
    setStartingData(test, 'nourl');
}

/*
Inputs the starting match data.
*/
function setStartingData(data, url)
{
    startingJSON = data;
    startingData = JSON.parse(data);

    if(startingData.input)
	loadGameData(startingData.input);

    var script = document.createElement('script');
    script.onload = function() {
	    drawText(.05,.05,'test');
      onStart();

    };
    if(url == "nourl")
        script.src = startingData.module;
    else
        script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);

}

/*
Draws text based on percentages from the left and top of the screen.
xPercent: horizontal percentage from the left.
yPercent: vertical percentage from the top.
text: text being drawn.
*/
function drawText(xPercent, yPercent, text)
{
    if(!canvasReady)
        return;
    var xLocation = xPercent * width * scale;
    var yLocation = yPercent * height * scale;
    context.fillText(text, xLocation, yLocation);
}

/*
Draws text based on percentages from the left and top of the screen with a circle around the text.
xPercent: horizontal percentage from the left.
yPercent: vertical percentage from the top.
text: text being drawn.
*/
function circleText(xPercent, yPercent, text)
{
    if(!canvasReady)
        return;
    drawText(xPercent, yPercent, text);
    var xLocation = xPercent * width * scale;
    var yLocation = yPercent * height * scale;

    var fontWidth = context.measureText(text).width * 2;
    var fontHeight = context.measureText("M").width * 2;
    drawEllipse(xLocation - (fontWidth / 4), yLocation - (fontHeight / 1.5), fontWidth, fontHeight);
}

/*
Draws text based on percentages from the left and top of the screen with a triangle around the text.
xPercent: horizontal percentage from the left.
yPercent: vertical percentage from the top.
text: text being drawn.
*/
function triangleText(xPercent, yPercent, text)
{
    if(!canvasReady)
        return;
    var xLocation = xPercent * width * scale;
    var yLocation = yPercent * height * scale;
    context.fillText(text, xLocation, yLocation);

    var fontWidth = context.measureText(text).width * 2;
    var fontHeight = context.measureText("M").width * 2;
    drawTriangle(xLocation - (fontWidth / 4), yLocation - (fontHeight / 1.25), fontWidth, fontHeight);
}

function measureText(text)
{
    if(!canvasReady)
        return -1;
    return context.measureText(text).width;
}

function clearRect(xPercent, yPercent, xPercent2, yPercent2)
{
    if(!canvasReady)
        return;
    var dx = xPercent2 - xPercent;
    var dy = yPercent2 - yPercent;
    context.clearRect(xPercent * width * scale, yPercent * height * scale, dx * scale * width, dy * height * scale);
}

/*
Increases the density scale by 1.
*/
function sharpen()
{
    scale++;
    setFontSize(scale * fontSize);
}

/*
Decreases the density scale by 1.
*/
function blur()
{
    scale--;
    setFontSize(scale * fontSize);
}

/*
Sets the size of the context's font.
size: the new font size (should be a number).
*/
function setFontSize(size)
{
    fontSize = size;
    context.font = size + "px " + fontFamily;
}

/*
Sets the color of the context's font.
color: the new color.
*/
function setFontColor(color)
{
    context.fillStyle = color;
}

/*
Draws an ellipse based on a rectangular boundary.
x: left of bounds.
y: top of bounds.
width: width of the bounding rectangle.
height: height of the bounding rectangle.
*/
function drawEllipse(x, y, width, height) {

    context.beginPath();
    context.moveTo(x + (width / 2), y);

    context.bezierCurveTo(
    x + width, y, x + width, y + height, x + (width / 2), y + height);

    context.bezierCurveTo(
    x, y + height, x, y, x + (width/2), y);

    context.stroke();
    context.closePath();
}

function drawTriangle(x, y, width, height) {

    context.beginPath();

    context.moveTo(x + (width/2), y);

    context.lineTo(x, y + height);
    context.lineTo(x + width, y + height);
    context.lineTo(x + (width/2), y);

    context.stroke();
    context.closePath();
}
<|endoftext|>


<commit_before>function extractEmails(text) {
  return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
}

function getDataForUser(username, callback) {
  $.get("/user?id=" + username, function(data) {
    var created = 0;
    var karma = 0;
    var bio = "";
    var avatar_url = null;

    try {
      // Loop through trs:
      $(data).find('tr').each(function() {
        if ($(this).find('td').length == 2) {
          var key = $(this).find('td').eq(0).text().trim();
          var value = $(this).find('td').eq(1).text().trim();

          if (key == "created:") {
            created = value;
          }

          if (key == "karma:") {
            karma = value;
          }

          if (key == "about:") {
            bio = $(this).find('td').eq(1).html().trim();
          }
        }
      });

      // Try and extract emails from bio:
      var emails = extractEmails(bio);
      if (emails && emails.length > 0) {
        var email = emails[0];
        var hash = CryptoJS.MD5(email);
        avatar_url = "http://gravatar.com/avatar/" + hash + "?s=80&d=mm"
      }

      callback({
        username: username,
        karma: karma,
        bio: bio,
        avatar: avatar_url,
        account_age: created,
      });
    } catch(err) {
      console.log(err);
      return callback(null);
    }
  });
}

function renderRateLimited() {
  return "
Unfortunately, you've been temporarily rate-limited for user profiles.
";
}

function renderLoadingTemplate() {
  var imgURL = chrome.extension.getURL("img/loading.gif");
  var html = "

";
  return html;
}

function renderProfileTemplate(data) {
  // Format bio:
  var bio = data["bio"].replace(/\n/g, "
");

  // Get avatar URL:
  var avatarUrl = chrome.extension.getURL("img/profile.png");
  if (data["avatar"]) {
    avatarUrl = data["avatar"];
  }

  // Create HTML:
  var html = "";
  html += "
";
  html += "
";
  html += "

";

  html += "
";
  html += "
" + data["username"] + "
";
  html += "
Karma: " + data["karma"] + "
";
  html += "
Created: " + data["account_age"] + "
";
  html += "
";
  html += "
";

  html += "
";
  html += "
Bio:
";
  html += "
" + bio + "
";
  html += "
";

  html += "
";
  html += "    Submissions";
  html += "    Comments";
  html += "
";
  html += "
";

  return html;
}

$(function() {
  // Loop through links where user profile links are:
  $('.comhead a, .subtext a').each(function() {
    // Check if link is a user profile:
    var link_src = $(this).attr('href');
    if (link_src.substr(0, 8) != "user?id=") {
      return;
    }

    // Bind to link:
    var drop = new Drop({
      target: this,
      content: renderLoadingTemplate(),
      position: 'bottom left',
      classes: 'drop-theme-arrows-bounce',
      openOn: 'hover'
    });

    // Save link for use in callback:
    var link = $(this);
    var username = $(this).attr('href').substr(8)

    // When popover is opened, fetch the user's info:
    drop.on('open', function() {
      getDataForUser(username, function(data) {
        if (!data) {
          $(drop.content).html(renderRateLimited());
        } else {
          $(drop.content).html(renderProfileTemplate(data));
        }
      });
    });
  });
});<commit_msg>Use Github avatars too if possible<commit_after>function extractEmails(text) {
  return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
}

function extractGithubs(text) {
  return text.match(/github.com\/([^\/ \n]*)/gi);
}

function getDataForUser(username, callback) {
  $.get("/user?id=" + username, function(data) {
    var created = 0;
    var karma = 0;
    var bio = "";
    var avatar_url = null;

    try {
      // Loop through trs:
      $(data).find('tr').each(function() {
        if ($(this).find('td').length == 2) {
          var key = $(this).find('td').eq(0).text().trim();
          var value = $(this).find('td').eq(1).text().trim();

          if (key == "created:") {
            created = value;
          }

          if (key == "karma:") {
            karma = value;
          }

          if (key == "about:") {
            bio = $(this).find('td').eq(1).html().trim();
          }
        }
      });

      // Try and get Github account (for avatar):
      var githubs = extractGithubs(bio);
      console.log("here")
      console.log(bio)
      console.log(githubs);
      if (githubs && githubs.length > 0) {
        var github_username = githubs[0].trim().replace("github.com/", "");
        avatar_url = "https://avatars.githubusercontent.com/" + github_username
      }

      // Try and extract emails from bio:
      if (avatar_url == null) {
        var emails = extractEmails(bio);
        if (emails && emails.length > 0) {
          var email = emails[0];
          var hash = CryptoJS.MD5(email);
          avatar_url = "http://gravatar.com/avatar/" + hash + "?s=80&d=mm"
        }
      }

      // Call callback with data:
      callback({
        username: username,
        karma: karma,
        bio: bio,
        avatar: avatar_url,
        account_age: created,
      });
    } catch(err) {
      console.log(err);
      return callback(null);
    }
  });
}

function renderRateLimited() {
  return "
Unfortunately, you've been temporarily rate-limited for user profiles.
";
}

function renderLoadingTemplate() {
  var imgURL = chrome.extension.getURL("img/loading.gif");
  var html = "

";
  return html;
}

function renderProfileTemplate(data) {
  // Format bio:
  var bio = data["bio"].replace(/\n/g, "
");

  // Get avatar URL:
  var avatarUrl = chrome.extension.getURL("img/profile.png");
  if (data["avatar"]) {
    avatarUrl = data["avatar"];
  }

  // Create HTML:
  var html = "";
  html += "
";
  html += "
";
  html += "

";

  html += "
";
  html += "
" + data["username"] + "
";
  html += "
Karma: " + data["karma"] + "
";
  html += "
Created: " + data["account_age"] + "
";
  html += "
";
  html += "
";

  html += "
";
  html += "
Bio:
";
  html += "
" + bio + "
";
  html += "
";

  html += "
";
  html += "    Submissions";
  html += "    Comments";
  html += "
";
  html += "
";

  return html;
}

$(function() {
  // Loop through links where user profile links are:
  $('.comhead a, .subtext a').each(function() {
    // Check if link is a user profile:
    var link_src = $(this).attr('href');
    if (link_src.substr(0, 8) != "user?id=") {
      return;
    }

    // Bind to link:
    var drop = new Drop({
      target: this,
      content: renderLoadingTemplate(),
      position: 'bottom left',
      classes: 'drop-theme-arrows-bounce',
      openOn: 'hover'
    });

    // Save link for use in callback:
    var link = $(this);
    var username = $(this).attr('href').substr(8)

    // When popover is opened, fetch the user's info:
    drop.on('open', function() {
      getDataForUser(username, function(data) {
        if (!data) {
          $(drop.content).html(renderRateLimited());
        } else {
          $(drop.content).html(renderProfileTemplate(data));
        }
      });
    });
  });
});<|endoftext|>