<commit_before>describe('trend performance', function() {

  function FrameRateTimer( _start) {
    this.start = _start
    this.frames = 0
    this.end = _start
  }
  FrameRateTimer.prototype.rate = function() {
    var elapsed = this.elapsed() / 1000.0
    return elapsed > 0 ? (this.frames / elapsed).toFixed(1)
      : 0
  }
  FrameRateTimer.prototype.frame = function( now) {
    this.frames ++
    this.end = now
  }
  FrameRateTimer.prototype.elapsed = function() {
    return this.end - this.start
  }
  FrameRateTimer.prototype.reset = function(now) {
    this.frames = 0
    this.start = now
    this.end = now
  }

  var chartDiv
  var selection
  function getData( count) {
    var i = 0,
        time = 0, //new Date().getTime()
        data = []

    for( i = 0; i < count; i++) {
      data.push( {date: time, y: i + Math.random()})
      time += 1000
    }
    return data
  }
  var dataCount = 4000,
      data = [ getData( dataCount) ]

  var accessX1 = function(d) { return d.date; }
  var accessY1 = function(d) { return d.y; }
  var accessSeriesData = function(s, i) { return s}
  var config = {
    x1:         accessX1,
    y1:         accessY1,
    seriesData: accessSeriesData
  }

  beforeEach(function() {
    chartDiv = affix('.chart-div[style="width: 600px; height: 400px"]')
    selection = d3.select(".chart-div")
  })

  describe("Chart update", function() {
    var originalTimeout;
    beforeEach(function() {
      originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
      jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
    });

    it("should handle chart updates with reasonable frame rate", function(done) {
      selection.datum(data)
      var chart = d3.trait(d3.trait.chart.base, config)
        .trait(d3.trait.scale.time, {axis: 'x1'})
        .trait(d3.trait.scale.linear, {axis: 'y1'})
//        .trait(d3.trait.axis.time.month, {axis: 'x1'})
//        .trait(d3.trait.axis.linear, {axis: 'y1'})
        .trait(d3.trait.chart.line)
        .call(selection)

      var div = selection[0][0]
      var chartGroup = div._chartGroup[0][0]

      var chartInstanceGroup = chartGroup.firstChild
      expect(chartInstanceGroup).toBeElement("g.chart-line")
      expect(chartInstanceGroup.childElementCount).toBe(data.length)

      var seriesGroup = chartInstanceGroup.firstChild
      expect(seriesGroup).toBeElement("g.series")
      expect(seriesGroup.childElementCount).toBe(1)

      var path = seriesGroup.firstChild
      expect(path).toBeElement("path.line")

      var frameRateDone = false,
          now = Date.now(),
          timerTotal = new FrameRateTimer( now),
          timerOneSecond = new FrameRateTimer( now),
          timings = []

      console.log( 'now = ' + now)
      function animationFrame() {
        if( ! frameRateDone) {
          var now = Date.now()

          timerTotal.frame( now)
          timerOneSecond.frame( now)
          if( timerOneSecond.elapsed() >= 1000) {
            timings.push( timerOneSecond.rate())
            timerOneSecond.reset( now)
          }
          requestAnimationFrame(animationFrame)
        }
      }
      requestAnimationFrame(animationFrame)

      function startUpdates() {

        var intervalId = setInterval( function() {
          var series = data[0],
              length = series.length,
              last = series[ length-1],
              rate = timings.length > 0 ? timings[timings.length-1] : '-'

          console.log( 'interval ' + last.y + ', timerOneSecond.rate: ' + rate )
          if( length < dataCount + 21) {
            series.push( {date: last.date+500, y: last.y+1+Math.random()})
            chart.update( "trend")
          } else {
            clearInterval( intervalId)
            frameRateDone = true
            console.log( 'Framerates = ' + timings)
            console.log( 'Framerate Average = ' + timerTotal.rate())
            done()
          }
        }, 500)
      }

      setTimeout( startUpdates, 1000)

    });

    afterEach(function() {
      jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
    });
  });

});

<commit_msg>Added brush chart to trendPerformance test.<commit_after>describe('trend performance', function() {

  function FrameRateTimer( _start) {
    this.start = _start
    this.frames = 0
    this.end = _start
  }
  FrameRateTimer.prototype.rate = function() {
    var elapsed = this.elapsed() / 1000.0
    return elapsed > 0 ? Math.round(this.frames / elapsed)
      : 0
  }
  FrameRateTimer.prototype.frame = function( now) {
    this.frames ++
    this.end = now
  }
  FrameRateTimer.prototype.elapsed = function() {
    return this.end - this.start
  }
  FrameRateTimer.prototype.reset = function(now) {
    this.frames = 0
    this.start = now
    this.end = now
  }

  var chartDiv, brushDiv
  var selection, brushSelection
  function getData( count) {
    var i = 0,
        time = 0, //new Date().getTime()
        data = []

    for( i = 0; i < count; i++) {
      data.push( {date: time, y: i + Math.random()})
      time += 1000
    }
    return data
  }
  var dataCount = 5000,
      data = [ getData( dataCount) ]

  var accessX1 = function(d) { return d.date; }
  var accessY1 = function(d) { return d.y; }
  var accessSeriesData = function(s, i) { return s}
  var config = {
    x1:         accessX1,
    y1:         accessY1,
    seriesData: accessSeriesData
  }

  function makeBrushTraits( target) {
    return d3.trait( d3.trait.chart.base, config )
      .trait( d3.trait.scale.time, { axis: "x1"})
      .trait( d3.trait.scale.linear, { axis: "y1" })
      .trait( d3.trait.chart.line, { interpolate: "monotone" })  // "linear"
      .trait( d3.trait.control.brush, { axis: 'x1', target: target, targetAxis: 'x1'})
      .trait( d3.trait.axis.time.month, { axis: "x1", ticks: 3})
      .trait( d3.trait.axis.linear, { axis: "y1", extentTicks: true})
  }

  beforeEach(function() {
    chartDiv = affix('.chart-div[style="width: 600px; height: 400px; fill: none"]')
    brushDiv = affix('.brush-div[style="width: 600px; height: 100px; fill: none"]')
    selection = d3.select(".chart-div")
    brushSelection = d3.select(".brush-div")
  })

  describe("Chart update", function() {
    var originalTimeout;
    beforeEach(function() {
      originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
      jasmine.DEFAULT_TIMEOUT_INTERVAL = 5 * 60 * 1000;
    });

    it("should handle chart updates with reasonable frame rate", function(done) {
      selection.datum(data)
      brushSelection.datum(data)
      var chart = d3.trait(d3.trait.chart.base, config)
        .trait(d3.trait.scale.time, {axis: 'x1'})
        .trait(d3.trait.scale.linear, {axis: 'y1'})
        .trait(d3.trait.axis.time.month, {axis: 'x1', gridLines: true})
        .trait(d3.trait.axis.linear, {axis: 'y1', gridLines: true})
        .trait(d3.trait.chart.line)
        .call(selection)

      var brush = makeBrushTraits( chart)
      brush.call( brushSelection)

      var div = selection[0][0]
      var chartGroup = div._chartGroup[0][0]

      var chartInstanceGroup = chartGroup.firstChild
      expect(chartInstanceGroup).toBeElement("g.chart-line")
      expect(chartInstanceGroup.childElementCount).toBe(data.length)

      var seriesGroup = chartInstanceGroup.firstChild
      expect(seriesGroup).toBeElement("g.series")
      expect(seriesGroup.childElementCount).toBe(1)

      var path = seriesGroup.firstChild
      expect(path).toBeElement("path.line")

      var frameRateDone = false,
          now = Date.now(),
          timerTotal = new FrameRateTimer( now),
          timerOneSecond = new FrameRateTimer( now),
          timings = []

      console.log( 'now = ' + now)
      function animationFrame() {
        if( ! frameRateDone) {
          var now = Date.now()

          timerTotal.frame( now)
          timerOneSecond.frame( now)
          if( timerOneSecond.elapsed() >= 1000) {
            timings.push( timerOneSecond.rate())
            timerOneSecond.reset( now)
          }
          requestAnimationFrame(animationFrame)
        }
      }
      requestAnimationFrame(animationFrame)

      function startUpdates() {

        var intervalId = setInterval( function() {
          var series = data[0],
              length = series.length,
              last = series[ length-1],
              rate = timings.length > 0 ? timings[timings.length-1] : '-'

          console.log( 'interval ' + last.y + ', timerOneSecond.rate: ' + rate )
          if( length < dataCount + 201) {
            series.push( {date: last.date+500, y: last.y+1+Math.random()})
//            chart.update( "trend")
            brush.update( "trend")
          } else {
            clearInterval( intervalId)
            frameRateDone = true
            console.log( 'Framerates = ' + timings)
            console.log( 'Framerate Average = ' + timerTotal.rate())
            done()
          }
        }, 500)
      }

      setTimeout( startUpdates, 1000)

    });

    afterEach(function() {
      jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
    });
  });

});

<|endoftext|>


<commit_before>import bodyParser from "body-parser";
import express from "express";
import morgan from "morgan";
import cors from "cors";
import compression from "compression";
import helmet from "helmet";
import logger from "./logger.js";

module.exports = app => {
  app.set("port", 3000);
  app.set("json spaces", 4);
  app.use(morgan("common", {
    stream: {
      write: (message) => {
        logger.info(message);
      }
    }
  }));
  app.use(helmet());
  app.use(cors({
    origin: ["http://localhost:3001"],
    methods: ["GET", "POST", "PUT", "DELETE"],
    allowedHeaders: ["Content-Type", "Authorization"]
  }));
  app.use(compression());
  app.use(bodyParser.json());
  app.use(app.auth.initialize());
  app.use((req, res, next) => {
    delete req.body.id;
    next();
  });
  app.use(express.static("public"));
};
<commit_msg>Api fix<commit_after>import bodyParser from "body-parser";
import express from "express";
import morgan from "morgan";
import cors from "cors";
import compression from "compression";
import helmet from "helmet";
import logger from "./logger.js";

module.exports = app => {
  app.set("port", 433);
  app.set("json spaces", 4);
  app.use(morgan("common", {
    stream: {
      write: (message) => {
        logger.info(message);
      }
    }
  }));
  app.use(helmet());
  app.use(cors({
    origin: ["http://localhost:3001",/\.softwill\.be$/],
    methods: ["GET", "POST", "PUT", "DELETE"],
    allowedHeaders: ["Content-Type", "Authorization"]
  }));
  app.use(compression());
  app.use(bodyParser.json());
  app.use(app.auth.initialize());
  app.use((req, res, next) => {
    delete req.body.id;
    next();
  });
  app.use(express.static("public"));
};
<|endoftext|>


