<commit_before>'use strict';
const Session = require("./session");

/*
 * This controller provides high level behavioral control over the treadmill controller. It keeps the controller drivers
 * simple by implementing the running logic here. The interface to this controller should be similar to the human interface
 * you would experience on a real treadmill.
 *
 */

//const Simulation = require('./controllers/simulation.js');
//const Nordic = require('./controllers/nordic.js');

class ControlPanel {
    constructor() {
        this.name = "Treadmill Control";
        this.devicePath = "controlpanel";
        this.description = "Provides user experience for treadmill control";
        this.devices = [];
        this.driver = {};
        this.depends = ["motion/controllers"];

        this.desiredSpeed = 0;
        this.speedMeasured = 0;

        this.currentIncline = 0;
        this.desiredIncline = 0;

        // limits - in native format
        this.speedIncrement = 0.1;
        this.minSpeed = 2; // this is a built in limit of the speed controller
        this.maxSpeed = 9;

        this.inclineIncrement = this.inclineGradeToNative(1);
        this.minIncline = this.inclineGradeToNative(0);
        this.maxIncline = this.inclineGradeToNative(50);

        this.session = null;
    }

    probe(props) {
        if(this.refs.controllers && this.refs.controllers.devices && this.refs.controllers.devices.length>0) {
            let devs = this.refs.controllers.devices;
            let sim = null;
            this.motion = null;
            for(let i=0, _i=devs.length; i<_i; i++) {
                if(!devs[i].simulation) {
                    this.motion = devs[i];
                    break;
                } else
                    sim = devs[i];
            }
            if(this.motion===null) {
                if(sim) {
                    this.motion = sim;
                } else {
                    console.log("no motion controller available, at least I require the simulation controller");
                    return false;
                }
            }

            this.system = props;
            this.sessionChannel = this.postal.channel("session");

            this.devices.push(this);
            console.log("selected "+this.motion.name+" motion controller");

            // setting a user enables the control panel
            this.subscriptions = {
                enable: this.postal.subscribe({
                        channel: "user",
                        topic: "selected",
                        callback: (user) => {
                            if(user) {
                                // start a new session and enable the control panel
                                this.__newSession(user);
                                this.enable();
                            } else {
                                // user logged out, close his session and disable the control panel
                                this.__closeSession();
                                this.disable();
                            }
                        }})
            };

            return !!this.motion;
        }
        return false; // no controllers to try
    }

    enable() {
        console.log("enabling control panel for "+this.session.user.name);

        // startup a thread to send status every 1 second
        if(this.__updateInterval)
            clearInterval(this.__updateInterval);
        this.__updateInterval = setInterval(function() { this.__updateStatus() }.bind(this), 1000);
        this.active = true;
        this.__sendStatus();
    }

    disable() {
        console.log("disabling control panel");

        this.active = false;
        if(this.__updateInterval) {
            clearInterval(this.__updateInterval);
            this.__updateInterval = null;
        }
        this.__sendStatus();
    }

    __closeSession()
    {
        if(this.session) {
            this.session.deactivate();
            this.sessionChannel.publish("close", this.session);
            this.session = null;
        }
    }

    __newSession(user)
    {
        this.__closeSession();
        this.reset();
        this.system.session = this.session = new Session(user);
        if(user.goaltime!==null)
            this.goaltime=user.goaltime;
        if(user.goaldistance!==null)
            this.goaldistance=user.goaldistance;
        this.session.activate();
        this.sessionChannel.publish("new", this.session);
        //console.log("created new session");
    }

    __speed(value) {
        this.motion.speed(value);
        this.__sendEvent("speed", { value: value });
    }

    __activate() {
        this.motion.enable();
        this.__sendEvent("active", { active: true });
    }

    __deactivate() {
        this.motion.disable();
        this.__sendEvent("active", { active: false });
    }

    speed(value) {
        if(!this.motion) return false;

        var was_active = this.active;

        // TODO: The accelleration verbs
        if(value==="STOP") {
            return this.stop();
        } else if(value==="PANIC" || value==="ESTOP") {
            return this.fullstop();
        } else if(value==="START") {
            return this.speed("2.0");
        } else if(value==="++") {
            this.active = true;
            this.desiredSpeed += this.speedIncrement;
        } else if(value==="--") {
            this.active = true;
            this.desiredSpeed -= this.speedIncrement;
        } else if(!Number.isNaN(value)) {
            // startup if stopped
            this.active = true;
            console.log("speed <= "+value);
            this.desiredSpeed = Number(value).clamp(this.minSpeed, this.maxSpeed);
        } else {
            console.trace("unexpected speed value", value);
        }

        // check limits
        if(this.desiredSpeed>this.maxSpeed)
            this.desiredSpeed=this.maxSpeed;
        else if(this.desiredSpeed<this.minSpeed && this.desiredSpeed>0)
            this.desiredSpeed=this.minSpeed;

        // update the PWM
        this.headline = null;   // clear any headline
        this.__speed(this.desiredSpeed);
        if(!was_active && this.active) {
            this.__activate();
            if(!this.motion.active)
                this.motion.enable();
        }
    }

    incline(value)
    {
        if(value==="++") {
            this.desiredIncline += this.inclineIncrement;
        } else if(value==="--") {
            this.desiredIncline -= this.inclineIncrement;
        } else if(value==="FLOOR") {
            this.desiredIncline = this.minIncline;
        } else if(!isNaN(value)) {
            value = clamp(Number(value), this.minIncline, this.maxIncline);
        }

        // TODO: do something here to make the incline change
    }

    __stop(value) {
        if(!this.motion) return false;
        this.__sendEvent("stop");
        this.motion.stop(value)
    }

    stop()
    {
        // todo: somehow the autpace UI driver needs to get an event from here
        //if(this.autopace.active)
        //    this.activateAutopace(false);
        this.__stop();
        this.__updateStatus();
    }

    fullstop()
    {
        // todo: somehow the autpace UI driver needs to get an event from here
        //if(this.autopace.active)
        //    this.activateAutopace(false);

        this.active = false;
        this.motion.stop();
        this.desiredSpeed=0;
        this.headline = "Emergency!";
        this.__sendEvent("fullstop");
        this.__updateStatus();
    }

    reset()
    {
        this.stop();
        this.runningSince=null;
        this.runningTime = 0;
        if(this.session)
            this.session = null;    // session begins when user starts treadmill again
        this.__sendStatus();
        this.__sendEvent("reset");
    }

    __sendEvent(name, data) {
        this.bus.publish("event."+name, data);
    }

    __updateStatus() {
        var now = new Date();

        // if we are starting or stopping, then start our running timer
        if(this.session) {
            if (!this.active && this.session.runningSince != null) {
                // we are stopping, add latest runtime to accumulated total
                this.runningTime += new Date().valueOf() - this.runningSince.valueOf();
                this.runningSince = null;
            } else if (this.active && this.session.runningSince == null) {
                // we are starting up, could be a new session or a continuation of an existing session
                if (this.session.id == null) {
                    // new session
                    this.runningSince = new Date();
                    this.session.id = this.runningSince.unix_timestamp();
                } else {
                    this.runningSince = new Date();
                }
            }
        }

        // HACK: make the incline move for now
        if(this.desiredIncline != this.currentIncline) {
            if(this.currentIncline < this.desiredIncline)
                this.currentIncline += this.inclineIncrement;
            else
                this.currentIncline -= this.inclineIncrement;
        }

        this.__sendStatus();
    };

    state() {
        if(this.motion.desired===0 && this.motion.value>0)
            return "Stopping";
        else if(!this.motion.active || this.motion.value===0)
            return "Stopped";
        else if(this.motion.desired>this.minSpeed && this.motion.value<this.minSpeed)
            return "Starting";
        else if(this.motion.active && this.motion.value>=8)
            return "Sprinting";
        else if(this.motion.active && this.motion.value>=5.6)
            return "Running";
        else if(this.motion.active && this.motion.value>=4.2)
            return "Jogging";
        else if(this.motion.active && this.motion.value>=3.0)
            return "Walking";
        else if(this.motion.active && this.motion.value>=2.0)
            return "Walking Dead";
        else
            return"Duck!";  // we should never get here
    }

    __sendStatus() {
        let status = {
            type: 'status',
            headline: this.headline ? this.headline : this.state(),
            timestamp: new Date(),
            active: this.active,
            runningSince: this.session ? this.session.runningSince : null,
            runningTime: this.session ? this.session.getTotalRunningMillis() : 0,
            distance: this.session ? this.session.distance : 0,
            currentSpeed: this.motion.value,
            desiredSpeed: this.desiredSpeed,
            currentIncline: this.nativeToInclineGrade(this.currentIncline),
            desiredIncline: this.nativeToInclineGrade(this.desiredIncline)
        };
        this.bus.publish("state", status);
    }

    inclineGradeToNative(value)
    {
        return Number(value);
    };

    nativeToInclineGrade(value)
    {
        return Number(value);
    };

};

module.exports = ControlPanel;
<commit_msg>converted speed member variables into a contained object<commit_after>'use strict';
const Session = require("./session");

/*
 * This controller provides high level behavioral control over the treadmill controller. It keeps the controller drivers
 * simple by implementing the running logic here. The interface to this controller should be similar to the human interface
 * you would experience on a real treadmill.
 *
 */

//const Simulation = require('./controllers/simulation.js');
//const Nordic = require('./controllers/nordic.js');

class ControlPanel {
    constructor() {
        this.name = "Treadmill Control";
        this.devicePath = "controlpanel";
        this.description = "Provides user experience for treadmill control";
        this.devices = [];
        this.driver = {};
        this.depends = ["motion/controllers"];

        // Note: we are actually adding these members to the function object speed()
        // so we cant just use this.speed= {...} syntax here.
        this.speed.target=0;
        this.speed.measured=0;
        this.speed.increment=0.1;
        this.speed.min= 2;
        this.speed.max= 9;
        //};

        this.currentIncline = 0;
        this.desiredIncline = 0;
        this.inclineIncrement = this.inclineGradeToNative(1);
        this.minIncline = this.inclineGradeToNative(0);
        this.maxIncline = this.inclineGradeToNative(50);

        this.session = null;
    }

    probe(props) {
        if(this.refs.controllers && this.refs.controllers.devices && this.refs.controllers.devices.length>0) {
            let devs = this.refs.controllers.devices;
            let sim = null;
            this.motion = null;
            for(let i=0, _i=devs.length; i<_i; i++) {
                if(!devs[i].simulation) {
                    this.motion = devs[i];
                    break;
                } else
                    sim = devs[i];
            }
            if(this.motion===null) {
                if(sim) {
                    this.motion = sim;
                } else {
                    console.log("no motion controller available, at least I require the simulation controller");
                    return false;
                }
            }

            this.system = props;
            this.sessionChannel = this.postal.channel("session");

            this.devices.push(this);
            console.log("selected "+this.motion.name+" motion controller");

            // setting a user enables the control panel
            this.subscriptions = {
                enable: this.postal.subscribe({
                        channel: "user",
                        topic: "selected",
                        callback: (user) => {
                            if(user) {
                                // start a new session and enable the control panel
                                this.__newSession(user);
                                this.enable();
                            } else {
                                // user logged out, close his session and disable the control panel
                                this.__closeSession();
                                this.disable();
                            }
                        }})
            };

            return !!this.motion;
        }
        return false; // no controllers to try
    }