<commit_before>// data-options.js
/*
   Portions Copyright (c) 2009-10 Zepheira LLC, Some Rights Reserved
   Portions Copyright (c) 2010-11 Talis Inc, Some Rights Reserved
   Licensed under the Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
*/

(function($, jQuery){

$(document).ready(function () {
    loadOptions($("[data-options]"));
});

$(document).bind('DOMNodeInserted', function (event) {
    loadOptions($(event.target).find("[data-options]").addBack().filter("[data-options]"));
});

function loadOptions(selects) {
    selects.each(function() {
        var select = $(this);
        var url = select.attr("data-options");
        select.removeAttr("data-options");
        calli.getText(url, function(data) {
            var options = $(data);
            var selected = select.children('option,label');
            var selectedOptions = [];
            options.contents().each(function() {
                if (this.nodeType == 3) {
                    select.append(this); // text node
                } else if (this.nodeType == 1 && $(this).is('option,label')) {
                    var option = $(this);
                    var checked = filterByAttributes(selected, option);
                    var bool = checked.is('option,label:has(input)');
                    if (!bool) { // IE8 can only read :checked if in document
                        disableRDFa(option);
                        option.removeAttr("selected");
                        option.children('input').removeAttr("checked");
                    }
                    checked.remove();
                    select.append(option);
                    if (bool && option.is('option')) {
                        selectedOptions.push(this);
                    }
                }
            });
            $(selectedOptions).each(function() {
                this.selected = true;
            });
            select.find('input[type="radio"]').each(function() {
                this.checked = this.getAttribute('checked') != null;
            });
            var controls = select.parents().addBack().filter('select').add(select.find('input'));
            controls.change(function() {
                select.children("option,label").each(function(){
                    var option = $(this);
                    if (option.is('option:selected') || option.children('input[type="checked"]').length) {
                        enableRDFa(option);
                    } else {
                        disableRDFa(option);
                    }
                });
            });
            controls.change();
        }).then(undefined, calli.error);
    });
}

function filterByAttributes(set, node) {
    return set.filter(function() {
        return 0 == countDifferentAttributes($(this), node);
    });
}

var RDFATTR = ["about", "typeof", "rel", "rev", "resource", "property", "href", "src"];

function countDifferentAttributes(selected, option) {
    var count = 0;
    for (var i = 0; i < RDFATTR.length; i++) {
        if (selected.attr(RDFATTR[i]) != option.attr(RDFATTR[i])) {
            count++;
        }
    }
    return count;
}

function disableRDFa(element) {
    element.find('*').addBack().each(function() {
        var node = $(this);
        for (var i = 0; i < RDFATTR.length; i++) {
            disableAttribute(node, RDFATTR[i]);
        }
    });
}

function enableRDFa(element) {
    element.find('*').addBack().each(function() {
        var node = $(this);
        for (var i = 0; i < RDFATTR.length; i++) {
            enableAttribute(node, RDFATTR[i]);
        }
    });
}

function disableAttribute(node, attr) {
    if (node.attr(attr) != undefined) {
        node.attr('data-' + attr, node.attr(attr));
        node.removeAttr(attr);
    }
}

function enableAttribute(node, attr) {
    if (node.attr('data-' + attr) != undefined) {
        node.attr(attr, node.attr('data-' + attr));
        node.removeAttr('data-' + attr);
    }
}

})(jQuery, jQuery);

<commit_msg>Fix radio/checkboxes using the 1.3 syntax<commit_after>// data-options.js
/*
   Portions Copyright (c) 2009-10 Zepheira LLC, Some Rights Reserved
   Portions Copyright (c) 2010-11 Talis Inc, Some Rights Reserved
   Licensed under the Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
*/

(function($, jQuery){

$(document).ready(function () {
    loadOptions($("[data-options]"));
});

$(document).bind('DOMNodeInserted', function (event) {
    loadOptions($(event.target).find("[data-options]").addBack().filter("[data-options]"));
});

function loadOptions(selects) {
    selects.each(function() {
        var select = $(this);
        var url = select.attr("data-options");
        select.removeAttr("data-options");
        calli.getText(url, function(data) {
            var options = $(data);
            var selected = select.children('option,label');
            var selectedOptions = [];
            options.contents().each(function() {
                if (this.nodeType == 3) {
                    select.append(this); // text node
                } else if (this.nodeType == 1 && $(this).is('option,label')) {
                    var option = $(this);
                    var checked = filterByAttributes(selected, option);
                    var bool = checked.is('option,label:has(input)');
                    if (!bool) { // IE8 can only read :checked if in document
                        disableRDFa(option);
                        option.removeAttr("selected");
                        option.children('input').removeAttr("checked");
                    }
                    checked.remove();
                    select.append(option);
                    if (bool && option.is('option')) {
                        selectedOptions.push(this);
                    }
                }
            });
            $(selectedOptions).each(function() {
                this.selected = true;
            });
            select.find('input[type="radio"]').each(function() {
                this.checked = this.getAttribute('checked') != null;
            });
            var controls = select.parents().addBack().filter('select').add(select.find('input'));
            controls.change(function() {
                select.children("option,label").each(function(){
                    var option = $(this);
                    if (option.is('option:selected') || option.children('input:checked]').length) {
                        enableRDFa(option);
                    } else {
                        disableRDFa(option);
                    }
                });
            });
            controls.change();
        }).then(undefined, calli.error);
    });
}

function filterByAttributes(set, node) {
    return set.filter(function() {
        return 0 == countDifferentAttributes($(this), node);
    });
}

var RDFATTR = ["about", "typeof", "rel", "rev", "resource", "property", "href", "src"];

function countDifferentAttributes(selected, option) {
    var count = 0;
    for (var i = 0; i < RDFATTR.length; i++) {
        if (selected.attr(RDFATTR[i]) != option.attr(RDFATTR[i])) {
            count++;
        }
    }
    return count;
}

function disableRDFa(element) {
    element.find('*').addBack().each(function() {
        var node = $(this);
        for (var i = 0; i < RDFATTR.length; i++) {
            disableAttribute(node, RDFATTR[i]);
        }
    });
}

function enableRDFa(element) {
    element.find('*').addBack().each(function() {
        var node = $(this);
        for (var i = 0; i < RDFATTR.length; i++) {
            enableAttribute(node, RDFATTR[i]);
        }
    });
}

function disableAttribute(node, attr) {
    if (node.attr(attr) != undefined) {
        node.attr('data-' + attr, node.attr(attr));
        node.removeAttr(attr);
    }
}

function enableAttribute(node, attr) {
    if (node.attr('data-' + attr) != undefined) {
        node.attr(attr, node.attr('data-' + attr));
        node.removeAttr('data-' + attr);
    }
}

})(jQuery, jQuery);

<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var env = require('./env');
var parser = require('./server-parser');

var servers = {};

var handleExit = function(server) {
    fs.unlink(server.pidFile, function(err) {
        if(err) return console.error(err);
        console.log('Server process exit, removing pid file: ', server.pidFile);
    });
};

var writePidFile = function(server) {
    fs.writeFile(server.pidFile, server.proc.pid, function(err) {
        if(err) return console.error(err);
    });
};

var spawnProcess = function(server) {
    var args = [
        '-c', path.join(server.workPath, 'server_cfg.ini'),
        '-e', path.join(server.workPath, 'entry_list.ini')
    ];

    var proc = require('child_process').spawn(env.getServerExecutable(), args, { cwd: env.getACPath() });
    proc.on('exit', handleExit.bind(null, server));
    proc.on('SIGINT', handleExit.bind(null, server));
    proc.on('uncaughtException', handleExit.bind(null, server));
    server.proc = proc;
};

var start = function(presetName) {
    var server = require('./server')(presetName);

    if (isRunning(server)) {
        throw new Error('Preset ' + preset.presetName + ' is already active');
    }

    spawnProcess(server);
    writePidFile(server);
    parser.connect(server);

    console.log('Started server', server.name, 'PID:', server.proc.pid);
    servers[presetName] = server;
    return true;
};

var stop = function(presetName) {
    var server = servers[presetName];
    // FIXME -- upload laptimes before exiting
    server.proc.kill();
    console.log('Stopped server', server.name, 'PID:', server.proc.pid);
    delete servers[presetName];
    return true;
};

var status = function(server) {
    if (fs.existsSync(server.pidFile) === false) {
        return 0;
    }
    if(server.proc === undefined) {
        return 0;
    }
    try {
        process.kill(server.proc.pid, 0);
        return 1;
    }
    catch (e) {
        handleExit(server);
        return -1;
    }
};

var isRunning = function(server) {
    return status(server) === 1;
};

module.exports = {
    env: env,
    servers: servers,
    start: start,
    stop: stop,
    status: status,
    isRunning: isRunning
};

<commit_msg>just some code cleanup<commit_after>var fs = require('fs');
var path = require('path');
var env = require('./env');

var servers = {};

var handleExit = function(server) {
    fs.unlink(server.pidFile, function(err) {
        if(err) return console.error(err);
        console.log('Server process exit, removing pid file: ', server.pidFile);
    });
};

var writePidFile = function(server) {
    fs.writeFile(server.pidFile, server.proc.pid, function(err) {
        if(err) return console.error(err);
    });
};

var handleOutput = function(server) {
    require('./server-parser').connect(server);
};

var spawnProcess = function(server) {
    var args = [
        '-c', path.join(server.workPath, 'server_cfg.ini'),
        '-e', path.join(server.workPath, 'entry_list.ini')
    ];

    var proc = require('child_process').spawn(env.getServerExecutable(), args, { cwd: env.getACPath() });
    proc.on('exit', handleExit.bind(null, server));
    proc.on('SIGINT', handleExit.bind(null, server));
    proc.on('uncaughtException', handleExit.bind(null, server));
    server.proc = proc;
};

var start = function(presetName) {
    var server = require('./server')(presetName);

    if (isRunning(server)) {
        throw new Error('Preset ' + preset.presetName + ' is already active');
    }

    spawnProcess(server);
    writePidFile(server);
    handleOutput(server);

    servers[presetName] = server;
    console.log('Started server', server.name, 'PID:', server.proc.pid);
    return true;
};

var stop = function(presetName) {
    var server = servers[presetName];
    server.proc.kill();
    delete servers[presetName];
    console.log('Stopped server', server.name, 'PID:', server.proc.pid);
    return true;
};

var status = function(server) {
    if (fs.existsSync(server.pidFile) === false) {
        return 0;
    }
    if(server.proc === undefined) {
        return 0;
    }
    try {
        process.kill(server.proc.pid, 0);
        return 1;
    }
    catch (e) {
        handleExit(server);
        return -1;
    }
};

var isRunning = function(server) {
    return status(server) === 1;
};

module.exports = {
    // objects
    env: env,
    servers: servers,
    // functions
    start: start,
    stop: stop,
    status: status,
    isRunning: isRunning
};