    enable() {
        console.log("enabling control panel for "+this.session.user.name);

        // startup a thread to send status every 1 second
        if(this.__updateInterval)
            clearInterval(this.__updateInterval);
        this.__updateInterval = setInterval(function() { this.__updateStatus() }.bind(this), 1000);
        this.active = true;
        this.__sendStatus();
    }

    disable() {
        console.log("disabling control panel");

        this.active = false;
        if(this.__updateInterval) {
            clearInterval(this.__updateInterval);
            this.__updateInterval = null;
        }
        this.__sendStatus();
    }

    __closeSession()
    {
        if(this.session) {
            this.session.deactivate();
            this.sessionChannel.publish("close", this.session);
            this.session = null;
        }
    }

    __newSession(user)
    {
        this.__closeSession();
        this.reset();
        this.system.session = this.session = new Session(user);
        if(user.goaltime!==null)
            this.goaltime=user.goaltime;
        if(user.goaldistance!==null)
            this.goaldistance=user.goaldistance;
        this.session.activate();
        this.sessionChannel.publish("new", this.session);
        //console.log("created new session");
    }

    __speed(value) {
        this.motion.speed(value);
        this.__sendEvent("speed", { value: value });
    }

    __activate() {
        this.motion.enable();
        this.__sendEvent("active", { active: true });
    }

    __deactivate() {
        this.motion.disable();
        this.__sendEvent("active", { active: false });
    }

    speed(value) {
        if(!this.motion) return false;

        var was_active = this.active;

        // TODO: The accelleration verbs
        if(value==="STOP") {
            return this.stop();
        } else if(value==="PANIC" || value==="ESTOP") {
            return this.fullstop();
        } else if(value==="START") {
            return this.speed("2.0");
        } else if(value==="++") {
            this.active = true;
            this.speed.target += this.speed.increment;
        } else if(value==="--") {
            this.active = true;
            this.speed.target -= this.speed.increment;
        } else if(!Number.isNaN(value)) {
            // startup if stopped
            this.active = true;
            console.log("speed <= "+value);
            this.speed.target = Number(value).clamp(this.speed.min, this.speed.max);
        } else {
            console.trace("unexpected speed value", value);
        }

        // check limits
        this.speed.target = (this.speed.target>0)
            ? this.speed.target.clamp(this.speed.min, this.speed.max)  // restrict to min/max
            : 0; // always allow 0 (off)

        // update the PWM
        this.headline = null;   // clear any headline
        this.__speed(this.speed.target);
        if(!was_active && this.active) {
            this.__activate();
            if(!this.motion.active)
                this.motion.enable();
        }
    }

    incline(value)
    {
        if(value==="++") {
            this.desiredIncline += this.inclineIncrement;
        } else if(value==="--") {
            this.desiredIncline -= this.inclineIncrement;
        } else if(value==="FLOOR") {
            this.desiredIncline = this.minIncline;
        } else if(!isNaN(value)) {
            value = value.clamp(this.minIncline, this.maxIncline);
        }

        // TODO: do something here to make the incline change
    }

    __stop(value) {
        if(!this.motion) return false;
        this.__sendEvent("stop");
        this.motion.stop(value)
    }

    stop()
    {
        // todo: somehow the autpace UI driver needs to get an event from here
        //if(this.autopace.active)
        //    this.activateAutopace(false);
        this.__stop();
        this.__updateStatus();
    }

    fullstop()
    {
        // todo: somehow the autpace UI driver needs to get an event from here
        //if(this.autopace.active)
        //    this.activateAutopace(false);

        this.active = false;
        this.motion.stop();
        this.speed.target=0;
        this.headline = "Emergency!";
        this.__sendEvent("fullstop");
        this.__updateStatus();
    }

    reset()
    {
        this.stop();
        this.runningSince=null;
        this.runningTime = 0;
        if(this.session)
            this.session = null;    // session begins when user starts treadmill again
        this.__sendStatus();
        this.__sendEvent("reset");
    }

    __sendEvent(name, data) {
        this.bus.publish("event."+name, data);
    }

    __updateStatus() {
        var now = new Date();

        // if we are starting or stopping, then start our running timer
        if(this.session) {
            if (!this.active && this.session.runningSince != null) {
                // we are stopping, add latest runtime to accumulated total
                this.runningTime += new Date().valueOf() - this.runningSince.valueOf();
                this.runningSince = null;
            } else if (this.active && this.session.runningSince == null) {
                // we are starting up, could be a new session or a continuation of an existing session
                if (this.session.id == null) {
                    // new session
                    this.runningSince = new Date();
                    this.session.id = this.runningSince.unix_timestamp();
                } else {
                    this.runningSince = new Date();
                }
            }
        }

        // HACK: make the incline move for now
        if(this.desiredIncline != this.currentIncline) {
            if(this.currentIncline < this.desiredIncline)
                this.currentIncline += this.inclineIncrement;
            else
                this.currentIncline -= this.inclineIncrement;
        }

        this.__sendStatus();
    };

    state() {
        if(this.motion.desired===0 && this.motion.value>0)
            return "Stopping";
        else if(!this.motion.active || this.motion.value===0)
            return "Stopped";
        else if(this.motion.desired>this.speed.min && this.motion.value<this.speed.min)
            return "Starting";
        else if(this.motion.active && this.motion.value>=8)
            return "Sprinting";
        else if(this.motion.active && this.motion.value>=5.6)
            return "Running";
        else if(this.motion.active && this.motion.value>=4.2)
            return "Jogging";
        else if(this.motion.active && this.motion.value>=3.0)
            return "Walking";
        else if(this.motion.active && this.motion.value>=2.0)
            return "Walking Dead";
        else
            return"Duck!";  // we should never get here
    }

    __sendStatus() {
        let status = {
            type: 'status',
            headline: this.headline ? this.headline : this.state(),
            timestamp: new Date(),
            active: this.active,
            runningSince: this.session ? this.session.runningSince : null,
            runningTime: this.session ? this.session.getTotalRunningMillis() : 0,
            distance: this.session ? this.session.distance : 0,
            currentSpeed: this.motion.value,
            desiredSpeed: this.speed.target,
            currentIncline: this.nativeToInclineGrade(this.currentIncline),
            desiredIncline: this.nativeToInclineGrade(this.desiredIncline)
        };
        this.bus.publish("state", status);
    }

    inclineGradeToNative(value)
    {
        return Number(value);
    };

    nativeToInclineGrade(value)
    {
        return Number(value);
    };

};

module.exports = ControlPanel;
<|endoftext|>


<commit_before>import '../BookReader/jquery-1.10.1.js';
import '../BookReader/jquery-ui-1.12.0.min.js';
import '../BookReader/jquery.browser.min.js';
import '../BookReader/dragscrollable-br.js';
import '../BookReader/jquery.colorbox-min.js';
import '../BookReader/jquery.bt.min.js';

import BookReader from '../src/js/BookReader.js';
import '../src/js/plugins/plugin.resume.js';
import '../src/js/plugins/plugin.url.js';

let br;
beforeAll(() => {
  document.body.innerHTML = '
';
  br = new BookReader();
});

afterEach(() => {
  jest.clearAllMocks();
});

test('has registered PostInit events', () => {
  expect(BookReader.eventNames.PostInit).toBeTruthy();
});

test('has registered zoom events', () => {
  expect(BookReader.eventNames.zoomIn).toBeTruthy();
  expect(BookReader.eventNames.zoomOut).toBeTruthy();
});

test('has registered view type selected events', () => {
  expect(BookReader.eventNames['1PageViewSelected']).toBeTruthy();
  expect(BookReader.eventNames['2PageViewSelected']).toBeTruthy();
  expect(BookReader.eventNames['3PageViewSelected']).toBeTruthy();
});

test('has registered fullscreen toggle event', () => {
  expect(BookReader.eventNames.fullscreenToggled).toBeTruthy();
});

test('checks cookie when initParams called', () => {
  br.getResumeValue = jest.fn(() => 15);
  br.urlReadFragment = jest.fn(() => '');

  const params = br.initParams();
  expect(br.getResumeValue).toHaveBeenCalledTimes(1);
  expect(params.init).toBe(true);
  expect(params.index).toBe(15);
  expect(params.fragmentChange).toBe(true);
});

test('does not check cookie when initParams called', () => {
  br.getResumeValue = jest.fn(() => null);
  br.urlReadFragment = jest.fn(() => '');
  br.options.enablePageResume = false;

  const params = br.initParams();
  expect(br.getResumeValue).toHaveBeenCalledTimes(0);
  expect(params.init).toBe(true);
  expect(params.index).toBe(0);
  expect(params.fragmentChange).toBe(false);
});

test('overrides cookie if page fragment when InitParams called', () => {
  br.getResumeValue = jest.fn(() => 15);
  br.urlReadFragment = jest.fn(() => 'page/n4');
  br.options.enablePageResume = true;

  const params = br.initParams();
  expect(br.getResumeValue).toHaveBeenCalledTimes(1);
  expect(params.init).toBe(true);
  expect(params.index).toBe(4);
  expect(params.fragmentChange).toBe(true);
});

test('sets prevReadMode when init called', () => {
  br.init();
  expect(br.prevReadMode).toBeTruthy();
});

test('sets prevPageMode if initial mode is thumb', () => {
  br.urlReadFragment = jest.fn(() => 'page/n4/mode/thumb');

  br.init();
  expect(br.prevReadMode).toBe(BookReader.constMode1up);
});

test('calls switchMode with init option when init called', () => {
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('init', true);
});

test('has suppressFragmentChange true when init with no input', () => {
  br.getResumeValue = jest.fn(() => null);
  br.urlReadFragment = jest.fn(() => '');
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('suppressFragmentChange', true);
});

test('has suppressFragmentChange false when init with cookie', () => {
  br.getResumeValue = jest.fn(() => 5);
  br.urlReadFragment = jest.fn(() => '');
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('suppressFragmentChange', false);
});

test('has suppressFragmentChange false when init with fragment', () => {
  br.getResumeValue = jest.fn(() => null);
  br.urlReadFragment = jest.fn(() => 'mode/1up');
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('suppressFragmentChange', false);
});
<commit_msg>Clarify test, add ref to special code in comment<commit_after>import '../BookReader/jquery-1.10.1.js';
import '../BookReader/jquery-ui-1.12.0.min.js';
import '../BookReader/jquery.browser.min.js';
import '../BookReader/dragscrollable-br.js';
import '../BookReader/jquery.colorbox-min.js';
import '../BookReader/jquery.bt.min.js';