<|endoftext|>


<commit_before>/**
 * Bootstrap require with the needed config, then load the app.js module.
 */
require.config({
  baseUrl: 'app',

  paths: {
    config:                   ['../config', '../config.sample'],
    settings:                 'components/settings',
    kbn:                      'components/kbn',
    store:                    'components/store',

    css:                      '../vendor/require/css',
    text:                     '../vendor/require/text',
    moment:                   '../vendor/moment',
    filesaver:                '../vendor/filesaver',
    angular:                  '../vendor/angular/angular',
    'angular-route':          '../vendor/angular/angular-route',
    'angular-dragdrop':       '../vendor/angular/angular-dragdrop',
    'angular-strap':          '../vendor/angular/angular-strap',
    timepicker:               '../vendor/angular/timepicker',
    datepicker:               '../vendor/angular/datepicker',
    bindonce:                 '../vendor/angular/bindonce',
    crypto:                   '../vendor/crypto.min',
    spectrum:                 '../vendor/spectrum',

    lodash:                   'components/lodash.extended',
    'lodash-src':             '../vendor/lodash',
    bootstrap:                '../vendor/bootstrap/bootstrap',

    jquery:                   '../vendor/jquery/jquery-2.1.1.min',

    'extend-jquery':          'components/extend-jquery',

    'jquery.flot':            '../vendor/jquery/jquery.flot',
    'jquery.flot.pie':        '../vendor/jquery/jquery.flot.pie',
    'jquery.flot.events':     '../vendor/jquery/jquery.flot.events',
    'jquery.flot.selection':  '../vendor/jquery/jquery.flot.selection',
    'jquery.flot.stack':      '../vendor/jquery/jquery.flot.stack',
    'jquery.flot.stackpercent':'../vendor/jquery/jquery.flot.stackpercent',
    'jquery.flot.time':       '../vendor/jquery/jquery.flot.time',
    'jquery.flot.crosshair':  '../vendor/jquery/jquery.flot.crosshair',
    'jquery.flot.fillbelow':  '../vendor/jquery/jquery.flot.fillbelow',

    modernizr:                '../vendor/modernizr-2.6.1',

    'bootstrap-tagsinput':    '../vendor/tagsinput/bootstrap-tagsinput',

  },
  shim: {

    spectrum: {
      deps: ['jquery']
    },

    crypto: {
      exports: 'Crypto'
    },

    angular: {
      deps: ['jquery','config'],
      exports: 'angular'
    },

    bootstrap: {
      deps: ['jquery']
    },

    modernizr: {
      exports: 'Modernizr'
    },

    jquery: {
      exports: 'jQuery'
    },

    // simple dependency declaration
    //
    'jquery.flot':          ['jquery'],
    'jquery.flot.pie':      ['jquery', 'jquery.flot'],
    'jquery.flot.events':   ['jquery', 'jquery.flot'],
    'jquery.flot.selection':['jquery', 'jquery.flot'],
    'jquery.flot.stack':    ['jquery', 'jquery.flot'],
    'jquery.flot.stackpercent':['jquery', 'jquery.flot'],
    'jquery.flot.time':     ['jquery', 'jquery.flot'],
    'jquery.flot.crosshair':['jquery', 'jquery.flot'],
    'jquery.flot.fillbelow':['jquery', 'jquery.flot'],
    'angular-cookies':      ['angular'],
    'angular-dragdrop':     ['jquery', 'angular'],
    'angular-loader':       ['angular'],
    'angular-mocks':        ['angular'],
    'angular-resource':     ['angular'],
    'angular-route':        ['angular'],
    'angular-touch':        ['angular'],
    'bindonce':             ['angular'],
    'angular-strap':        ['angular', 'bootstrap','timepicker', 'datepicker'],

    timepicker:             ['jquery', 'bootstrap'],
    datepicker:             ['jquery', 'bootstrap'],

    'bootstrap-tagsinput':          ['jquery'],
  },
  waitSeconds: 60,
});
<commit_msg>Tech: added cache busting for requirejs fetches, will only affect config.js for optimized builds, should solve user issues where browsers cache config.js which causes initial confusing setup/config issues.<commit_after>/**
 * Bootstrap require with the needed config, then load the app.js module.
 */
require.config({
  baseUrl: 'app',
  urlArgs: 'bust=' + (new Date().getTime()),

  paths: {
    config:                   ['../config', '../config.sample'],
    settings:                 'components/settings',
    kbn:                      'components/kbn',
    store:                    'components/store',

    css:                      '../vendor/require/css',
    text:                     '../vendor/require/text',
    moment:                   '../vendor/moment',
    filesaver:                '../vendor/filesaver',
    angular:                  '../vendor/angular/angular',
    'angular-route':          '../vendor/angular/angular-route',
    'angular-dragdrop':       '../vendor/angular/angular-dragdrop',
    'angular-strap':          '../vendor/angular/angular-strap',
    timepicker:               '../vendor/angular/timepicker',
    datepicker:               '../vendor/angular/datepicker',
    bindonce:                 '../vendor/angular/bindonce',
    crypto:                   '../vendor/crypto.min',
    spectrum:                 '../vendor/spectrum',

    lodash:                   'components/lodash.extended',
    'lodash-src':             '../vendor/lodash',
    bootstrap:                '../vendor/bootstrap/bootstrap',

    jquery:                   '../vendor/jquery/jquery-2.1.1.min',

    'extend-jquery':          'components/extend-jquery',

    'jquery.flot':            '../vendor/jquery/jquery.flot',
    'jquery.flot.pie':        '../vendor/jquery/jquery.flot.pie',
    'jquery.flot.events':     '../vendor/jquery/jquery.flot.events',
    'jquery.flot.selection':  '../vendor/jquery/jquery.flot.selection',
    'jquery.flot.stack':      '../vendor/jquery/jquery.flot.stack',
    'jquery.flot.stackpercent':'../vendor/jquery/jquery.flot.stackpercent',
    'jquery.flot.time':       '../vendor/jquery/jquery.flot.time',
    'jquery.flot.crosshair':  '../vendor/jquery/jquery.flot.crosshair',
    'jquery.flot.fillbelow':  '../vendor/jquery/jquery.flot.fillbelow',

    modernizr:                '../vendor/modernizr-2.6.1',

    'bootstrap-tagsinput':    '../vendor/tagsinput/bootstrap-tagsinput',

  },
  shim: {

    spectrum: {
      deps: ['jquery']
    },

    crypto: {
      exports: 'Crypto'
    },

    angular: {
      deps: ['jquery','config'],
      exports: 'angular'
    },

    bootstrap: {
      deps: ['jquery']
    },

    modernizr: {
      exports: 'Modernizr'
    },

    jquery: {
      exports: 'jQuery'
    },

    // simple dependency declaration
    //
    'jquery.flot':          ['jquery'],
    'jquery.flot.pie':      ['jquery', 'jquery.flot'],
    'jquery.flot.events':   ['jquery', 'jquery.flot'],
    'jquery.flot.selection':['jquery', 'jquery.flot'],
    'jquery.flot.stack':    ['jquery', 'jquery.flot'],
    'jquery.flot.stackpercent':['jquery', 'jquery.flot'],
    'jquery.flot.time':     ['jquery', 'jquery.flot'],
    'jquery.flot.crosshair':['jquery', 'jquery.flot'],
    'jquery.flot.fillbelow':['jquery', 'jquery.flot'],
    'angular-cookies':      ['angular'],
    'angular-dragdrop':     ['jquery', 'angular'],
    'angular-loader':       ['angular'],
    'angular-mocks':        ['angular'],
    'angular-resource':     ['angular'],
    'angular-route':        ['angular'],
    'angular-touch':        ['angular'],
    'bindonce':             ['angular'],
    'angular-strap':        ['angular', 'bootstrap','timepicker', 'datepicker'],

    timepicker:             ['jquery', 'bootstrap'],
    datepicker:             ['jquery', 'bootstrap'],

    'bootstrap-tagsinput':          ['jquery'],
  },
  waitSeconds: 60,
});
<|endoftext|>


<commit_before>/* global _ */

/*
 * Complex scripted dashboard
 * This script generates a dashboard object that Grafana can load. It also takes a number of user
 * supplied URL parameters (int ARGS variable)
 *
 * Global accessable variables
 * window, document, $, jQuery, ARGS, moment
 *
 * Return a dashboard object, or a function
 *
 * For async scripts, return a function, this function must take a single callback function,
 * call this function with the dasboard object
 */

'use strict';

// accessable variables in this scope
var window, document, ARGS, $, jQuery, moment, kbn;

return function(callback) {

  // Setup some variables
  var dashboard, timspan;

  // Set a default timespan if one isn't specified
  timspan = '1d';

  // Intialize a skeleton with nothing but a rows array and service object
  dashboard = {
    rows : [],
    services : {}
  };

  // Set a title
  dashboard.title = 'Scripted dash';
  dashboard.services.filter = {
    time: {
      from: "now-" + (ARGS.from || timspan),
      to: "now"
    }
  };

  var rows = 1;
  var seriesName = 'argName';

  if(!_.isUndefined(ARGS.rows)) {
    rows = parseInt(ARGS.rows, 10);
  }

  if(!_.isUndefined(ARGS.name)) {
    seriesName = ARGS.name;
  }

  $.ajax({
    method: 'GET',
    url: '/'
  })
  .done(function(result) {

    dashboard.rows.push({
      title: 'Chart',
      height: '300px',
      panels: [
        {
          title: 'Async dashboard test',
          type: 'text',
          span: 12,
          fill: 1,
          content: '# Async test'
        }
      ]
    });

    // when dashboard is composed call the callback
    // function and pass the dashboard
    callback(dashboard);

  });
}<commit_msg>Small fix to scripted async dashboard example<commit_after>/* global _ */

/*
 * Complex scripted dashboard
 * This script generates a dashboard object that Grafana can load. It also takes a number of user
 * supplied URL parameters (int ARGS variable)
 *
 * Global accessable variables
 * window, document, $, jQuery, ARGS, moment
 *
 * Return a dashboard object, or a function
 *
 * For async scripts, return a function, this function must take a single callback function,
 * call this function with the dasboard object
 */

'use strict';

// accessable variables in this scope
var window, document, ARGS, $, jQuery, moment, kbn;