import BookReader from '../src/js/BookReader.js';
import '../src/js/plugins/plugin.resume.js';
import '../src/js/plugins/plugin.url.js';

let br;
beforeAll(() => {
  document.body.innerHTML = '
';
  br = new BookReader();
});

afterEach(() => {
  jest.clearAllMocks();
});

test('has registered PostInit events', () => {
  expect(BookReader.eventNames.PostInit).toBeTruthy();
});

test('has registered zoom events', () => {
  expect(BookReader.eventNames.zoomIn).toBeTruthy();
  expect(BookReader.eventNames.zoomOut).toBeTruthy();
});

test('has registered view type selected events', () => {
  expect(BookReader.eventNames['1PageViewSelected']).toBeTruthy();
  expect(BookReader.eventNames['2PageViewSelected']).toBeTruthy();
  expect(BookReader.eventNames['3PageViewSelected']).toBeTruthy();
});

test('has registered fullscreen toggle event', () => {
  expect(BookReader.eventNames.fullscreenToggled).toBeTruthy();
});

test('checks cookie when initParams called', () => {
  br.getResumeValue = jest.fn(() => 15);
  br.urlReadFragment = jest.fn(() => '');

  const params = br.initParams();
  expect(br.getResumeValue).toHaveBeenCalledTimes(1);
  expect(params.init).toBe(true);
  expect(params.index).toBe(15);
  expect(params.fragmentChange).toBe(true);
});

test('does not check cookie when initParams called', () => {
  br.getResumeValue = jest.fn(() => null);
  br.urlReadFragment = jest.fn(() => '');
  br.options.enablePageResume = false;

  const params = br.initParams();
  expect(br.getResumeValue).toHaveBeenCalledTimes(0);
  expect(params.init).toBe(true);
  expect(params.index).toBe(0);
  expect(params.fragmentChange).toBe(false);
});

test('gets index from fragment when both fragment and cookie when InitParams called', () => {
  br.getResumeValue = jest.fn(() => 15);
  br.urlReadFragment = jest.fn(() => 'page/n4');
  br.options.enablePageResume = true;

  const params = br.initParams();
  expect(br.getResumeValue).toHaveBeenCalledTimes(1);
  expect(params.init).toBe(true);
  expect(params.index).toBe(4);
  expect(params.fragmentChange).toBe(true);
});

test('sets prevReadMode when init called', () => {
  br.init();
  expect(br.prevReadMode).toBeTruthy();
});

// Default behavior same in
//   BookReader.prototype.drawLeafsThumbnail
//   BookReader.prototype.getPrevReadMode
test('sets prevPageMode if initial mode is thumb', () => {
  br.urlReadFragment = jest.fn(() => 'page/n4/mode/thumb');

  br.init();
  expect(br.prevReadMode).toBe(BookReader.constMode1up);
});

test('calls switchMode with init option when init called', () => {
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('init', true);
});

test('has suppressFragmentChange true when init with no input', () => {
  br.getResumeValue = jest.fn(() => null);
  br.urlReadFragment = jest.fn(() => '');
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('suppressFragmentChange', true);
});

test('has suppressFragmentChange false when init with cookie', () => {
  br.getResumeValue = jest.fn(() => 5);
  br.urlReadFragment = jest.fn(() => '');
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('suppressFragmentChange', false);
});

test('has suppressFragmentChange false when init with fragment', () => {
  br.getResumeValue = jest.fn(() => null);
  br.urlReadFragment = jest.fn(() => 'mode/1up');
  br.switchMode = jest.fn();

  br.init();
  expect(br.switchMode.mock.calls[0][1])
    .toHaveProperty('suppressFragmentChange', false);
});
<|endoftext|>


<commit_before>/**
 * L.Control.GeoSearch - search for an address and zoom to it's location
 * L.GeoSearch.Provider.OpenStreetMap uses openstreetmap geocoding service
 * https://github.com/smeijer/leaflet.control.geosearch
 */

L.GeoSearch.Provider.OpenStreetMap = L.Class.extend({
    options: {

    },

    initialize: function(options) {
        options = L.Util.setOptions(this, options);
    },

    GetServiceUrl: function (qry) {
        var parameters = L.Util.extend({
            q: qry,
            format: 'json'
        }, this.options);

        return 'http://nominatim.openstreetmap.org/search'
            + L.Util.getParamString(parameters);
    },

    ParseJSON: function (data) {
        if (data.length == 0)
            return [];

        var results = [];
        for (var i = 0; i < data.length; i++)
            results.push(new L.GeoSearch.Result(
                data[i].lon,
                data[i].lat,
                data[i].display_name
            ));

        return results;
    }
});<commit_msg>remove protocol from nominatim url<commit_after>/**
 * L.Control.GeoSearch - search for an address and zoom to it's location
 * L.GeoSearch.Provider.OpenStreetMap uses openstreetmap geocoding service
 * https://github.com/smeijer/leaflet.control.geosearch
 */

L.GeoSearch.Provider.OpenStreetMap = L.Class.extend({
    options: {

    },

    initialize: function(options) {
        options = L.Util.setOptions(this, options);
    },

    GetServiceUrl: function (qry) {
        var parameters = L.Util.extend({
            q: qry,
            format: 'json'
        }, this.options);

        return '//nominatim.openstreetmap.org/search'
            + L.Util.getParamString(parameters);
    },

    ParseJSON: function (data) {
        if (data.length == 0)
            return [];

        var results = [];
        for (var i = 0; i < data.length; i++)
            results.push(new L.GeoSearch.Result(
                data[i].lon,
                data[i].lat,
                data[i].display_name
            ));

        return results;
    }
});
<|endoftext|>


<commit_before>requirejs.config({
    shim: {
        'underscore': {
            exports: '_'
        }
    }
});

require(["./sweet"], function(sweet) {
    var storage_code = 'editor_code';
    var storage_mode = 'editor_mode';

    var starting_code = $("#editor").text();
    var compileWithSourcemap = $("body").attr("data-sourcemap") === "true";

    var editor = CodeMirror.fromTextArea($('#editor')[0], {
        lineNumbers: true,
        smartIndent: false,
        indentWithTabs: true,
        tabSize: 2,
        autofocus: true,
        theme: 'solarized dark'
    });
    editor.setValue(localStorage[storage_code] ? localStorage[storage_code] : starting_code);
    if(localStorage[storage_mode]) {
        editor.setOption("keyMap", localStorage[storage_mode]);
    }

    var output = CodeMirror.fromTextArea($('#output')[0], {
        lineNumbers: true,
        theme: 'solarized dark',
        readOnly: true
    });

    $('#btn-vim').click(function() {
        editor.setOption('keyMap', 'vim');
        editor.focus();
        localStorage[storage_mode] = "vim";
    });
    $('#btn-emacs').click(function() {
        editor.setOption('keyMap', 'emacs');
        editor.focus();
        localStorage[storage_mode] = "emacs";
    });

    var updateTimeout;
    editor.on("change", function(e) {
        clearTimeout(updateTimeout);
        updateTimeout = setTimeout(updateExpand, 200);
    });

    function updateExpand() {
        var code = editor.getValue();
        var expanded, compiled;
        try {
            if (compileWithSourcemap) {
                var res = sweet.compileWithSourcemap(code);
                compiled = res.code;
            } else {
                compiled = sweet.compile(code);
            }
            output.setValue(compiled);
            localStorage[storage_code] = code;

            $('#errors').text('');
        } catch (e) {
            $('#errors').text(e);
        }
    }
    updateExpand();
});
<commit_msg>updates to compile return value<commit_after>requirejs.config({
    shim: {
        'underscore': {
            exports: '_'
        }
    }
});

require(["./sweet"], function(sweet) {
    var storage_code = 'editor_code';
    var storage_mode = 'editor_mode';

    var starting_code = $("#editor").text();
    var compileWithSourcemap = $("body").attr("data-sourcemap") === "true";

    var editor = CodeMirror.fromTextArea($('#editor')[0], {
        lineNumbers: true,
        smartIndent: false,
        indentWithTabs: true,
        tabSize: 2,
        autofocus: true,
        theme: 'solarized dark'
    });
    editor.setValue(localStorage[storage_code] ? localStorage[storage_code] : starting_code);
    if(localStorage[storage_mode]) {
        editor.setOption("keyMap", localStorage[storage_mode]);
    }

    var output = CodeMirror.fromTextArea($('#output')[0], {
        lineNumbers: true,
        theme: 'solarized dark',
        readOnly: true
    });

    $('#btn-vim').click(function() {
        editor.setOption('keyMap', 'vim');
        editor.focus();
        localStorage[storage_mode] = "vim";
    });
    $('#btn-emacs').click(function() {
        editor.setOption('keyMap', 'emacs');
        editor.focus();
        localStorage[storage_mode] = "emacs";
    });

    var updateTimeout;
    editor.on("change", function(e) {
        clearTimeout(updateTimeout);
        updateTimeout = setTimeout(updateExpand, 200);
    });

    function updateExpand() {
        var code = editor.getValue();
        var expanded, compiled, res;
        try {
            if (compileWithSourcemap) {
                res = sweet.compile(code, {
                    sourceMap: true,
                    filename: "test.js"
                });
            } else {
                res = sweet.compile(code, {
                    sourceMap: false
                });
            }
            compiled = res.code;
            output.setValue(compiled);
            localStorage[storage_code] = code;

            $('#errors').text('');
        } catch (e) {
            $('#errors').text(e);
        }
    }
    updateExpand();
});
<|endoftext|>


<commit_before>
var graphs = [];        // rickshaw objects
var datum = [];         // metric data
var aliases = [];       // alias strings
var descriptions = [];  // description strings
var realMetrics = [];   // non-false targets

// minutes of data in the live feed
var period = (typeof period == 'undefined') ? 5 : period;

// gather our non-false targets
function gatherRealMetrics() {
  var falseTargets = 0;
  for (var i=0; i<metrics.length; i++) {
    if (metrics[i].target === false) {
    falseTargets++;
    } else {
      realMetrics[i - falseTargets] = metrics[i];
    }
  }
}

// build our graph objects
function constructGraphs() {
  for (var i=0; i<realMetrics.length; i++) {
    aliases[i] = realMetrics[i].alias || realMetrics[i].target;
    descriptions[i] = realMetrics[i].description || null;
    datum[i] = [{ x:0, y:0 }];
    graphs[i] = new Rickshaw.Graph({
      element: document.querySelector('.graph' + i),
      width: 348,
      height: 100,
      interpolation: 'step-after',
      series: [{
        name: aliases[i],
        color: '#afdab1',
        data: datum[i]
      }]
    });
    graphs[i].render();
  }
}