return function(callback) {

  // Setup some variables
  var dashboard, timspan;

  // Set a default timespan if one isn't specified
  timspan = '1d';

  // Intialize a skeleton with nothing but a rows array and service object
  dashboard = {
    rows : [],
    services : {}
  };

  // Set a title
  dashboard.title = 'Scripted dash';
  dashboard.time = {
    from: "now-" + (ARGS.from || timspan),
    to: "now"
  };

  var rows = 1;
  var seriesName = 'argName';

  if(!_.isUndefined(ARGS.rows)) {
    rows = parseInt(ARGS.rows, 10);
  }

  if(!_.isUndefined(ARGS.name)) {
    seriesName = ARGS.name;
  }

  $.ajax({
    method: 'GET',
    url: '/'
  })
  .done(function(result) {

    dashboard.rows.push({
      title: 'Chart',
      height: '300px',
      panels: [
        {
          title: 'Async dashboard test',
          type: 'text',
          span: 12,
          fill: 1,
          content: '# Async test'
        }
      ]
    });

    // when dashboard is composed call the callback
    // function and pass the dashboard
    callback(dashboard);

  });
}
<|endoftext|>


<commit_before>const prefix = 'b-image-overlay-license-modal';

const downloadButtonClass = '__download-button';
const contactButton = '__contact-button';
const modalClass = '__image-modal';
const contactModalOpen = '__contact-modal-open';
const iconLinkContainer = '__icon-link-container';
const checkmark = '__checkmark';
const imageIconLink = '__image-icon-link';
const agreeToTerms = '__agree-to-terms';
const downloadContentClass = '__modal-download-content';
const contactContentClass = '__modal-contact-content';
const checkboxContainer = '__checkbox-container';
const agreeCheckbox = '__agree-checkbox';
const agreeToTermsReminder = '__agree-to-terms-reminder';

const active = '--active';
const warning = '--warning';

const elements = [
  iconLinkContainer,
  checkmark,
  imageIconLink,
  agreeToTerms
];

const modal = document.querySelector(`.${prefix}${modalClass}`);
const imageOverlay = document.querySelector('.b-image-overlay') || document.querySelector('body');
const downloadContent = document.querySelector(`.${prefix}${downloadContentClass}`);
const contactContent = document.querySelector(`.${prefix}${contactContentClass}`);
const downloadLink = document.querySelector('.u-link.b-image-overlay-license-modal__download-link.js-modal-action');
const downloadButton = document.querySelector('.b-icon-link.b-icon-link__download.js-modal-action');
const closeButton = document.querySelector('.b-image-overlay-license-modal__close-container');

window.addEventListener('click', (e) => {
  if (e.target.closest('.b-image-overlay-license-modal__close-container')) {
    closeButton.disabled = true;
    modal.classList.remove('b-modal--active');
    modal.dispatchEvent(new CustomEvent('jsModalClosed', { bubbles: true }));
  }

  if (e.target.closest(`.${prefix}${downloadButtonClass}`)) {
    downloadContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = false;
    contactContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = true;
    const focusable = downloadContent.querySelectorAll(`
      .b-image-overlay-license-modal__close-container,
      .b-image-overlay-license-modal__title-section a,
      .b-modal__description,
      .b-image-overlay-license-modal__content-container button,
      .b-image-overlay-license-modal__footer-section a
    `);
    imageOverlay.classList.add('b-image-overlay--unfocus');
    modal.dispatchEvent(new CustomEvent('jsModalOpen', { bubbles: true }));
    modal.classList.add('b-modal--active');
    closeButton.disabled = false;
    downloadContent.classList.add(`${prefix}${downloadContentClass}${active}`);
    contactContent.classList.remove(`${prefix}${contactContentClass}${active}`);
    focusable[0].focus();
  }

  if (e.target.closest(`.${prefix}${contactButton}`)) {
    downloadContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = true;
    contactContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = false;
    imageOverlay.classList.add('b-image-overlay--unfocus');
    modal.dispatchEvent(new CustomEvent('jsModalOpen', { bubbles: true }));
    modal.classList.add('b-modal--active');
    closeButton.disabled = false;
    downloadContent.classList.remove(`${prefix}${downloadContentClass}${active}`);
    contactContent.classList.add(`${prefix}${contactContentClass}${active}`);
    document.querySelector('.b-modal__description-license-contact').focus();
  }

  if (e.target.closest(`.${prefix}${contactModalOpen}`)) {
    downloadContent.classList.remove(`${prefix}${downloadContentClass}${active}`);
    contactContent.classList.add(`${prefix}${contactContentClass}${active}`);
    document.querySelector('.b-modal__description-license-contact').focus();
  }

  if (e.target.closest(`.${prefix}${checkboxContainer}`)) {
    if (e.target.closest(`.${prefix}${agreeToTerms}`) === document.querySelector(`.${prefix}${agreeToTerms}`)) {
      document.querySelector(`.${prefix}${agreeCheckbox}`).checked =
        !document.querySelector(`.${prefix}${agreeCheckbox}`).checked;

      document.querySelector(`.${prefix}${agreeToTerms}`).classList.remove(`${prefix}${agreeToTerms}${warning}`);

      if (document.querySelector(`.${prefix}${agreeCheckbox}`).checked) {
        document.querySelector(`.${prefix}${agreeToTermsReminder}`).style.display = 'none';
        elements.forEach(c =>
          document.querySelector(`.${prefix}${c}`) && document.querySelector(`.${prefix}${c}`).classList.add(`${prefix}${c}--active`)
        );
        document.querySelector('.b-image-overlay-license-modal__download-link .b-icon-link').classList.add('b-icon-link--active');
        downloadLink.setAttribute('data-tracking-collections', 'image download');
        downloadButton.setAttribute('data-tracking-collections', 'image download');
      } else {
        elements.forEach(c =>
          document.querySelector(`.${prefix}${c}`) && document.querySelector(`.${prefix}${c}`).classList.remove(`${prefix}${c}--active`)
        );
        document.querySelector('.b-image-overlay-license-modal__download-link .b-icon-link').classList.remove('b-icon-link--active');
        downloadLink.removeAttribute('data-tracking-collections');
        downloadButton.removeAttribute('data-tracking-collections');
      }
    }
  }

  if (e.target.closest(`.${prefix}${checkboxContainer}`)) {
    if (!document.querySelector(`.${prefix}${agreeCheckbox}`).checked) {
      document.querySelector(`.${prefix}${agreeToTermsReminder}`).style.display = 'block';
      document.querySelector(`.${prefix}${agreeToTerms}`).classList.add(`${prefix}${agreeToTerms}${warning}`);
    }
  }
});

window.addEventListener('keydown', (e) => {
  const activeModal = (document.querySelector(`.${prefix}${modalClass}.b-modal--active`));
  const activeContent = document.querySelector(`.${prefix}${downloadContentClass}.${prefix}${downloadContentClass}${active}`) ||
    document.querySelector(`.${prefix}${contactContentClass}.${prefix}${contactContentClass}${active}`);

  if (activeModal) {
    // https://stackoverflow.com/a/60031728 w/ modifications
    if (e.keyCode === 9) {
      const focusable = activeContent.querySelectorAll(`
        .b-image-overlay-license-modal__close-container,
        .b-image-overlay-license-modal__title-section a,
        .b-modal__description.b-image-overlay-license-modal__description-container,
        .b-image-overlay-license-modal__content-container button,
        .b-image-overlay-license-modal__footer-section a
      `);
      const first = focusable[0];
      const last = focusable[focusable.length - 1];
      const shift = e.shiftKey;
      if (focusable.length) {
        if (shift && document.activeElement === first) {
          if (focusable.length === 1) {
            first.focus();
          } else {
            last.focus();
          }
          e.preventDefault();
        } else if (!shift && document.activeElement === last) {
          first.focus();
          e.preventDefault();
        }
      }
    }
  }

  if (e.keyCode === 13 && document.activeElement.classList.contains('b-image-overlay-license-modal__contact-modal-open')) {
    document.activeElement.click();
  }

  if (activeModal && e.keyCode === 27) {
    modal.classList.remove('b-modal--active');
    modal.dispatchEvent(new CustomEvent('jsModalClosed', { bubbles: true }));
    e.preventDefault();
    e.stopPropagation();
    return false;
  }

  // idk, it stops lint complaining
  return true;
});
<commit_msg>fix focus in license overlay<commit_after>const prefix = 'b-image-overlay-license-modal';

const downloadButtonClass = '__download-button';
const contactButton = '__contact-button';
const modalClass = '__image-modal';
const contactModalOpen = '__contact-modal-open';
const iconLinkContainer = '__icon-link-container';
const checkmark = '__checkmark';
const imageIconLink = '__image-icon-link';
const agreeToTerms = '__agree-to-terms';
const downloadContentClass = '__modal-download-content';
const contactContentClass = '__modal-contact-content';
const checkboxContainer = '__checkbox-container';
const agreeCheckbox = '__agree-checkbox';
const agreeToTermsReminder = '__agree-to-terms-reminder';

const active = '--active';
const warning = '--warning';

const elements = [
  iconLinkContainer,
  checkmark,
  imageIconLink,
  agreeToTerms
];

const modal = document.querySelector(`.${prefix}${modalClass}`);
const imageOverlay = document.querySelector('.b-image-overlay') || document.querySelector('body');
const downloadContent = document.querySelector(`.${prefix}${downloadContentClass}`);
const contactContent = document.querySelector(`.${prefix}${contactContentClass}`);
const downloadLink = document.querySelector('.u-link.b-image-overlay-license-modal__download-link.js-modal-action');
const downloadButton = document.querySelector('.b-icon-link.b-icon-link__download.js-modal-action');
const closeButton = document.querySelector('.b-image-overlay-license-modal__close-container');

window.addEventListener('click', (e) => {
  if (e.target.closest('.b-image-overlay-license-modal__close-container')) {
    closeButton.disabled = true;
    modal.classList.remove('b-modal--active');
    modal.dispatchEvent(new CustomEvent('jsModalClosed', { bubbles: true }));
  }

  if (e.target.closest(`.${prefix}${downloadButtonClass}`)) {
    downloadContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = false;
    contactContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = true;
    const focusable = downloadContent.querySelectorAll(`
      .b-image-overlay-license-modal__close-container,
      .b-image-overlay-license-modal__title-section a,
      .b-modal__description.b-image-overlay-license-modal__description-container,
      .b-image-overlay-license-modal__content-container button,
      .b-image-overlay-license-modal__footer-section a
    `);
    imageOverlay.classList.add('b-image-overlay--unfocus');
    modal.dispatchEvent(new CustomEvent('jsModalOpen', { bubbles: true }));
    modal.classList.add('b-modal--active');
    closeButton.disabled = false;
    downloadContent.classList.add(`${prefix}${downloadContentClass}${active}`);
    contactContent.classList.remove(`${prefix}${contactContentClass}${active}`);
    focusable[0].focus();
  }

  if (e.target.closest(`.${prefix}${contactButton}`)) {
    downloadContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = true;
    contactContent.querySelector('.b-image-overlay-license-modal__close-container').disabled = false;
    imageOverlay.classList.add('b-image-overlay--unfocus');
    modal.dispatchEvent(new CustomEvent('jsModalOpen', { bubbles: true }));
    modal.classList.add('b-modal--active');
    closeButton.disabled = false;
    downloadContent.classList.remove(`${prefix}${downloadContentClass}${active}`);
    contactContent.classList.add(`${prefix}${contactContentClass}${active}`);
    document.querySelector('.b-modal__description-license-contact').focus();
  }

  if (e.target.closest(`.${prefix}${contactModalOpen}`)) {
    downloadContent.classList.remove(`${prefix}${downloadContentClass}${active}`);
    contactContent.classList.add(`${prefix}${contactContentClass}${active}`);
    document.querySelector('.b-modal__description-license-contact').focus();
  }

  if (e.target.closest(`.${prefix}${checkboxContainer}`)) {
    if (e.target.closest(`.${prefix}${agreeToTerms}`) === document.querySelector(`.${prefix}${agreeToTerms}`)) {
      document.querySelector(`.${prefix}${agreeCheckbox}`).checked =
        !document.querySelector(`.${prefix}${agreeCheckbox}`).checked;

      document.querySelector(`.${prefix}${agreeToTerms}`).classList.remove(`${prefix}${agreeToTerms}${warning}`);

      if (document.querySelector(`.${prefix}${agreeCheckbox}`).checked) {
        document.querySelector(`.${prefix}${agreeToTermsReminder}`).style.display = 'none';
        elements.forEach(c =>
          document.querySelector(`.${prefix}${c}`) && document.querySelector(`.${prefix}${c}`).classList.add(`${prefix}${c}--active`)
        );
        document.querySelector('.b-image-overlay-license-modal__download-link .b-icon-link').classList.add('b-icon-link--active');
        downloadLink.setAttribute('data-tracking-collections', 'image download');
        downloadButton.setAttribute('data-tracking-collections', 'image download');
      } else {
        elements.forEach(c =>
          document.querySelector(`.${prefix}${c}`) && document.querySelector(`.${prefix}${c}`).classList.remove(`${prefix}${c}--active`)
        );
        document.querySelector('.b-image-overlay-license-modal__download-link .b-icon-link').classList.remove('b-icon-link--active');
        downloadLink.removeAttribute('data-tracking-collections');
        downloadButton.removeAttribute('data-tracking-collections');
      }
    }
  }

  if (e.target.closest(`.${prefix}${checkboxContainer}`)) {
    if (!document.querySelector(`.${prefix}${agreeCheckbox}`).checked) {
      document.querySelector(`.${prefix}${agreeToTermsReminder}`).style.display = 'block';
      document.querySelector(`.${prefix}${agreeToTerms}`).classList.add(`${prefix}${agreeToTerms}${warning}`);
    }
  }
});

window.addEventListener('keydown', (e) => {
  const activeModal = (document.querySelector(`.${prefix}${modalClass}.b-modal--active`));
  const activeContent = document.querySelector(`.${prefix}${downloadContentClass}.${prefix}${downloadContentClass}${active}`) ||
    document.querySelector(`.${prefix}${contactContentClass}.${prefix}${contactContentClass}${active}`);

  if (activeModal) {
    // https://stackoverflow.com/a/60031728 w/ modifications
    if (e.keyCode === 9) {
      const focusable = activeContent.querySelectorAll(`
        .b-image-overlay-license-modal__close-container,
        .b-image-overlay-license-modal__title-section a,
        .b-modal__description.b-image-overlay-license-modal__description-container,
        .b-image-overlay-license-modal__content-container button,
        .b-image-overlay-license-modal__footer-section a
      `);
      const first = focusable[0];
      const last = focusable[focusable.length - 1];
      const shift = e.shiftKey;
      if (focusable.length) {
        if (shift && document.activeElement === first) {
          if (focusable.length === 1) {
            first.focus();
          } else {
            last.focus();
          }
          e.preventDefault();
        } else if (!shift && document.activeElement === last) {
          first.focus();
          e.preventDefault();
        }
      }
    }
  }

  if (e.keyCode === 13 && document.activeElement.classList.contains('b-image-overlay-license-modal__contact-modal-open')) {
    document.activeElement.click();
  }

  if (activeModal && e.keyCode === 27) {
    modal.classList.remove('b-modal--active');
    modal.dispatchEvent(new CustomEvent('jsModalClosed', { bubbles: true }));
    e.preventDefault();
    e.stopPropagation();
    return false;
  }

  // idk, it stops lint complaining
  return true;
});
<|endoftext|>


<commit_before>
/**
 * provides paging functionality for table widget
 */
goog.provide('recoil.ui.widgets.table.PagedTableWidget');
goog.provide('recoil.ui.widgets.table.PagerWidget');
goog.provide('recoil.ui.widgets.table.createNextTablePager');

goog.require('goog.dom.classes');
goog.require('goog.string');
goog.require('goog.ui.Container');
goog.require('recoil.frp.Behaviour');
goog.require('recoil.frp.Util');
goog.require('recoil.frp.table.TableCell');
goog.require('recoil.structs.table.Table');
goog.require('recoil.structs.table.TableRow');
goog.require('recoil.ui.AttachableWidget');
goog.require('recoil.ui.BoolWithExplanation');
goog.require('recoil.ui.ComponentWidgetHelper');
goog.require('recoil.ui.RenderedDecorator');
goog.require('recoil.ui.messages');
goog.require('recoil.ui.widgets.LabelWidget');
goog.require('recoil.ui.widgets.TableMetaData');
goog.require('recoil.ui.widgets.table.Column');
goog.require('recoil.ui.widgets.table.StringColumn');
goog.require('recoil.ui.widgets.table.TableWidget');

/**
 * @constructor
 * @param {!recoil.ui.WidgetScope} scope
 * @implements recoil.ui.Widget
 */
recoil.ui.widgets.table.PagedTableWidget = function(scope) {
    this.scope_ = scope;
    this.container_ = new goog.ui.Component();
    this.container_.createDom();
    this.tableWidget_ = new recoil.ui.widgets.table.TableWidget(scope);
//    this.helper_ = new recoil.ui.ComponentWidgetHelper(scope, this.container_, this, this.updateState_);

    this.topPager_ = new recoil.ui.widgets.table.PagerWidget(scope);
    this.bottomPager_ = new recoil.ui.widgets.table.PagerWidget(scope);

    var tableDiv = goog.dom.createDom('div');
    this.tableWidget_.getComponent().render(tableDiv);

    var div = goog.dom.createDom('div', {class: 'recoil-table-pager-container'});

    this.container_.getElement().appendChild(div);
    div.appendChild(this.topPager_.getComponent().getElement());
    div.appendChild(tableDiv);
    div.appendChild(this.bottomPager_.getComponent().getElement());

    var me = this;

};

/**
 * all widgets should not allow themselves to be flatterned
 *
 * @type {!Object}
 */

recoil.ui.widgets.table.PagedTableWidget.prototype.flatten = recoil.frp.struct.NO_FLATTEN;

/**
 *
 * @return {!goog.ui.Component}
 */
recoil.ui.widgets.table.PagedTableWidget.prototype.getComponent = function() {
    return this.container_;
};

/**
 * @param {!recoil.frp.Behaviour<!recoil.structs.table.Table> | !recoil.structs.table.Table} table
 * @param {!recoil.frp.Behaviour<!recoil.ui.widgets.TableMetaData> |!recoil.ui.widgets.TableMetaData} meta
 * @param {!recoil.frp.Behaviour<!number>} page
 * @param {!recoil.frp.Behaviour<!number>|!number} count
 */
recoil.ui.widgets.table.PagedTableWidget.prototype.attach = function(table, meta, page, count) {
    this.tableWidget_.attach(table, meta);
    this.topPager_.attach(page, count);
    this.bottomPager_.attach(page, count);
};

/**
 * this should be called after the attach this way it can filter out the
 * rows that do not exist in the table.
 *
 * note this is a bidirectional behaviour, so setting it will change the selection
 *
 * @return {recoil.frp.Behaviour<Array<Array<Object>>>}
 */
recoil.ui.widgets.table.PagedTableWidget.prototype.createSelected = function() {
    return this.tableWidget_.createSelected();
};

/**
 * @constructor
 * @param {!recoil.ui.WidgetScope} scope
 * @implements recoil.ui.Widget
 */
recoil.ui.widgets.table.PagerWidget = function(scope) {
    this.scope_ = scope;
    this.container_ = new goog.ui.Component();
    this.container_.createDom();
    this.helper_ = new recoil.ui.ComponentWidgetHelper(scope, this.container_, this, this.updateState_);
    var me = this;

    this.first_ = goog.dom.createDom('a', {
        class: 'first'},'\u00ab');
    this.last_ = goog.dom.createDom('a', {
        class: 'last'},'\u00bb');
    this.next_ = goog.dom.createDom('a', {
        class: 'next'},'\u203A');
    this.prev_ = goog.dom.createDom('a', {
        class: 'previous'},'\u2039');

    var selectPage = goog.dom.createDom('input', {
        type: 'text',
        class: 'page'
    });

    var container = goog.dom.createDom('table', {
        class: 'recoil-table-pager pagination'
    });

    this.pageInput_ = selectPage;

    var row = goog.dom.createDom('div', {class: 'row'});

    selectPage.onblur = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    var val = parseInt(selectPage.value, 10);

                    if (val + '' === selectPage.value && val > 0 && val <= me.countB_.get()) {
                        me.pageB_.set(val);
                    }
                }
                me.updateInfo_();
            }, me.pageB_, me.countB_);

    };
    selectPage.onfocus = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    selectPage.value = me.pageB_.get();
                    selectPage.setSelectionRange(0, selectPage.value.length);
                }
            }, me.pageB_, me.countB_);
    };

    this.last_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    me.pageB_.set(me.countB_.get());
                }
            }, me.pageB_, me.countB_);
    };

    this.first_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    me.pageB_.set(1);
                }
            }, me.pageB_, me.countB_);
    };

    this.prev_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    if (me.pageB_.get() > 1) {
                        me.pageB_.set(me.pageB_.get() - 1);
                    }
                }
            }, me.pageB_, me.countB_);
    };

    this.next_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    if (me.pageB_.get() < me.countB_.get()) {
                        me.pageB_.set(me.pageB_.get() + 1);
                    }
                }
            }, me.pageB_, me.countB_);
    };

    container.appendChild(row);

    row.appendChild(this.first_);
    row.appendChild(this.prev_);
    row.appendChild(selectPage);
    row.appendChild(this.next_);
    row.appendChild(this.last_);

    this.container_.getElement().appendChild(container);
};

/**
 * all widgets should not allow themselves to be flatterned
 *
 * @type {!Object}
 */

recoil.ui.widgets.table.PagerWidget.prototype.flatten = recoil.frp.struct.NO_FLATTEN;

/**
 *
 * @return {!goog.ui.Component}
 */