// construct url
var myUrl;
var padnulls = (typeof padnulls == 'undefined') ? true : padnulls;
function constructUrl(period) {
  var targets = "";
  for (var i=0; i<realMetrics.length; i++) {
    if (i != 0) {
      targets += '&';
    }
    if (padnulls === true) {
      targets += ('target=keepLastValue(' + encodeURI(realMetrics[i].target) + ')');
    } else {
      targets += ('target=' + encodeURI(realMetrics[i].target));
    }
  }
  myUrl = url + '/render/?' + targets + '&from=-' + period + 'minutes&format=json';
}

// refresh the graph
function refreshData(immediately) {

  getData(function(values) {
    for (var i=0; i<graphs.length; i++) {
      for (var j=0; j<values[i].length; j++) {
        if (typeof values[i][j] !== "undefined") {
          datum[i][j] = values[i][j];
        }
      }

      // check our thresholds and update color
      var lastValue = datum[i][datum[i].length - 1].y;
      var warning = realMetrics[i].warning;
      var critical = realMetrics[i].critical;
      if (critical > warning) {
        if (lastValue >= critical) {
          graphs[i].series[0].color = '#d59295';
        } else if (lastValue >= warning) {
          graphs[i].series[0].color = '#f5cb56';
        } else {
          graphs[i].series[0].color = '#afdab1';
        }
      } else {
        if (lastValue <= critical) {
          graphs[i].series[0].color = '#d59295';
        } else if (lastValue <= warning) {
          graphs[i].series[0].color = '#f5cb56';
        } else {
          graphs[i].series[0].color = '#afdab1';
        }
      }
      // we want to render immediately, i.e.
      // as soon as ajax completes
      // used for time period / pause view
      if (immediately) {
        updateGraphs(i);
      }
    }
    values = null;
  });

  // we can wait until all data is gathered, i.e.
  // the live refresh should happen synchronously
  if (!immediately) {
    for (var i=0; i<graphs.length; i++) {
      updateGraphs(i);
    }
  }
}

// retrieve dashboard list
function getDashboards(cb) {
  $.ajax({
    dataType: 'json',
    error: function(xhr, textStatus, errorThrown) { console.log(errorThrown); },
    url: '/'
  }).done(function(d) {
    cb(d.dashboards);
  });
}

// retrieve the data from Graphite
function getData(cb) {
  var myDatum = [];
  $.ajax({
    beforeSend: function(xhr) {
      if (auth.length > 0) {
        var bytes = Crypto.charenc.Binary.stringToBytes(auth);
        var base64 = Crypto.util.bytesToBase64(bytes);
        xhr.setRequestHeader("Authorization", "Basic " + base64);
      }
    },
    dataType: 'json',
    error: function(xhr, textStatus, errorThrown) { console.log(errorThrown); },
    url: myUrl
  }).done(function(d) {
    if (d.length > 0) {
      for (var i=0; i<d.length; i++) {
        myDatum[i] = [];
        myDatum[i][0] = { x: d[i].datapoints[0][1], y: d[i].datapoints[0][0] };
        for (var j=0; j<d[i].datapoints.length; j++) {
          myDatum[i][j] = { x: d[i].datapoints[j][1], y: d[i].datapoints[j][0] };
        }
      }
    }
    cb(myDatum);
  });
}

// perform the actual graph object and
// overlay name and number updates
function updateGraphs(i) {
  // update our graph
  graphs[i].update();
  if (datum[i][datum[i].length - 1] !== undefined) {
    var lastValue = datum[i][datum[i].length - 1].y;
    var lastValueDisplay;
    if ((typeof lastValue == 'number') && lastValue < 2.0) {
      lastValueDisplay = Math.round(lastValue*1000)/1000;
    } else {
      lastValueDisplay = parseInt(lastValue);
    }
    if (realMetrics[i].description) {
      $('.description' + i).html('Note:

' + descriptions[i]);
    }
    $('.overlay-name' + i).text(aliases[i]);
    $('.overlay-number' + i).text(lastValueDisplay);
    if (realMetrics[i].unit) {
      $('.overlay-number' + i).append('' + realMetrics[i].unit + '');
    }
  } else {
    $('.overlay-name' + i).text(aliases[i]);
    $('.overlay-number' + i).html('NF');
  }
}

// add our containers
function buildContainers() {
  var falseTargets = 0;
  for (var i=0; i<metrics.length; i++) {
    if (metrics[i].target === false) {
      $('.main').append('

');
      falseTargets++;
    } else {
      var j = i - falseTargets;
      $('.main').append(
        '
' +
        '' +
        '

' +
        '

' +
        '
'
      );
    }
  }
}

// filter out false targets
gatherRealMetrics();

// build our div containers
buildContainers();

// build our graph objects
constructGraphs();

// build our url
constructUrl(period);

// set our theme
var myTheme = (typeof theme == 'undefined') ? 'default' : theme;
if (myTheme === "dark") { enableNightMode(); }

// hide our toolbar if necessary
var toolbar = (typeof toolbar == 'undefined') ? true : toolbar;
if (!toolbar) { $('div.toolbar').css('display', 'none'); }

// initial load screen
for (var i=0; i<graphs.length; i++) {
  if (realMetrics[i].target === false) {
    //continue;
  } else if (myTheme === "dark") {
    $('.overlay-number' + i).html('');
  } else {
    $('.overlay-number' + i).html('');
  }
}
refreshData("now");

// define our refresh and start interval
var refreshInterval = (typeof refresh == 'undefined') ? 2000 : refresh;
var refreshId = setInterval(refreshData, refreshInterval);

// set our "live" interval hint
$('.toolbar ul li.timepanel a.play').text(period + 'min');

// populate and render our navigation list
$('.title').on('hover', 'span', function() {
  getDashboards(function(list) {
    $('.title span').html('<select><option value="/">welcome</option></select>');
    for (var i in list) {
      if (list[i] === window.location.pathname.replace(/^\//, '')) {
        $('.title select').append('<option selected="selected">' + list[i] + '</option>');
      } else {
        $('.title select').append('<option>' + list[i] + '</option>');
      }
    }
    $('.title span select').focus();
  });
});

// display description
$(document).on('mouseenter', 'div.graph', function() {
  if ($(this).find('span.description').text().length > 0) {
    $(this).find('span.description').css('visibility', 'visible');
  }
});

// hide description
$(document).on('mouseleave', 'div.graph', function() {
  $(this).find('span.description').css('visibility', 'hidden');
});

// clear navigation list on focusout
$('.title span').on('focusout', 'select', function() {
  $('.title span').html(window.location.pathname.replace(/^\//, ''));
});

// navigate to selection
$('.title span').on('change', 'select', function() {
  window.location.pathname = '/' + $(this).val();
});

// activate night mode
function enableNightMode() {
  $('body').addClass('night');
  $('div.title h1').addClass('night');
  $('div.graph svg').css('opacity', '0.8');
  $('span.description').addClass('night');
  $('div.overlay-name').addClass('night');
  $('div.overlay-number').addClass('night');
  $('div.toolbar ul li.timepanel').addClass('night');
}

// deactivate night mode
function disableNightMode() {
  $('body').removeClass('night');
  $('div.title h1').removeClass('night');
  $('div.graph svg').css('opacity', '1.0');
  $('span.description').removeClass('night');
  $('div.overlay-name').removeClass('night');
  $('div.overlay-number').removeClass('night');
  $('div.toolbar ul li.timepanel').removeClass('night');
}

// activate night mode by click
$('li.toggle-night').on('click', 'a', function() {
  if ($('body').hasClass('night')) {
    disableNightMode();
  } else {
    enableNightMode();
  }
});

// toggle number display
$('li.toggle-nonum').on('click', 'a', function() { $('div.overlay-number').toggleClass('nonum'); });

// time panel, pause live feed and show range
$('.toolbar ul li.timepanel').on('click', 'a.range', function() {
  var period = $(this).attr("title");
  for (var i=0; i<realMetrics.length; i++) {
    constructUrl(period);
  }
  if (! $('.toolbar ul li.timepanel a.play').hasClass('pause')) {
    $('.toolbar ul li.timepanel a.play').addClass('pause');
  }
  $('.toolbar ul li.timepanel a.play').text('paused');
  $(this).parent('li').parent('ul').find('li').removeClass('selected');
  $(this).parent('li').addClass('selected');
  refreshData("now");
  clearInterval(refreshId);
});

// time panel, resume live feed
$('.toolbar ul li.timepanel').on('click', 'a.play', function() {
  for (var i=0; i<realMetrics.length; i++) {
    constructUrl(5);
  }
  $(this).parent('li').parent('ul').find('li').removeClass('selected');
  $(this).parent('li').addClass('selected');
  $(this).removeClass('pause');
  $('.toolbar ul li.timepanel a.play').text(period + 'min');
  refreshData("now");
  // explicitly clear the old Interval in case
  // someone "doubles up" on the live play button
  clearInterval(refreshId);
  // remove and recreate the original graphs[]
  // helps clear out any rendering artifacts
  $('.graph svg').remove();
  constructGraphs();
  // reapply our style settings if night mode is active
  if ($('body').hasClass('night')) { enableNightMode(); }
  // restart our refresh interval
  refreshId = setInterval(refreshData, refreshInterval);
});

<commit_msg>add stroke to graphs<commit_after>
var graphs = [];        // rickshaw objects
var datum = [];         // metric data
var aliases = [];       // alias strings
var descriptions = [];  // description strings
var realMetrics = [];   // non-false targets

// minutes of data in the live feed
var period = (typeof period == 'undefined') ? 5 : period;

// gather our non-false targets
function gatherRealMetrics() {
  var falseTargets = 0;
  for (var i=0; i<metrics.length; i++) {
    if (metrics[i].target === false) {
    falseTargets++;
    } else {
      realMetrics[i - falseTargets] = metrics[i];
    }
  }
}

// build our graph objects
function constructGraphs() {
  for (var i=0; i<realMetrics.length; i++) {
    aliases[i] = realMetrics[i].alias || realMetrics[i].target;
    descriptions[i] = realMetrics[i].description || null;
    datum[i] = [{ x:0, y:0 }];
    graphs[i] = new Rickshaw.Graph({
      element: document.querySelector('.graph' + i),
      width: 348,
      height: 100,
      interpolation: 'step-after',
      renderer: 'area',
      stroke: true,
      series: [{
        name: aliases[i],
        color: '#afdab1',
        data: datum[i]
      }]
    });
    graphs[i].render();
  }
}

// construct url
var myUrl;
var padnulls = (typeof padnulls == 'undefined') ? true : padnulls;
function constructUrl(period) {
  var targets = "";
  for (var i=0; i<realMetrics.length; i++) {
    if (i != 0) {
      targets += '&';
    }
    if (padnulls === true) {
      targets += ('target=keepLastValue(' + encodeURI(realMetrics[i].target) + ')');
    } else {
      targets += ('target=' + encodeURI(realMetrics[i].target));
    }
  }
  myUrl = url + '/render/?' + targets + '&from=-' + period + 'minutes&format=json';
}

// refresh the graph
function refreshData(immediately) {

  getData(function(values) {
    for (var i=0; i<graphs.length; i++) {
      for (var j=0; j<values[i].length; j++) {
        if (typeof values[i][j] !== "undefined") {
          datum[i][j] = values[i][j];
        }
      }

      // check our thresholds and update color
      var lastValue = datum[i][datum[i].length - 1].y;
      var warning = realMetrics[i].warning;
      var critical = realMetrics[i].critical;
      if (critical > warning) {
        if (lastValue >= critical) {
          graphs[i].series[0].color = '#d59295';
        } else if (lastValue >= warning) {
          graphs[i].series[0].color = '#f5cb56';
        } else {
          graphs[i].series[0].color = '#afdab1';
        }
      } else {
        if (lastValue <= critical) {
          graphs[i].series[0].color = '#d59295';
        } else if (lastValue <= warning) {
          graphs[i].series[0].color = '#f5cb56';
        } else {
          graphs[i].series[0].color = '#afdab1';
        }
      }
      // we want to render immediately, i.e.
      // as soon as ajax completes
      // used for time period / pause view
      if (immediately) {
        updateGraphs(i);
      }
    }
    values = null;
  });

  // we can wait until all data is gathered, i.e.
  // the live refresh should happen synchronously
  if (!immediately) {
    for (var i=0; i<graphs.length; i++) {
      updateGraphs(i);
    }
  }
}

// retrieve dashboard list
function getDashboards(cb) {
  $.ajax({
    dataType: 'json',
    error: function(xhr, textStatus, errorThrown) { console.log(errorThrown); },
    url: '/'
  }).done(function(d) {
    cb(d.dashboards);
  });
}

// retrieve the data from Graphite
function getData(cb) {
  var myDatum = [];
  $.ajax({
    beforeSend: function(xhr) {
      if (auth.length > 0) {
        var bytes = Crypto.charenc.Binary.stringToBytes(auth);
        var base64 = Crypto.util.bytesToBase64(bytes);
        xhr.setRequestHeader("Authorization", "Basic " + base64);
      }
    },
    dataType: 'json',
    error: function(xhr, textStatus, errorThrown) { console.log(errorThrown); },
    url: myUrl
  }).done(function(d) {
    if (d.length > 0) {
      for (var i=0; i<d.length; i++) {
        myDatum[i] = [];
        myDatum[i][0] = { x: d[i].datapoints[0][1], y: d[i].datapoints[0][0] };
        for (var j=0; j<d[i].datapoints.length; j++) {
          myDatum[i][j] = { x: d[i].datapoints[j][1], y: d[i].datapoints[j][0] };
        }
      }
    }
    cb(myDatum);
  });
}

// perform the actual graph object and
// overlay name and number updates
function updateGraphs(i) {
  // update our graph
  graphs[i].update();
  if (datum[i][datum[i].length - 1] !== undefined) {
    var lastValue = datum[i][datum[i].length - 1].y;
    var lastValueDisplay;
    if ((typeof lastValue == 'number') && lastValue < 2.0) {
      lastValueDisplay = Math.round(lastValue*1000)/1000;
    } else {
      lastValueDisplay = parseInt(lastValue);
    }
    if (realMetrics[i].description) {
      $('.description' + i).html('Note:

' + descriptions[i]);
    }
    $('.overlay-name' + i).text(aliases[i]);
    $('.overlay-number' + i).text(lastValueDisplay);
    if (realMetrics[i].unit) {
      $('.overlay-number' + i).append('' + realMetrics[i].unit + '');
    }
  } else {
    $('.overlay-name' + i).text(aliases[i]);
    $('.overlay-number' + i).html('NF');
  }
}

// add our containers
function buildContainers() {
  var falseTargets = 0;
  for (var i=0; i<metrics.length; i++) {
    if (metrics[i].target === false) {
      $('.main').append('

');
      falseTargets++;
    } else {
      var j = i - falseTargets;
      $('.main').append(
        '
' +
        '' +
        '

' +
        '

' +
        '
'
      );
    }
  }
}

// filter out false targets
gatherRealMetrics();

// build our div containers
buildContainers();

// build our graph objects
constructGraphs();

// build our url
constructUrl(period);

// set our theme
var myTheme = (typeof theme == 'undefined') ? 'default' : theme;
if (myTheme === "dark") { enableNightMode(); }

// hide our toolbar if necessary
var toolbar = (typeof toolbar == 'undefined') ? true : toolbar;
if (!toolbar) { $('div.toolbar').css('display', 'none'); }

// initial load screen
for (var i=0; i<graphs.length; i++) {
  if (realMetrics[i].target === false) {
    //continue;
  } else if (myTheme === "dark") {
    $('.overlay-number' + i).html('');
  } else {
    $('.overlay-number' + i).html('');
  }
}
refreshData("now");

// define our refresh and start interval
var refreshInterval = (typeof refresh == 'undefined') ? 2000 : refresh;
var refreshId = setInterval(refreshData, refreshInterval);

// set our "live" interval hint
$('.toolbar ul li.timepanel a.play').text(period + 'min');

// populate and render our navigation list
$('.title').on('hover', 'span', function() {
  getDashboards(function(list) {
    $('.title span').html('<select><option value="/">welcome</option></select>');
    for (var i in list) {
      if (list[i] === window.location.pathname.replace(/^\//, '')) {
        $('.title select').append('<option selected="selected">' + list[i] + '</option>');
      } else {
        $('.title select').append('<option>' + list[i] + '</option>');
      }
    }
    $('.title span select').focus();
  });
});

// display description
$(document).on('mouseenter', 'div.graph', function() {
  if ($(this).find('span.description').text().length > 0) {
    $(this).find('span.description').css('visibility', 'visible');
  }
});

// hide description
$(document).on('mouseleave', 'div.graph', function() {
  $(this).find('span.description').css('visibility', 'hidden');
});

// clear navigation list on focusout
$('.title span').on('focusout', 'select', function() {
  $('.title span').html(window.location.pathname.replace(/^\//, ''));
});

// navigate to selection
$('.title span').on('change', 'select', function() {
  window.location.pathname = '/' + $(this).val();
});

// activate night mode
function enableNightMode() {
  $('body').addClass('night');
  $('div.title h1').addClass('night');
  $('div.graph svg').css('opacity', '0.8');
  $('span.description').addClass('night');
  $('div.overlay-name').addClass('night');
  $('div.overlay-number').addClass('night');
  $('div.toolbar ul li.timepanel').addClass('night');
}

// deactivate night mode
function disableNightMode() {
  $('body').removeClass('night');
  $('div.title h1').removeClass('night');
  $('div.graph svg').css('opacity', '1.0');
  $('span.description').removeClass('night');
  $('div.overlay-name').removeClass('night');
  $('div.overlay-number').removeClass('night');
  $('div.toolbar ul li.timepanel').removeClass('night');
}

// activate night mode by click
$('li.toggle-night').on('click', 'a', function() {
  if ($('body').hasClass('night')) {
    disableNightMode();
  } else {
    enableNightMode();
  }
});

// toggle number display
$('li.toggle-nonum').on('click', 'a', function() { $('div.overlay-number').toggleClass('nonum'); });

// time panel, pause live feed and show range
$('.toolbar ul li.timepanel').on('click', 'a.range', function() {
  var period = $(this).attr("title");
  for (var i=0; i<realMetrics.length; i++) {
    constructUrl(period);
  }
  if (! $('.toolbar ul li.timepanel a.play').hasClass('pause')) {
    $('.toolbar ul li.timepanel a.play').addClass('pause');
  }
  $('.toolbar ul li.timepanel a.play').text('paused');
  $(this).parent('li').parent('ul').find('li').removeClass('selected');
  $(this).parent('li').addClass('selected');
  refreshData("now");
  clearInterval(refreshId);
});

// time panel, resume live feed
$('.toolbar ul li.timepanel').on('click', 'a.play', function() {
  for (var i=0; i<realMetrics.length; i++) {
    constructUrl(5);
  }
  $(this).parent('li').parent('ul').find('li').removeClass('selected');
  $(this).parent('li').addClass('selected');
  $(this).removeClass('pause');
  $('.toolbar ul li.timepanel a.play').text(period + 'min');
  refreshData("now");
  // explicitly clear the old Interval in case
  // someone "doubles up" on the live play button
  clearInterval(refreshId);
  // remove and recreate the original graphs[]
  // helps clear out any rendering artifacts
  $('.graph svg').remove();
  constructGraphs();
  // reapply our style settings if night mode is active
  if ($('body').hasClass('night')) { enableNightMode(); }
  // restart our refresh interval
  refreshId = setInterval(refreshData, refreshInterval);
});

<|endoftext|>


<commit_before>"use strict";

var _ = require("underscore");
var util = require("substance-util");
var html = util.html;
var NodeView = require("../node").View;
var TextView = require("../text").View;
var $$ = require("substance-application").$$;
var articleUtil = require("../../article_util");

// Lens.Cover.View
// ==========================================================================

var CoverView = function(node, viewFactory) {
  NodeView.call(this, node, viewFactory);

  this.$el.attr({id: node.id});
  this.$el.addClass("content-node cover");
};

CoverView.Prototype = function() {

  // Render it
  // --------
  //
  // .content
  //   video
  //     source
  //   .title
  //   .caption
  //   .doi

  this.render = function() {
    NodeView.prototype.render.call(this);

    var node = this.node;
    var pubInfo = this.node.document.get('publication_info');

    // Intro + Send feedback for HighWire
    // --------------
    //
    // TODO: this should be refactored and live in some configuration object

    if (pubInfo.provider === "HighWire") {
      var introEl = $$('.intro.container', {
        children: [
          $$('.intro-text', {
            html: '  Lens provides a novel way of looking at research on the web.'
          }),
          $$('a.send-feedback', {href: "mailto:lens-feedback@highwire.org?subject=Lens%20Feedback", text: "Send feedback"})
        ]
      });

      this.content.appendChild(introEl);
    }

    if (node.breadcrumbs && node.breadcrumbs.length > 0) {
      var breadcrumbs = $$('.breadcrumbs', {
        children: _.map(node.breadcrumbs, function(bc) {
          var html;
          if (bc.image) {
            html = '';
          } else {
            html = bc.name;
          }
          return $$('a', {href: bc.url, html: html})
        })
      });
      this.content.appendChild(breadcrumbs);
    }

    if (pubInfo) {
      var pubDate = pubInfo.published_on;
      if (pubDate) {
        this.content.appendChild($$('.published-on', {
          text: articleUtil.formatDate(pubDate)
        }));
      }
    }

    // Title View
    // --------------
    //

    // HACK: we need to update to a newer substance version to be able to delegate
    // to sub-views.
    var titleView = new TextView(this.node, {
      path: ['document', 'title'],
      classes: 'title'
    });
    this.content.appendChild(titleView.render().el);

    // Render Authors
    // --------------
    //

    var authors = $$('.authors', {
      children: _.map(node.getAuthors(), function(authorPara) {
        var paraView = this.viewFactory.createView(authorPara);
        var paraEl = paraView.render().el;
        this.content.appendChild(paraEl);
        return paraEl;
      }, this)
    });

    authors.appendChild($$('.content-node.text.plain', {
      children: [
        $$('.content', {text: this.node.document.on_behalf_of})
      ]
    }));

    this.content.appendChild(authors);

    // Render Links
    // --------------
    //

    if (pubInfo && pubInfo.links.length > 0) {
      var linksEl = $$('.links');
      _.each(pubInfo.links, function(link) {
        if (link.type === "json" && link.url === "") {
          // Make downloadable JSON
          var json = JSON.stringify(this.node.document.toJSON(), null, '  ');
          var bb = new Blob([json], {type: "application/json"});

          linksEl.appendChild($$('a.json', {
            href: window.URL ? window.URL.createObjectURL(bb) : "#",
            html: ' '+link.name,
            target: '_blank'
          }));

        } else {
          linksEl.appendChild($$('a.'+link.type, {
            href: link.url,
            html: ' '+ link.name,
            target: '_blank'
          }));
        }
      }, this);

      this.content.appendChild(linksEl);
    }

    if (pubInfo) {
      var doi = pubInfo.doi;
      if (doi) {
        this.content.appendChild($$('.doi', {
          html: 'DOI: '+doi+''
        }));
      }
    }

    return this;
  }
};

CoverView.Prototype.prototype = NodeView.prototype;
CoverView.prototype = new CoverView.Prototype();

module.exports = CoverView;
<commit_msg>Remove link to elife and link to HW feedback form.<commit_after>"use strict";

var _ = require("underscore");
var util = require("substance-util");
var html = util.html;
var NodeView = require("../node").View;
var TextView = require("../text").View;
var $$ = require("substance-application").$$;
var articleUtil = require("../../article_util");

// Lens.Cover.View
// ==========================================================================

var CoverView = function(node, viewFactory) {
  NodeView.call(this, node, viewFactory);

  this.$el.attr({id: node.id});
  this.$el.addClass("content-node cover");
};

CoverView.Prototype = function() {

  // Render it
  // --------
  //
  // .content
  //   video
  //     source
  //   .title
  //   .caption
  //   .doi

  this.render = function() {
    NodeView.prototype.render.call(this);

    var node = this.node;
    var pubInfo = this.node.document.get('publication_info');

    // Intro + Send feedback for HighWire
    // --------------
    //
    // TODO: this should be refactored and live in some configuration object

    if (pubInfo.provider === "HighWire") {
      var introEl = $$('.intro.container', {
        children: [
          $$('.intro-text', {
            html: '  Lens provides a novel way of looking at research on the web.'
          }),
          $$('a.send-feedback', {href: "http://home.highwire.org/feedback/lens-feedback", text: "Send feedback", target: "_blank" })
        ]
      });

      this.content.appendChild(introEl);
    }

    if (node.breadcrumbs && node.breadcrumbs.length > 0) {
      var breadcrumbs = $$('.breadcrumbs', {
        children: _.map(node.breadcrumbs, function(bc) {
          var html;
          if (bc.image) {
            html = '';
          } else {
            html = bc.name;
          }
          return $$('a', {href: bc.url, html: html})
        })
      });
      this.content.appendChild(breadcrumbs);
    }

    if (pubInfo) {
      var pubDate = pubInfo.published_on;
      if (pubDate) {
        this.content.appendChild($$('.published-on', {
          text: articleUtil.formatDate(pubDate)
        }));
      }
    }

    // Title View
    // --------------
    //

    // HACK: we need to update to a newer substance version to be able to delegate
    // to sub-views.
    var titleView = new TextView(this.node, {
      path: ['document', 'title'],
      classes: 'title'
    });
    this.content.appendChild(titleView.render().el);

    // Render Authors
    // --------------
    //

    var authors = $$('.authors', {
      children: _.map(node.getAuthors(), function(authorPara) {
        var paraView = this.viewFactory.createView(authorPara);
        var paraEl = paraView.render().el;
        this.content.appendChild(paraEl);
        return paraEl;
      }, this)
    });

    authors.appendChild($$('.content-node.text.plain', {
      children: [
        $$('.content', {text: this.node.document.on_behalf_of})
      ]
    }));

    this.content.appendChild(authors);

    // Render Links
    // --------------
    //

    if (pubInfo && pubInfo.links.length > 0) {
      var linksEl = $$('.links');
      _.each(pubInfo.links, function(link) {
        if (link.type === "json" && link.url === "") {
          // Make downloadable JSON
          var json = JSON.stringify(this.node.document.toJSON(), null, '  ');
          var bb = new Blob([json], {type: "application/json"});

          linksEl.appendChild($$('a.json', {
            href: window.URL ? window.URL.createObjectURL(bb) : "#",
            html: ' '+link.name,
            target: '_blank'
          }));

        } else {
          linksEl.appendChild($$('a.'+link.type, {
            href: link.url,
            html: ' '+ link.name,
            target: '_blank'
          }));
        }
      }, this);

      this.content.appendChild(linksEl);
    }

    if (pubInfo) {
      var doi = pubInfo.doi;
      if (doi) {
        this.content.appendChild($$('.doi', {
          html: 'DOI: '+doi+''
        }));
      }
    }

    return this;
  }
};

CoverView.Prototype.prototype = NodeView.prototype;
CoverView.prototype = new CoverView.Prototype();

module.exports = CoverView;
<|endoftext|>


<commit_before>const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;

var mainWindow = null;

app.on('window-all-closed', function() {
  if (process.platform != 'darwin')
    app.quit();
});

app.on('ready', function() {
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});
<commit_msg>Update electron sample to make it work on electron v5.<commit_after>const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;

var mainWindow = null;

app.on('window-all-closed', function() {
  if (process.platform != 'darwin')
    app.quit();
});

app.on('ready', function() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: { nodeIntegration: true }
  });
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth.email',
  name: 'EmailDocService',
  documentation: 'Sends an email with an html doc',

  implements: [
    'foam.nanos.auth.email.EmailDocInterface'
  ],

  imports: [
    'appConfig',
    'email',
    'localUserDAO',
    'tokenDAO',
    'htmlDocDAO'
  ],

  javaImports: [
    'foam.dao.DAO',
    'foam.dao.ArraySink',
    'foam.dao.Sink',
    'foam.mlang.MLang',
    'foam.nanos.app.AppConfig',
    'foam.nanos.auth.token.Token',
    'foam.nanos.auth.User',
    'foam.nanos.auth.HtmlDoc',
    'foam.nanos.notification.email.EmailMessage',
    'foam.nanos.notification.email.EmailService',
    'foam.util.Password',
    'foam.util.SafetyUtil',
    'java.util.Calendar',
    'java.util.HashMap',
    'java.util.List',
    'java.util.UUID'
  ],

  methods: [
    {
      name: 'emailDoc',
      javaCode:
      `
try{
  DAO htmlDocDAO = (DAO) getHtmlDocDAO();
  htmlDocDAO = htmlDocDAO.where(MLang.EQ(HtmlDoc.NAME, docName));
  ArraySink listSink = (ArraySink) htmlDocDAO.orderBy(new foam.mlang.order.Desc(HtmlDoc.ID)).limit(1).select(new ArraySink());
  HtmlDoc doc = (HtmlDoc) listSink.getArray().get(0);

  EmailService email = (EmailService) getEmail();
  EmailMessage message = new EmailMessage();
  message.setTo(new String[] { user.getEmail() });

  HashMap<String, Object> args = new HashMap<>();
  args.put("doc", doc.getBody());

  email.sendEmailFromTemplate(user, message, "docEmail", args);
  return true;
}catch(Exception e){
  e.printStackTrace();
}
return false;
       `
    },]
});
<commit_msg>added logger to EmailDocService<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth.email',
  name: 'EmailDocService',
  documentation: 'Sends an email with an html doc',

  implements: [
    'foam.nanos.auth.email.EmailDocInterface'
  ],

  imports: [
    'appConfig',
    'email',
    'localUserDAO',
    'tokenDAO',
    'htmlDocDAO',
    'logger'
  ],

  javaImports: [
    'foam.dao.DAO',
    'foam.dao.ArraySink',
    'foam.dao.Sink',
    'foam.mlang.MLang',
    'foam.nanos.app.AppConfig',
    'foam.nanos.auth.token.Token',
    'foam.nanos.auth.User',
    'foam.nanos.auth.HtmlDoc',
    'foam.nanos.logger.Logger',
    'foam.nanos.notification.email.EmailMessage',
    'foam.nanos.notification.email.EmailService',
    'foam.util.Password',
    'foam.util.SafetyUtil',
    'java.util.Calendar',
    'java.util.HashMap',
    'java.util.List',
    'java.util.UUID'
  ],

  methods: [
    {
      name: 'emailDoc',
      javaCode:
      `
      try{
        DAO htmlDocDAO = (DAO) getHtmlDocDAO();
        htmlDocDAO = htmlDocDAO.where(MLang.EQ(HtmlDoc.NAME, docName));
        ArraySink listSink = (ArraySink) htmlDocDAO.orderBy(new foam.mlang.order.Desc(HtmlDoc.ID)).limit(1).select(new ArraySink());
        HtmlDoc doc = (HtmlDoc) listSink.getArray().get(0);

        EmailService email = (EmailService) getEmail();
        EmailMessage message = new EmailMessage();
        message.setTo(new String[] { user.getEmail() });

        HashMap<String, Object> args = new HashMap<>();
        args.put("doc", doc.getBody());

        email.sendEmailFromTemplate(user, message, "docEmail", args);
        return true;
      }catch(Throwable t){
        ((Logger) getLogger()).error("Error retrieving Terms and Conditions.", t);
      }
      return false;

       `
    },]
});
<|endoftext|>


<commit_before><commit_msg>missed an icon changing attachment<commit_after>const DrawCard = require('../../../drawcard.js');

class SyriosTraining extends DrawCard {
    attach(player, card) {
        card.setIcon('military');
    }

    leavesPlay() {
        this.parent.setIcon('military');
    }
}

SyriosTraining.code = '01037';

module.exports = SyriosTraining;
<|endoftext|>


<commit_before>(function (factory) {
	// Packaging/modules magic dance
	var L;
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['leaflet'], factory);
	} else if (typeof module !== 'undefined') {
		// Node/CommonJS
		L = require('leaflet');
		module.exports = factory(L);
	} else {
		// Browser globals
		if (typeof window.L === 'undefined')
			throw 'Leaflet must be loaded first';
		factory(window.L);
	}
}(function (L) {
	'use strict';
	L.Control.Geocoder = L.Control.extend({
		options: {
			showResultIcons: false,
			collapsed: true,
			expand: 'click',
			position: 'topright',
			placeholder: 'Search...',
			errorMessage: 'Nothing found.'
		},

		_callbackId: 0,

		initialize: function (options) {
			L.Util.setOptions(this, options);
			if (!this.options.geocoder) {
				this.options.geocoder = new L.Control.Geocoder.Nominatim();
			}
		},

		onAdd: function (map) {
			var className = 'leaflet-control-geocoder',
			    container = L.DomUtil.create('div', className),
			    form = this._form = L.DomUtil.create('form', className + '-form', container),
			    input,
			    icon;

			this._map = map;
			input = this._input = document.createElement('input');
			input.type = 'text';

			L.DomEvent.addListener(input, 'keydown', this._keydown, this);
			//L.DomEvent.addListener(input, 'onpaste', this._clearResults, this);
			//L.DomEvent.addListener(input, 'oninput', this._clearResults, this);

			icon = L.DomUtil.create('div', 'leaflet-control-geocoder-icon');
			container.appendChild(icon);

			this._errorElement = document.createElement('div');
			this._errorElement.className = className + '-form-no-error';
			this._errorElement.innerHTML = this.options.errorMessage;

			this._alts = L.DomUtil.create('ul', className + '-alternatives leaflet-control-geocoder-alternatives-minimized');

			form.appendChild(input);
			form.appendChild(this._errorElement);
			container.appendChild(this._alts);

			L.DomEvent.addListener(form, 'submit', this._geocode, this);

			if (this.options.collapsed) {
				if (this.options.expand === 'click') {
					L.DomEvent.addListener(icon, 'click', function(e) {
						// TODO: touch
						if (e.button === 0 && e.detail === 1) {
							this._toggle();
						}
					}, this);
				} else {
					L.DomEvent.addListener(icon, 'mouseover', this._expand, this);
					L.DomEvent.addListener(icon, 'mouseout', this._collapse, this);
					this._map.on('movestart', this._collapse, this);
				}
			} else {
				this._expand();
			}

			L.DomEvent.disableClickPropagation(container);

			return container;
		},

		_geocodeResult: function (results) {
			L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-throbber');
			if (results.length === 1) {
				this._geocodeResultSelected(results[0]);
			} else if (results.length > 0) {
				this._alts.innerHTML = '';
				this._results = results;
				L.DomUtil.removeClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
				for (var i = 0; i < results.length; i++) {
					this._alts.appendChild(this._createAlt(results[i], i));
				}
			} else {
				L.DomUtil.addClass(this._errorElement, 'leaflet-control-geocoder-error');
			}
		},

		markGeocode: function(result) {
			this._map.fitBounds(result.bbox);

			if (this._geocodeMarker) {
				this._map.removeLayer(this._geocodeMarker);
			}

			this._geocodeMarker = new L.Marker(result.center)
				.bindPopup(result.name)
				.addTo(this._map)
				.openPopup();

			return this;
		},

		_geocode: function(event) {
			L.DomEvent.preventDefault(event);

			L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-throbber');
			this._clearResults();
			this.options.geocoder.geocode(this._input.value, this._geocodeResult, this);

			return false;
		},

		_geocodeResultSelected: function(result) {
			if (this.options.collapsed) {
				this._collapse();
			}
			this.markGeocode(result);
		},

		_toggle: function() {
			if (this._container.className.indexOf('leaflet-control-geocoder-expanded') >= 0) {
				this._collapse();
			} else {
				this._expand();
			}
		},

		_expand: function () {
			L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-expanded');
			this._input.select();
		},

		_collapse: function () {
			this._container.className = this._container.className.replace(' leaflet-control-geocoder-expanded', '');
			L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
		},

		_clearResults: function () {
			L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
			this._selection = null;
			L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error');
		},

		_createAlt: function(result, index) {
			var li = document.createElement('li');
			li.innerHTML = '' +
				(this.options.showResultIcons && result.icon ?
					'' :
					'') +
				result.name + '';
			L.DomEvent.addListener(li, 'click', function clickHandler() {
				this._geocodeResultSelected(result);
			}, this);

			return li;
		},

		_keydown: function(e) {
			var _this = this,
				select = function select(dir) {
					if (_this._selection) {
						L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected');
						_this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling'];
					}
					if (!_this._selection) {
						_this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild'];
					}

					if (_this._selection) {
						L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected');
					}
				};

			switch (e.keyCode) {
			// Up
			case 38:
				select(-1);
				L.DomEvent.preventDefault(e);
				break;
			// Up
			case 40:
				select(1);
				L.DomEvent.preventDefault(e);
				break;
			// Enter
			case 13:
				if (this._selection) {
					var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10);
					this._geocodeResultSelected(this._results[index]);
					this._clearResults();
					L.DomEvent.preventDefault(e);
				}
			}
			return true;
		}
	});

	L.Control.geocoder = function(id, options) {
		return new L.Control.Geocoder(id, options);
	};

	L.Control.Geocoder.callbackId = 0;
	L.Control.Geocoder.jsonp = function(url, params, callback, context, jsonpParam) {
		var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++);
		params[jsonpParam || 'callback'] = callbackId;
		window[callbackId] = L.Util.bind(callback, context);
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = url + L.Util.getParamString(params);
		script.id = callbackId;
		document.getElementsByTagName('head')[0].appendChild(script);
	};

	L.Control.Geocoder.Nominatim = L.Class.extend({
		options: {
			serviceUrl: 'http://nominatim.openstreetmap.org/'
		},

		initialize: function(options) {
			L.Util.setOptions(this, options);
		},

		geocode: function(query, cb, context) {
			L.Control.Geocoder.jsonp(this.options.serviceUrl + 'search/', {
				q: query,
				limit: 5,
				format: 'json'
			}, function(data) {
				var results = [];
				for (var i = data.length - 1; i >= 0; i--) {
					var bbox = data[i].boundingbox;
					for (var j = 0; j < 4; j++) bbox[j] = parseFloat(bbox[j]);
					results[i] = {
						icon: data[i].icon,
						name: data[i].display_name,
						bbox: L.latLngBounds([bbox[0], bbox[2]], [bbox[1], bbox[3]]),
						center: L.latLng((bbox[0] + bbox[1]) / 2, (bbox[2] + bbox[3]) / 2)
					};
				}
				cb.call(context, results);
			}, this, 'json_callback');
		},

		reverse: function(location, scale, cb, context) {
			L.Control.Geocoder.jsonp(this.options.serviceUrl + 'reverse/', {
				lat: location.lat,
				lon: location.lng,
				zoom: Math.round(Math.log(scale / 256) / Math.log(2)),
				format: 'json'
			}, function(data) {
				var loc = L.latLng(data.lat, data.lon);
				cb.call(context, [{
					name: data.display_name,
					center: loc,
					bounds: L.latLngBounds(loc, loc)
				}]);
			}, this, 'json_callback');
		}
	});

	L.Control.Geocoder.nominatim = function(options) {
		return new L.Control.Geocoder.Nominatim(options);
	};

	L.Control.Geocoder.Bing = L.Class.extend({
		initialize: function(key) {
			this.key = key;
		},

		geocode : function (query, cb, context) {
			L.Control.Geocoder.jsonp('http://dev.virtualearth.net/REST/v1/Locations', {
				query: query,
				key : this.key
			}, function(data) {
				var results = [];
				for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
					var resource = data.resourceSets[0].resources[i],
						bbox = resource.bbox;
					results[i] = {
						name: resource.name,
						bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
						center: L.latLng(resource.point.coordinates)
					};
				}
				cb.call(context, results);
			}, this, 'jsonp');
		},

		reverse: function(location, scale, cb, context) {
			L.Control.Geocoder.jsonp('http://dev.virtualearth.net/REST/v1/Locations/' + location.lat + ',' + location.lng, {
				key : this.key
			}, function(data) {
				var results = [];
				for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
					var resource = data.resourceSets[0].resources[i],
						bbox = resource.bbox;
					results[i] = {
						name: resource.name,
						bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
						center: L.latLng(resource.point.coordinates)
					};
				}
				cb.call(context, results);
			}, this, 'jsonp');
		}
	});

	L.Control.Geocoder.bing = function(key) {
		return new L.Control.Geocoder.Bing(key);
	};

	L.Control.Geocoder.RaveGeo = L.Class.extend({
		options: {
			querySuffix: '',
			deepSearch: true,
			wordBased: false
		},

		jsonp: function(params, callback, context) {
			var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++),
				paramParts = [];
			params.prepend = callbackId + '(';
			params.append = ')';
			for (var p in params) {
				paramParts.push(p + '=' + escape(params[p]));
			}

			window[callbackId] = L.Util.bind(callback, context);
			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = this._serviceUrl + '?' + paramParts.join('&');
			script.id = callbackId;
			document.getElementsByTagName('head')[0].appendChild(script);
		},

		initialize: function(serviceUrl, scheme, options) {
			L.Util.setOptions(this, options);

			this._serviceUrl = serviceUrl;
			this._scheme = scheme;
		},

		geocode: function(query, cb, context) {
			L.Control.Geocoder.jsonp(this._serviceUrl, {
				address: query + this.options.querySuffix,
				scheme: this._scheme,
				outputFormat: 'jsonp',
				deepSearch: this.options.deepSearch,
				wordBased: this.options.wordBased
			}, function(data) {
				var results = [];
				for (var i = data.length - 1; i >= 0; i--) {
					var r = data[i],
						c = L.latLng(r.y, r.x);
					results[i] = {
						name: r.address,
						bbox: L.latLngBounds([c]),
						center: c
					};
				}
				cb.call(context, results);
			}, this);
		}
	});

	L.Control.Geocoder.raveGeo = function(serviceUrl, scheme, options) {
		return new L.Control.Geocoder.RaveGeo(serviceUrl, scheme, options);
	};

	return L.Control.Geocoder;
}));
<commit_msg>Use L.DomUtil<commit_after>(function (factory) {
	// Packaging/modules magic dance
	var L;
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['leaflet'], factory);
	} else if (typeof module !== 'undefined') {
		// Node/CommonJS
		L = require('leaflet');
		module.exports = factory(L);
	} else {
		// Browser globals
		if (typeof window.L === 'undefined')
			throw 'Leaflet must be loaded first';
		factory(window.L);
	}
}(function (L) {
	'use strict';
	L.Control.Geocoder = L.Control.extend({
		options: {
			showResultIcons: false,
			collapsed: true,
			expand: 'click',
			position: 'topright',
			placeholder: 'Search...',
			errorMessage: 'Nothing found.'
		},

		_callbackId: 0,

		initialize: function (options) {
			L.Util.setOptions(this, options);
			if (!this.options.geocoder) {
				this.options.geocoder = new L.Control.Geocoder.Nominatim();
			}
		},

		onAdd: function (map) {
			var className = 'leaflet-control-geocoder',
			    container = L.DomUtil.create('div', className),
			    form = this._form = L.DomUtil.create('form', className + '-form', container),
			    input,
			    icon;

			this._map = map;
			input = this._input = L.DomUtil.create('input');
			input.type = 'text';

			L.DomEvent.addListener(input, 'keydown', this._keydown, this);
			//L.DomEvent.addListener(input, 'onpaste', this._clearResults, this);
			//L.DomEvent.addListener(input, 'oninput', this._clearResults, this);

			icon = L.DomUtil.create('div', 'leaflet-control-geocoder-icon');
			container.appendChild(icon);

			this._errorElement = document.createElement('div');
			this._errorElement.className = className + '-form-no-error';
			this._errorElement.innerHTML = this.options.errorMessage;

			this._alts = L.DomUtil.create('ul', className + '-alternatives leaflet-control-geocoder-alternatives-minimized');

			form.appendChild(input);
			form.appendChild(this._errorElement);
			container.appendChild(this._alts);

			L.DomEvent.addListener(form, 'submit', this._geocode, this);

			if (this.options.collapsed) {
				if (this.options.expand === 'click') {
					L.DomEvent.addListener(icon, 'click', function(e) {
						// TODO: touch
						if (e.button === 0 && e.detail === 1) {
							this._toggle();
						}
					}, this);
				} else {
					L.DomEvent.addListener(icon, 'mouseover', this._expand, this);
					L.DomEvent.addListener(icon, 'mouseout', this._collapse, this);
					this._map.on('movestart', this._collapse, this);
				}
			} else {
				this._expand();
			}

			L.DomEvent.disableClickPropagation(container);

			return container;
		},

		_geocodeResult: function (results) {
			L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-throbber');
			if (results.length === 1) {
				this._geocodeResultSelected(results[0]);
			} else if (results.length > 0) {
				this._alts.innerHTML = '';
				this._results = results;
				L.DomUtil.removeClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
				for (var i = 0; i < results.length; i++) {
					this._alts.appendChild(this._createAlt(results[i], i));
				}
			} else {
				L.DomUtil.addClass(this._errorElement, 'leaflet-control-geocoder-error');
			}
		},

		markGeocode: function(result) {
			this._map.fitBounds(result.bbox);

			if (this._geocodeMarker) {
				this._map.removeLayer(this._geocodeMarker);
			}

			this._geocodeMarker = new L.Marker(result.center)
				.bindPopup(result.name)
				.addTo(this._map)
				.openPopup();

			return this;
		},

		_geocode: function(event) {
			L.DomEvent.preventDefault(event);

			L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-throbber');
			this._clearResults();
			this.options.geocoder.geocode(this._input.value, this._geocodeResult, this);

			return false;
		},

		_geocodeResultSelected: function(result) {
			if (this.options.collapsed) {
				this._collapse();
			}
			this.markGeocode(result);
		},

		_toggle: function() {
			if (this._container.className.indexOf('leaflet-control-geocoder-expanded') >= 0) {
				this._collapse();
			} else {
				this._expand();
			}
		},

		_expand: function () {
			L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-expanded');
			this._input.select();
		},

		_collapse: function () {
			this._container.className = this._container.className.replace(' leaflet-control-geocoder-expanded', '');
			L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
		},

		_clearResults: function () {
			L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
			this._selection = null;
			L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error');
		},

		_createAlt: function(result, index) {
			var li = document.createElement('li');
			li.innerHTML = '' +
				(this.options.showResultIcons && result.icon ?
					'' :
					'') +
				result.name + '';
			L.DomEvent.addListener(li, 'click', function clickHandler() {
				this._geocodeResultSelected(result);
			}, this);

			return li;
		},

		_keydown: function(e) {
			var _this = this,
				select = function select(dir) {
					if (_this._selection) {
						L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected');
						_this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling'];
					}
					if (!_this._selection) {
						_this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild'];
					}

					if (_this._selection) {
						L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected');
					}
				};

			switch (e.keyCode) {
			// Up
			case 38:
				select(-1);
				L.DomEvent.preventDefault(e);
				break;
			// Up
			case 40:
				select(1);
				L.DomEvent.preventDefault(e);
				break;
			// Enter
			case 13:
				if (this._selection) {
					var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10);
					this._geocodeResultSelected(this._results[index]);
					this._clearResults();
					L.DomEvent.preventDefault(e);
				}
			}
			return true;
		}
	});

	L.Control.geocoder = function(id, options) {
		return new L.Control.Geocoder(id, options);
	};

	L.Control.Geocoder.callbackId = 0;
	L.Control.Geocoder.jsonp = function(url, params, callback, context, jsonpParam) {
		var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++);
		params[jsonpParam || 'callback'] = callbackId;
		window[callbackId] = L.Util.bind(callback, context);
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = url + L.Util.getParamString(params);
		script.id = callbackId;
		document.getElementsByTagName('head')[0].appendChild(script);
	};

	L.Control.Geocoder.Nominatim = L.Class.extend({
		options: {
			serviceUrl: 'http://nominatim.openstreetmap.org/'
		},

		initialize: function(options) {
			L.Util.setOptions(this, options);
		},

		geocode: function(query, cb, context) {
			L.Control.Geocoder.jsonp(this.options.serviceUrl + 'search/', {
				q: query,
				limit: 5,
				format: 'json'
			}, function(data) {
				var results = [];
				for (var i = data.length - 1; i >= 0; i--) {
					var bbox = data[i].boundingbox;
					for (var j = 0; j < 4; j++) bbox[j] = parseFloat(bbox[j]);
					results[i] = {
						icon: data[i].icon,
						name: data[i].display_name,
						bbox: L.latLngBounds([bbox[0], bbox[2]], [bbox[1], bbox[3]]),
						center: L.latLng((bbox[0] + bbox[1]) / 2, (bbox[2] + bbox[3]) / 2)
					};
				}
				cb.call(context, results);
			}, this, 'json_callback');
		},

		reverse: function(location, scale, cb, context) {
			L.Control.Geocoder.jsonp(this.options.serviceUrl + 'reverse/', {
				lat: location.lat,
				lon: location.lng,
				zoom: Math.round(Math.log(scale / 256) / Math.log(2)),
				format: 'json'
			}, function(data) {
				var loc = L.latLng(data.lat, data.lon);
				cb.call(context, [{
					name: data.display_name,
					center: loc,
					bounds: L.latLngBounds(loc, loc)
				}]);
			}, this, 'json_callback');
		}
	});

	L.Control.Geocoder.nominatim = function(options) {
		return new L.Control.Geocoder.Nominatim(options);
	};

	L.Control.Geocoder.Bing = L.Class.extend({
		initialize: function(key) {
			this.key = key;
		},

		geocode : function (query, cb, context) {
			L.Control.Geocoder.jsonp('http://dev.virtualearth.net/REST/v1/Locations', {
				query: query,
				key : this.key
			}, function(data) {
				var results = [];
				for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
					var resource = data.resourceSets[0].resources[i],
						bbox = resource.bbox;
					results[i] = {
						name: resource.name,
						bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
						center: L.latLng(resource.point.coordinates)
					};
				}
				cb.call(context, results);
			}, this, 'jsonp');
		},

		reverse: function(location, scale, cb, context) {
			L.Control.Geocoder.jsonp('http://dev.virtualearth.net/REST/v1/Locations/' + location.lat + ',' + location.lng, {
				key : this.key
			}, function(data) {
				var results = [];
				for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
					var resource = data.resourceSets[0].resources[i],
						bbox = resource.bbox;
					results[i] = {
						name: resource.name,
						bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
						center: L.latLng(resource.point.coordinates)
					};
				}
				cb.call(context, results);
			}, this, 'jsonp');
		}
	});

	L.Control.Geocoder.bing = function(key) {
		return new L.Control.Geocoder.Bing(key);
	};

	L.Control.Geocoder.RaveGeo = L.Class.extend({
		options: {
			querySuffix: '',
			deepSearch: true,
			wordBased: false
		},

		jsonp: function(params, callback, context) {
			var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++),
				paramParts = [];
			params.prepend = callbackId + '(';
			params.append = ')';
			for (var p in params) {
				paramParts.push(p + '=' + escape(params[p]));
			}

			window[callbackId] = L.Util.bind(callback, context);
			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = this._serviceUrl + '?' + paramParts.join('&');
			script.id = callbackId;
			document.getElementsByTagName('head')[0].appendChild(script);
		},

		initialize: function(serviceUrl, scheme, options) {
			L.Util.setOptions(this, options);

			this._serviceUrl = serviceUrl;
			this._scheme = scheme;
		},

		geocode: function(query, cb, context) {
			L.Control.Geocoder.jsonp(this._serviceUrl, {
				address: query + this.options.querySuffix,
				scheme: this._scheme,
				outputFormat: 'jsonp',
				deepSearch: this.options.deepSearch,
				wordBased: this.options.wordBased
			}, function(data) {
				var results = [];
				for (var i = data.length - 1; i >= 0; i--) {
					var r = data[i],
						c = L.latLng(r.y, r.x);
					results[i] = {
						name: r.address,
						bbox: L.latLngBounds([c]),
						center: c
					};
				}
				cb.call(context, results);
			}, this);
		}
	});

	L.Control.Geocoder.raveGeo = function(serviceUrl, scheme, options) {
		return new L.Control.Geocoder.RaveGeo(serviceUrl, scheme, options);
	};

	return L.Control.Geocoder;
}));
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var config = require( './config.js' );