recoil.ui.widgets.table.PagerWidget.prototype.getComponent = function() {
    return this.container_;
};

/**
 * @param {!recoil.frp.Behaviour<!number>} page the page that need to be displayed, must be behaviour otherwise
 8                                              we can't change the page
 * @param {!recoil.frp.Behaviour<!number> |!number} count
 */
recoil.ui.widgets.table.PagerWidget.prototype.attach = function(page, count) {
    var util = new recoil.frp.Util(this.scope_.getFrp());

    this.pageB_ = page;
    this.countB_ = util.toBehaviour(count);
    this.helper_.attach(page, this.countB_);
};

/***
 * helper to mark buttons disabled
 * @private
 * @param {boolean} disabled
 * @param {...Element} var_items
 */
recoil.ui.widgets.table.PagerWidget.prototype.disable_ = function(disabled, var_items) {

    for (var i = 1; i < arguments.length; i++) {
        var item = arguments[i];
        if (disabled) {
            goog.dom.classlist.add(item, 'disabled');
        }
        else {
            goog.dom.classlist.remove(item, 'disabled');
        }
    }
};

/**
 * updates the info in the table widget
 * @private
 */

recoil.ui.widgets.table.PagerWidget.prototype.updateInfo_ = function() {
    if (this.helper_.isGood()) {
        this.pageInput_.value = recoil.ui.messages.PAGE_X_OF_Y.resolve(
            { x: this.pageB_.get(), y: this.countB_.get() }).toString();
        var c = this.countB_.get();
        var p = this.pageB_.get();
        var enabled = c > 1;
        this.pageInput_.disabled = !enabled;
        this.disable_(!enabled || p === 1, this.first_, this.prev_);
        this.disable_(!enabled || p === c, this.last_, this.next_);
        this.pageInput_.disabled = !enabled;
    }
    else {
        this.pageInput_.disabled = true;
        this.disable_(true, this.first_, this.prev_, this.last_, this.next_);
        this.pageInput_.value = recoil.ui.messages.PAGE_X_OF_Y.resolve(
            { x: this.pageB_.metaGet().good() ? this.pageB_.get() : recoil.ui.messages.__UNKNOWN_VAL,
              y: this.countB_.metaGet().good() ? this.countB_.get() : recoil.ui.messages.__UNKNOWN_VAL}).toString();
    }
};

/**
 * updates the display in the pager widget
 * @private
 */
recoil.ui.widgets.table.PagerWidget.prototype.updateState_ = function() {
    var enabled = this.helper_.isGood();
    if (this.helper_.isGood()) {
        if (this.pageInput_ !== document.activeElement) {
            this.updateInfo_();
        }
    }
    else {
        this.updateInfo_();
    }

};

/**
 * a pager that takes a table with 2 extra rows
 * @param {!recoil.frp.Behaviour<!recoil.structs.table.Table>} tableB table to be paged, it should contain an extra row for before and after (if it exists)
 * @param {!recoil.frp.Behaviour<Object>} keyB an object specifies to do nextcan be null - first, page: _, prev: row, next: row
 * @param {!recoil.frp.Behaviour<!number>|!number} count size of a page
 * @return {{page:!recoil.frp.Behaviour<!number>,table: !recoil.frp.Behaviour<!recoil.structs.table.Table>, count : !recoil.frp.Behaviour<!number>}}
 */

recoil.ui.widgets.table.createNextTablePager = function(tableB, keyB, count) {
    var frp = tableB.frp();
    var util = new recoil.frp.Util(this.scope_.getFrp());
    var countB = util.toBehaviour(count);
    var memoryB = frp.createB(1);

    var rememberPageB = tableB.frp().liftBI(
        function()  {
            return {orig: memoryB.get(), val: memoryB.get()};
        },
        function(val) {
            var table = tableB.get();
            var first = null;
            var last = null;
            table.forEach(function(row) {
                first = first || row;
                last = row;
            });

            if (val.orig + 1 === val.val) {
                // value has increased by 1 just get the next page
                if (table.size() > countB.get() + 1 && last) {
                    keyB.set({next: last});
                    memoryB.set(val.val);
                }
            }
            else if (val.val === 1) {
                // we want the first page no need for a key
                keyB.set(null);
                memoryB.set(val.val);
            }
            else if (val.orig - 1 === val.val) {
                // went back 1 use prev
                keyB.set({prev: first});
                memoryB.set(val.val);
            }
            else {
                // random page just get that
                keyB.set({prev: val.val});
                memoryB.set(val.val);
            }
        }, tableB, keyB, memoryB);

    var pageB = frp.liftBI(
        function() {
            return rememberPageB.get().val;
        },
        function(val) {
            rememberPageB.set({orig: rememberPageB.get().orig, val: val});
        }, rememberPageB);
    // this filters out the first and last row if necessary
    var outTableB = frp.liftBI(
        function(table, page, count) {
            var res = table.createEmpty();
            var row = 0;
            table.forEach(function(row) {
                var max = page === 1 ? count : count + 1;
                if ((page === 1 && row === 0) || (row !== 0 && row < max)) {
                    res.addRow(row);
                }
                row++;
            });
            return res;
        },
        function(val) {
            var res = tableB.get().createEmpty();
            var rowPos = 0;
            var page = memoryB.get();
            var count = countB.get();
            // add first row used for pager
            if (page !== 0) {
                tableB.get().forEach(function(row) {
                    if (rowPos === 0) {
                        res.addRow(row);
                    }
                    rowPos++;
                });
            }

            // add the data for the output rows
            val.forEach(function(row) {
                res.addRow(row);
            });

            rowPos = 0;
            var max = page === 1 ? count : count + 1;
            tableB.get().forEach(function(row) {
                if (rowPos >= max) {
                    res.addRow(row);
                }
                rowPos++;
            });

        }, tableB, memoryB, countB);

    return {
        table: outTableB,
        page: pageB,
        count: countB
    };
};
<commit_msg>get frp properly<commit_after>
/**
 * provides paging functionality for table widget
 */
goog.provide('recoil.ui.widgets.table.PagedTableWidget');
goog.provide('recoil.ui.widgets.table.PagerWidget');
goog.provide('recoil.ui.widgets.table.createNextTablePager');

goog.require('goog.dom.classes');
goog.require('goog.string');
goog.require('goog.ui.Container');
goog.require('recoil.frp.Behaviour');
goog.require('recoil.frp.Util');
goog.require('recoil.frp.table.TableCell');
goog.require('recoil.structs.table.Table');
goog.require('recoil.structs.table.TableRow');
goog.require('recoil.ui.AttachableWidget');
goog.require('recoil.ui.BoolWithExplanation');
goog.require('recoil.ui.ComponentWidgetHelper');
goog.require('recoil.ui.RenderedDecorator');
goog.require('recoil.ui.messages');
goog.require('recoil.ui.widgets.LabelWidget');
goog.require('recoil.ui.widgets.TableMetaData');
goog.require('recoil.ui.widgets.table.Column');
goog.require('recoil.ui.widgets.table.StringColumn');
goog.require('recoil.ui.widgets.table.TableWidget');

/**
 * @constructor
 * @param {!recoil.ui.WidgetScope} scope
 * @implements recoil.ui.Widget
 */
recoil.ui.widgets.table.PagedTableWidget = function(scope) {
    this.scope_ = scope;
    this.container_ = new goog.ui.Component();
    this.container_.createDom();
    this.tableWidget_ = new recoil.ui.widgets.table.TableWidget(scope);
//    this.helper_ = new recoil.ui.ComponentWidgetHelper(scope, this.container_, this, this.updateState_);

    this.topPager_ = new recoil.ui.widgets.table.PagerWidget(scope);
    this.bottomPager_ = new recoil.ui.widgets.table.PagerWidget(scope);

    var tableDiv = goog.dom.createDom('div');
    this.tableWidget_.getComponent().render(tableDiv);

    var div = goog.dom.createDom('div', {class: 'recoil-table-pager-container'});

    this.container_.getElement().appendChild(div);
    div.appendChild(this.topPager_.getComponent().getElement());
    div.appendChild(tableDiv);
    div.appendChild(this.bottomPager_.getComponent().getElement());

    var me = this;

};

/**
 * all widgets should not allow themselves to be flatterned
 *
 * @type {!Object}
 */

recoil.ui.widgets.table.PagedTableWidget.prototype.flatten = recoil.frp.struct.NO_FLATTEN;

/**
 *
 * @return {!goog.ui.Component}
 */
recoil.ui.widgets.table.PagedTableWidget.prototype.getComponent = function() {
    return this.container_;
};

/**
 * @param {!recoil.frp.Behaviour<!recoil.structs.table.Table> | !recoil.structs.table.Table} table
 * @param {!recoil.frp.Behaviour<!recoil.ui.widgets.TableMetaData> |!recoil.ui.widgets.TableMetaData} meta
 * @param {!recoil.frp.Behaviour<!number>} page
 * @param {!recoil.frp.Behaviour<!number>|!number} count
 */
recoil.ui.widgets.table.PagedTableWidget.prototype.attach = function(table, meta, page, count) {
    this.tableWidget_.attach(table, meta);
    this.topPager_.attach(page, count);
    this.bottomPager_.attach(page, count);
};

/**
 * this should be called after the attach this way it can filter out the
 * rows that do not exist in the table.
 *
 * note this is a bidirectional behaviour, so setting it will change the selection
 *
 * @return {recoil.frp.Behaviour<Array<Array<Object>>>}
 */
recoil.ui.widgets.table.PagedTableWidget.prototype.createSelected = function() {
    return this.tableWidget_.createSelected();
};

/**
 * @constructor
 * @param {!recoil.ui.WidgetScope} scope
 * @implements recoil.ui.Widget
 */