// VARIABLES //

var valid;
var test;

// MAIN //

// Create our test cases:
valid = [];

test = {
	'code': [
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

test = {
	'code': [
		'/**/',
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

test = {
	'code': [
		'// Beep boop.',
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

test = {
	'code': [
		'/* Beep boop. */',
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

// EXPORTS //

module.exports = valid;
<commit_msg>Add tests<commit_after>'use strict';

// MODULES //

var config = require( './config.js' );

// VARIABLES //

var valid;
var test;

// MAIN //

// Create our test cases:
valid = [];

test = {
	'code': [
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

test = {
	'code': [
		'/**/',
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

test = {
	'code': [
		'// Beep boop.',
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

test = {
	'code': [
		'/* Beep boop. */',
		'function fizzBuzz() {',
		'  // This is a single-line comment',
		'  var out;',
		'  var i;',
		'',
		'  for ( i = 1; i <= 100; i++ ) {',
		'    /*',
		'    * This is a multi-line comment...',
		'    */',
		'    out = ( i % 5 === 0 ) ? "Buzz" : ( i % 3 === 0 ) ? "Fizz" : i;',
		'    console.log( out );',
		'  }',
		'}'
	].join( '\n' ),
	'options': [
		{
			'config': config
		}
	]
};
valid.push( test );

// The following is only valid as the configuration provided:
test = {
	'code': [
		'/**',
		'* Beep boop.',
		'*',
		'* ## Beep',
		'*',
		'* ## Beep',
		'*/',
		'function beep() {',
		'    console.log( "boop" );',
		'}'
	].join( '\n' )
};
valid.push( test );

// EXPORTS //

module.exports = valid;
<|endoftext|>