recoil.ui.widgets.table.PagerWidget = function(scope) {
    this.scope_ = scope;
    this.container_ = new goog.ui.Component();
    this.container_.createDom();
    this.helper_ = new recoil.ui.ComponentWidgetHelper(scope, this.container_, this, this.updateState_);
    var me = this;

    this.first_ = goog.dom.createDom('a', {
        class: 'first'},'\u00ab');
    this.last_ = goog.dom.createDom('a', {
        class: 'last'},'\u00bb');
    this.next_ = goog.dom.createDom('a', {
        class: 'next'},'\u203A');
    this.prev_ = goog.dom.createDom('a', {
        class: 'previous'},'\u2039');

    var selectPage = goog.dom.createDom('input', {
        type: 'text',
        class: 'page'
    });

    var container = goog.dom.createDom('table', {
        class: 'recoil-table-pager pagination'
    });

    this.pageInput_ = selectPage;

    var row = goog.dom.createDom('div', {class: 'row'});

    selectPage.onblur = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    var val = parseInt(selectPage.value, 10);

                    if (val + '' === selectPage.value && val > 0 && val <= me.countB_.get()) {
                        me.pageB_.set(val);
                    }
                }
                me.updateInfo_();
            }, me.pageB_, me.countB_);

    };
    selectPage.onfocus = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    selectPage.value = me.pageB_.get();
                    selectPage.setSelectionRange(0, selectPage.value.length);
                }
            }, me.pageB_, me.countB_);
    };

    this.last_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    me.pageB_.set(me.countB_.get());
                }
            }, me.pageB_, me.countB_);
    };

    this.first_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    me.pageB_.set(1);
                }
            }, me.pageB_, me.countB_);
    };

    this.prev_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    if (me.pageB_.get() > 1) {
                        me.pageB_.set(me.pageB_.get() - 1);
                    }
                }
            }, me.pageB_, me.countB_);
    };

    this.next_.onclick = function() {
        me.scope_.getFrp().accessTrans(
            function() {
                if (me.helper_.isGood()) {
                    if (me.pageB_.get() < me.countB_.get()) {
                        me.pageB_.set(me.pageB_.get() + 1);
                    }
                }
            }, me.pageB_, me.countB_);
    };

    container.appendChild(row);

    row.appendChild(this.first_);
    row.appendChild(this.prev_);
    row.appendChild(selectPage);
    row.appendChild(this.next_);
    row.appendChild(this.last_);

    this.container_.getElement().appendChild(container);
};

/**
 * all widgets should not allow themselves to be flatterned
 *
 * @type {!Object}
 */

recoil.ui.widgets.table.PagerWidget.prototype.flatten = recoil.frp.struct.NO_FLATTEN;

/**
 *
 * @return {!goog.ui.Component}
 */
recoil.ui.widgets.table.PagerWidget.prototype.getComponent = function() {
    return this.container_;
};

/**
 * @param {!recoil.frp.Behaviour<!number>} page the page that need to be displayed, must be behaviour otherwise
 8                                              we can't change the page
 * @param {!recoil.frp.Behaviour<!number> |!number} count
 */
recoil.ui.widgets.table.PagerWidget.prototype.attach = function(page, count) {
    var util = new recoil.frp.Util(this.scope_.getFrp());

    this.pageB_ = page;
    this.countB_ = util.toBehaviour(count);
    this.helper_.attach(page, this.countB_);
};

/***
 * helper to mark buttons disabled
 * @private
 * @param {boolean} disabled
 * @param {...Element} var_items
 */
recoil.ui.widgets.table.PagerWidget.prototype.disable_ = function(disabled, var_items) {

    for (var i = 1; i < arguments.length; i++) {
        var item = arguments[i];
        if (disabled) {
            goog.dom.classlist.add(item, 'disabled');
        }
        else {
            goog.dom.classlist.remove(item, 'disabled');
        }
    }
};

/**
 * updates the info in the table widget
 * @private
 */

recoil.ui.widgets.table.PagerWidget.prototype.updateInfo_ = function() {
    if (this.helper_.isGood()) {
        this.pageInput_.value = recoil.ui.messages.PAGE_X_OF_Y.resolve(
            { x: this.pageB_.get(), y: this.countB_.get() }).toString();
        var c = this.countB_.get();
        var p = this.pageB_.get();
        var enabled = c > 1;
        this.pageInput_.disabled = !enabled;
        this.disable_(!enabled || p === 1, this.first_, this.prev_);
        this.disable_(!enabled || p === c, this.last_, this.next_);
        this.pageInput_.disabled = !enabled;
    }
    else {
        this.pageInput_.disabled = true;
        this.disable_(true, this.first_, this.prev_, this.last_, this.next_);
        this.pageInput_.value = recoil.ui.messages.PAGE_X_OF_Y.resolve(
            { x: this.pageB_.metaGet().good() ? this.pageB_.get() : recoil.ui.messages.__UNKNOWN_VAL,
              y: this.countB_.metaGet().good() ? this.countB_.get() : recoil.ui.messages.__UNKNOWN_VAL}).toString();
    }
};

/**
 * updates the display in the pager widget
 * @private
 */
recoil.ui.widgets.table.PagerWidget.prototype.updateState_ = function() {
    var enabled = this.helper_.isGood();
    if (this.helper_.isGood()) {
        if (this.pageInput_ !== document.activeElement) {
            this.updateInfo_();
        }
    }
    else {
        this.updateInfo_();
    }

};

/**
 * a pager that takes a table with 2 extra rows
 * @param {!recoil.frp.Behaviour<!recoil.structs.table.Table>} tableB table to be paged, it should contain an extra row for before and after (if it exists)
 * @param {!recoil.frp.Behaviour<Object>} keyB an object specifies to do nextcan be null - first, page: _, prev: row, next: row
 * @param {!recoil.frp.Behaviour<!number>|!number} count size of a page
 * @return {{page:!recoil.frp.Behaviour<!number>,table: !recoil.frp.Behaviour<!recoil.structs.table.Table>, count : !recoil.frp.Behaviour<!number>}}
 */

recoil.ui.widgets.table.createNextTablePager = function(tableB, keyB, count) {
    var frp = tableB.frp();
    var util = new recoil.frp.Util(tableB.frp());
    var countB = util.toBehaviour(count);
    var memoryB = frp.createB(1);

    var rememberPageB = tableB.frp().liftBI(
        function()  {
            return {orig: memoryB.get(), val: memoryB.get()};
        },
        function(val) {
            var table = tableB.get();
            var first = null;
            var last = null;
            table.forEach(function(row) {
                first = first || row;
                last = row;
            });

            if (val.orig + 1 === val.val) {
                // value has increased by 1 just get the next page
                if (table.size() > countB.get() + 1 && last) {
                    keyB.set({next: last});
                    memoryB.set(val.val);
                }
            }
            else if (val.val === 1) {
                // we want the first page no need for a key
                keyB.set(null);
                memoryB.set(val.val);
            }
            else if (val.orig - 1 === val.val) {
                // went back 1 use prev
                keyB.set({prev: first});
                memoryB.set(val.val);
            }
            else {
                // random page just get that
                keyB.set({prev: val.val});
                memoryB.set(val.val);
            }
        }, tableB, keyB, memoryB);

    var pageB = frp.liftBI(
        function() {
            return rememberPageB.get().val;
        },
        function(val) {
            rememberPageB.set({orig: rememberPageB.get().orig, val: val});
        }, rememberPageB);
    // this filters out the first and last row if necessary
    var outTableB = frp.liftBI(
        function(table, page, count) {
            var res = table.createEmpty();
            var row = 0;
            table.forEach(function(row) {
                var max = page === 1 ? count : count + 1;
                if ((page === 1 && row === 0) || (row !== 0 && row < max)) {
                    res.addRow(row);
                }
                row++;
            });
            return res;
        },
        function(val) {
            var res = tableB.get().createEmpty();
            var rowPos = 0;
            var page = memoryB.get();
            var count = countB.get();
            // add first row used for pager
            if (page !== 0) {
                tableB.get().forEach(function(row) {
                    if (rowPos === 0) {
                        res.addRow(row);
                    }
                    rowPos++;
                });
            }

            // add the data for the output rows
            val.forEach(function(row) {
                res.addRow(row);
            });

            rowPos = 0;
            var max = page === 1 ? count : count + 1;
            tableB.get().forEach(function(row) {
                if (rowPos >= max) {
                    res.addRow(row);
                }
                rowPos++;
            });

        }, tableB, memoryB, countB);

    return {
        table: outTableB,
        page: pageB,
        count: countB
    };
};
<|endoftext|>


<commit_before>'use strict';

describe('controllers', function(){
  var scope;

  beforeEach(module('geoPusher'));

  beforeEach(inject(function($rootScope) {
    scope = $rootScope.$new();
  }));

  it('should define more than 5 awesome things', inject(function($controller) {
    expect(scope.awesomeThings).toBeUndefined();

    $controller('MainCtrl', {
      $scope: scope
    });

    expect(angular.isArray(scope.awesomeThings)).toBeTruthy();
    expect(scope.awesomeThings.length > 5).toBeTruthy();
  }));
});
<commit_msg>Remove generated spec<commit_after><|endoftext|>


<commit_before>/**
 * This class provides a ScratchLinkSocket implementation using WebSockets,
 * attempting to connect with the locally installed Scratch-Link.
 *
 * To connect with ScratchLink without WebSockets, you must implement all of the
 * public methods in this class.
 * - open()
 * - close()
 * - set[Open|Close|Error]
 * - setHandleMessage
 * - isOpen()
 */
class ScratchLinkWebSocket {
    constructor (type) {
        this._type = type;
        this._onOpen = null;
        this._onClose = null;
        this._onError = null;
        this._handleMessage = null;

        this._ws = null;
    }

    open () {
        switch (this._type) {
        case 'BLE':
            this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/ble');
            break;
        case 'BT':
            this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/bt');
            break;
        default:
            throw new Error(`Unknown ScratchLink socket Type: ${this._type}`);
        }

        if (this._onOpen && this._onClose && this._onError) {
            this._ws.onopen = this._onOpen;
            this._ws.onclose = this._onClose;
            this._ws.onerror = this._onError;
        } else {
            throw new Error('Must set open, close and error handlers before calling open on the socket');
        }

        this._ws.onmessage = this._onMessage.bind(this);
    }

    close () {
        this._ws.close();
        this._ws = null;
    }

    sendMessage (message) {
        const messageText = JSON.stringify(message);
        this._ws.send(messageText);
    }

    setOnOpen (fn) {
        this._onOpen = fn;
    }

    setOnClose (fn) {
        this._onClose = fn;
    }

    setOnError (fn) {
        this._onError = fn;
    }

    setHandleMessage (fn) {
        this._handleMessage = fn;
    }

    isOpen () {
        return this._ws && this._ws.readyState === this._ws.OPEN;
    }

    _onMessage (e) {
        const json = JSON.parse(e.data);
        this._handleMessage(json);
    }
}

module.exports = ScratchLinkWebSocket;
<commit_msg>Require handleMessage to be set before opening scratch-link-socket<commit_after>/**
 * This class provides a ScratchLinkSocket implementation using WebSockets,
 * attempting to connect with the locally installed Scratch-Link.
 *
 * To connect with ScratchLink without WebSockets, you must implement all of the
 * public methods in this class.
 * - open()
 * - close()
 * - set[Open|Close|Error]
 * - setHandleMessage
 * - isOpen()
 */
class ScratchLinkWebSocket {
    constructor (type) {
        this._type = type;
        this._onOpen = null;
        this._onClose = null;
        this._onError = null;
        this._handleMessage = null;

        this._ws = null;
    }

    open () {
        switch (this._type) {
        case 'BLE':
            this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/ble');
            break;
        case 'BT':
            this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/bt');
            break;
        default:
            throw new Error(`Unknown ScratchLink socket Type: ${this._type}`);
        }

        if (this._onOpen && this._onClose && this._onError && this._handleMessage) {
            this._ws.onopen = this._onOpen;
            this._ws.onclose = this._onClose;
            this._ws.onerror = this._onError;
        } else {
            throw new Error('Must set open, close, message and error handlers before calling open on the socket');
        }

        this._ws.onmessage = this._onMessage.bind(this);
    }

    close () {
        this._ws.close();
        this._ws = null;
    }

    sendMessage (message) {
        const messageText = JSON.stringify(message);
        this._ws.send(messageText);
    }

    setOnOpen (fn) {
        this._onOpen = fn;
    }

    setOnClose (fn) {
        this._onClose = fn;
    }

    setOnError (fn) {
        this._onError = fn;
    }

    setHandleMessage (fn) {
        this._handleMessage = fn;
    }

    isOpen () {
        return this._ws && this._ws.readyState === this._ws.OPEN;
    }

    _onMessage (e) {
        const json = JSON.parse(e.data);
        this._handleMessage(json);
    }
}

module.exports = ScratchLinkWebSocket;
<|endoftext|>


<commit_before>var nqp = require('nqp-runtime');
var Null = nqp.Null;
var CodeRef = require('nqp-runtime/code-ref');
var op = {};

var Scalar, True, False, Int, Num, Str, Code;

op.p6settypes = function(types) {
  Scalar = types.content.get('Scalar');
  True = types.content.get('True');
  False = types.content.get('False');
  Int = types.content.get('Int');
  Num = types.content.get('Num');
  Str = types.content.get('Str');
  Code = types.content.get('Code');
  Mu = types.content.get('Mu');
  return types;
};

op.p6bool = function(value) {
  return value ? True : False;
};

op.p6definite = function(obj) {
  return obj.typeObject_ ? False : True;
};

op.p6typecheckrv = function(rv, routine, bypassType) {
  // STUB
  return rv;
};

op.p6decontrv = function(rountine, cont) {
  // STUB
  return cont;
};

op.p6box_i = function(int) {
  var repr = Int._STable.REPR;
  var boxed = repr.allocate(Int._STable);
  boxed.$$setInt(int);
  return boxed;
};

op.p6box_n = function(num) {
  var repr = Num._STable.REPR;
  var boxed = repr.allocate(Num._STable);
  boxed.$$setNum(num);
  return boxed;
};

op.p6box_s = function(str) {
  var repr = Str._STable.REPR;
  var boxed = repr.allocate(Str._STable);
  boxed.$$setStr(str);
  return boxed;
};

op.p6captureouters2 = function(ctx, capList, target) {
  var cf = (target.outerCtx || closure.forcedOuter);

  if (cf === Null) {
    return capList;
  }

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);

      var closure = codeObj.$$getattr(Code, "$!do");

      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = cf;
  }

  return capList;
};

op.p6captureouters = function(ctx, capList) {

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);
      var closure = codeObj.$$getattr(Code, "$!do");
      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = ctx;
  }

  return capList;
};

op.p6capturelex = function(ctx, codeObj) {

  var closure = codeObj.$$getattr(Code, "$!do");
  var wantedStaticInfo = closure.staticCode.outerCodeRef;

  if (ctx.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx;
  } else if (ctx.$$outer.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx.$$outer;
  }

  return codeObj;
};

op.p6var = function(cont) {
  if (cont.$$iscont && cont.$$iscont()) {
    var wrapper = Scalar._STable.REPR.allocate(Scalar._STable);
    wrapper.$$bindattr(Scalar, '$!value', cont);
    return wrapper;
  } else {
    return cont;
  }
}

op.p6bindassert = function(ctx, value, type) {
  if (type !== Mu) {
    if (nqp.op.istype(ctx, value.$$decont(ctx), type) == 0) {
      ctx.die("Type check failed in binding");
    }
  }
  return value;
};

op.p6store = function(ctx, cont, value) {
  if (cont) {
    cont.$$assign(ctx, value.$$decont(ctx));
  } else {
    if (!cont.STORE) {
      // TODO throw typed exception X::Assignment::RO
      ctx.die("Cannot assign to a non-container");
    } else {
      cont.STORE(ctx, null, cont, value);
    }
  }
  return cont;
};

op.p6argvmarray = function(ctx, args) {
  var array = [];
  console.log("in p6argvmarray");
  for (var i=2; i < args.length; i++) {
    array[i-2] = nqp.op.hllizefor(ctx, args[i], 'perl6');
  }
  return nqp.createArray(array);
};

var containerSpecs = require('nqp-runtime/container-specs.js');

function RakudoScalar(STable) {
  this.STable = STable;
}

RakudoScalar.prototype.configure = function(conf) {
  this.setupSTable();
};

RakudoScalar.prototype.setupSTable = function() {
  this.STable.addInternalMethod('$$assignunchecked', function(ctx, value) {
    console.log('storing into rakudo_scalar unchecked');
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$assign', function(ctx, value) {
    /* TODO - checking and WHENCE */
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$decont', function(ctx) {
    return this.$$getattr(Scalar, '$!value');
  });

  this.STable.addInternalMethod('$$getInt', function(ctx) {
    return this.$$decont().$$getInt();
  });

  this.STable.addInternalMethod('$$getNum', function(ctx) {
    return this.$$decont().$$getNum();
  });

  this.STable.addInternalMethod('$$getStr', function(ctx) {
    return this.$$decont().$$getStr();
  });

  this.STable.addInternalMethod('$$iscont', function() {
    return 1;
  });
};

RakudoScalar.prototype.serialize = function(cursor) {
  console.log('// serializing rakudo_scalar');
};

RakudoScalar.prototype.deserialize = function(cursor) {
  console.log('// deserializing rakudo_scalar');
};

RakudoScalar.prototype.name = 'rakudo_scalar';

containerSpecs.rakudo_scalar = RakudoScalar;

nqp.loadOps({op: op});
module.exports = null;

<commit_msg>[js] Get rid of debugging leftover.<commit_after>var nqp = require('nqp-runtime');
var Null = nqp.Null;
var CodeRef = require('nqp-runtime/code-ref');
var op = {};

var Scalar, True, False, Int, Num, Str, Code;

op.p6settypes = function(types) {
  Scalar = types.content.get('Scalar');
  True = types.content.get('True');
  False = types.content.get('False');
  Int = types.content.get('Int');
  Num = types.content.get('Num');
  Str = types.content.get('Str');
  Code = types.content.get('Code');
  Mu = types.content.get('Mu');
  return types;
};

op.p6bool = function(value) {
  return value ? True : False;
};

op.p6definite = function(obj) {
  return obj.typeObject_ ? False : True;
};

op.p6typecheckrv = function(rv, routine, bypassType) {
  // STUB
  return rv;
};

op.p6decontrv = function(rountine, cont) {
  // STUB
  return cont;
};

op.p6box_i = function(int) {
  var repr = Int._STable.REPR;
  var boxed = repr.allocate(Int._STable);
  boxed.$$setInt(int);
  return boxed;
};

op.p6box_n = function(num) {
  var repr = Num._STable.REPR;
  var boxed = repr.allocate(Num._STable);
  boxed.$$setNum(num);
  return boxed;
};

op.p6box_s = function(str) {
  var repr = Str._STable.REPR;
  var boxed = repr.allocate(Str._STable);
  boxed.$$setStr(str);
  return boxed;
};

op.p6captureouters2 = function(ctx, capList, target) {
  var cf = (target.outerCtx || closure.forcedOuter);

  if (cf === Null) {
    return capList;
  }

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);

      var closure = codeObj.$$getattr(Code, "$!do");

      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = cf;
  }

  return capList;
};

op.p6captureouters = function(ctx, capList) {

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);
      var closure = codeObj.$$getattr(Code, "$!do");
      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = ctx;
  }

  return capList;
};

op.p6capturelex = function(ctx, codeObj) {

  var closure = codeObj.$$getattr(Code, "$!do");
  var wantedStaticInfo = closure.staticCode.outerCodeRef;

  if (ctx.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx;
  } else if (ctx.$$outer.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx.$$outer;
  }

  return codeObj;
};

op.p6var = function(cont) {
  if (cont.$$iscont && cont.$$iscont()) {
    var wrapper = Scalar._STable.REPR.allocate(Scalar._STable);
    wrapper.$$bindattr(Scalar, '$!value', cont);
    return wrapper;
  } else {
    return cont;
  }
}

op.p6bindassert = function(ctx, value, type) {
  if (type !== Mu) {
    if (nqp.op.istype(ctx, value.$$decont(ctx), type) == 0) {
      ctx.die("Type check failed in binding");
    }
  }
  return value;
};

op.p6store = function(ctx, cont, value) {
  if (cont) {
    cont.$$assign(ctx, value.$$decont(ctx));
  } else {
    if (!cont.STORE) {
      // TODO throw typed exception X::Assignment::RO
      ctx.die("Cannot assign to a non-container");
    } else {
      cont.STORE(ctx, null, cont, value);
    }
  }
  return cont;
};

op.p6argvmarray = function(ctx, args) {
  var array = [];
  for (var i=2; i < args.length; i++) {
    array[i-2] = nqp.op.hllizefor(ctx, args[i], 'perl6');
  }
  return nqp.createArray(array);
};

var containerSpecs = require('nqp-runtime/container-specs.js');

function RakudoScalar(STable) {
  this.STable = STable;
}

RakudoScalar.prototype.configure = function(conf) {
  this.setupSTable();
};

RakudoScalar.prototype.setupSTable = function() {
  this.STable.addInternalMethod('$$assignunchecked', function(ctx, value) {
    console.log('storing into rakudo_scalar unchecked');
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$assign', function(ctx, value) {
    /* TODO - checking and WHENCE */
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$decont', function(ctx) {
    return this.$$getattr(Scalar, '$!value');
  });

  this.STable.addInternalMethod('$$getInt', function(ctx) {
    return this.$$decont().$$getInt();
  });

  this.STable.addInternalMethod('$$getNum', function(ctx) {
    return this.$$decont().$$getNum();
  });

  this.STable.addInternalMethod('$$getStr', function(ctx) {
    return this.$$decont().$$getStr();
  });

  this.STable.addInternalMethod('$$iscont', function() {
    return 1;
  });
};

RakudoScalar.prototype.serialize = function(cursor) {
  console.log('// serializing rakudo_scalar');
};

RakudoScalar.prototype.deserialize = function(cursor) {
  console.log('// deserializing rakudo_scalar');
};

RakudoScalar.prototype.name = 'rakudo_scalar';

containerSpecs.rakudo_scalar = RakudoScalar;

nqp.loadOps({op: op});
module.exports = null;

<|endoftext|>