<commit_before>require('./raf-polyfill')();

var Game = require('./game');

var Time = require('./time');

var Debugger = require('potion-debugger');

var StateManager = require('./state-manager');

/**
 * Main Engine class which calls the game methods
 * @constructor
 */
var Engine = function(container, methods) {
  var GameClass = this._subclassGame(container, methods);

  container.style.position = 'relative';

  var canvas = document.createElement('canvas');
  canvas.style.display = 'block';
  container.appendChild(canvas);

  this.game = new GameClass(canvas);
  this.game.debug = new Debugger(this.game);

  this._setDefaultStates();

  this.tickFunc = (function (self) { return function() { self.tick(); }; })(this);
  this.preloaderTickFunc = (function (self) { return function() { self._preloaderTick(); }; })(this);

  this.strayTime = 0;

  this._time = Time.now();

  this.game.assets.onload(function() {
    this.start();

    window.cancelAnimationFrame(this.preloaderId);
    window.requestAnimationFrame(this.tickFunc);
  }.bind(this));

  if (this.game.assets.isLoading) {
    this.preloaderId = window.requestAnimationFrame(this.preloaderTickFunc);
  }
};

/**
 * Add event listener for window events
 * @private
 */
Engine.prototype.addEvents = function() {
  var self = this;

  var game = self.game;
  window.addEventListener('blur', function() {
    self.game.input.resetKeys();
    self.game.blur();
  });

  window.addEventListener('focus', function() {
    self.game.input.resetKeys();
    self.game.focus();
  });
};

/**
 * Starts the game, adds events and run first frame
 * @private
 */
Engine.prototype.start = function() {
  if (this.game.config.addInputEvents) {
    this.addEvents();
  }
};

/**
 * Main tick function in game loop
 * @private
 */
Engine.prototype.tick = function() {
  window.requestAnimationFrame(this.tickFunc);

  var now = Time.now();
  var time = (now - this._time) / 1000;
  this._time = now;

  this.update(time);
  this.game.states.exitUpdate(time);
  this.render();
};

/**
 * Updates the game
 * @param {number} time - time in seconds since last frame
 * @private
 */
Engine.prototype.update = function(time) {
  if (time > this.game.config.maxStepTime) { time = this.game.config.maxStepTime; }

  if (this.game.config.fixedStep) {
    this.strayTime = this.strayTime + time;
    while (this.strayTime >= this.game.config.stepTime) {
      this.strayTime = this.strayTime - this.game.config.stepTime;
      this.game.states.update(this.game.config.stepTime);
    }
  } else {
    this.game.states.update(time);
  }
};

/**
 * Renders the game
 * @private
 */
Engine.prototype.render = function() {
  this.game.video.beginFrame();

  this.game.video.clear();

  this.game.states.render();

  this.game.video.endFrame();
};

/**
 * Main tick function in preloader loop
 * @private
 */
Engine.prototype._preloaderTick = function() {
  this.preloaderId = window.requestAnimationFrame(this.preloaderTickFunc);

  var now = Time.now();
  var time = (now - this._time) / 1000;
  this._time = now;

  if (this.game.config.showPreloader) {
    this.game.video.clear();
    this.game.preloading(time);
  }
};

Engine.prototype._setDefaultStates = function() {
  var states = new StateManager();
  states.add('app', this.game);
  states.add('debug', this.game.debug);

  states.protect('app');
  states.protect('debug');

  this.game.states = states;
};

Engine.prototype._subclassGame = function(container, methods) {
  var GameClass = function(container) {
    Game.call(this, container);
  };

  GameClass.prototype = Object.create(Game.prototype);

  for (var method in methods) {
    GameClass.prototype[method] = methods[method];
  }

  return GameClass;
};

module.exports = Engine;
<commit_msg>use debugger perf monitor for update and render<commit_after>require('./raf-polyfill')();

var Game = require('./game');

var Time = require('./time');

var Debugger = require('potion-debugger');

var StateManager = require('./state-manager');

/**
 * Main Engine class which calls the game methods
 * @constructor
 */
var Engine = function(container, methods) {
  var GameClass = this._subclassGame(container, methods);

  container.style.position = 'relative';

  var canvas = document.createElement('canvas');
  canvas.style.display = 'block';
  container.appendChild(canvas);

  this.game = new GameClass(canvas);
  this.game.debug = new Debugger(this.game);

  this._setDefaultStates();

  this.tickFunc = (function (self) { return function() { self.tick(); }; })(this);
  this.preloaderTickFunc = (function (self) { return function() { self._preloaderTick(); }; })(this);

  this.strayTime = 0;

  this._time = Time.now();

  this.game.assets.onload(function() {
    this.start();

    window.cancelAnimationFrame(this.preloaderId);
    window.requestAnimationFrame(this.tickFunc);
  }.bind(this));

  if (this.game.assets.isLoading) {
    this.preloaderId = window.requestAnimationFrame(this.preloaderTickFunc);
  }
};

/**
 * Add event listener for window events
 * @private
 */
Engine.prototype.addEvents = function() {
  var self = this;

  var game = self.game;
  window.addEventListener('blur', function() {
    self.game.input.resetKeys();
    self.game.blur();
  });

  window.addEventListener('focus', function() {
    self.game.input.resetKeys();
    self.game.focus();
  });
};

/**
 * Starts the game, adds events and run first frame
 * @private
 */
Engine.prototype.start = function() {
  if (this.game.config.addInputEvents) {
    this.addEvents();
  }
};

/**
 * Main tick function in game loop
 * @private
 */
Engine.prototype.tick = function() {
  window.requestAnimationFrame(this.tickFunc);

  var now = Time.now();
  var time = (now - this._time) / 1000;
  this._time = now;

  this.game.debug.perf('update');
  this.update(time);
  this.game.debug.stopPerf('update');

  this.game.states.exitUpdate(time);

  this.game.debug.perf('render');
  this.render();
  this.game.debug.stopPerf('render');

  this.game.debug.render();
};

/**
 * Updates the game
 * @param {number} time - time in seconds since last frame
 * @private
 */
Engine.prototype.update = function(time) {
  if (time > this.game.config.maxStepTime) { time = this.game.config.maxStepTime; }

  if (this.game.config.fixedStep) {
    this.strayTime = this.strayTime + time;
    while (this.strayTime >= this.game.config.stepTime) {
      this.strayTime = this.strayTime - this.game.config.stepTime;
      this.game.states.update(this.game.config.stepTime);
    }
  } else {
    this.game.states.update(time);
  }
};

/**
 * Renders the game
 * @private
 */
Engine.prototype.render = function() {
  this.game.video.beginFrame();

  this.game.video.clear();

  this.game.states.render();

  this.game.video.endFrame();
};

/**
 * Main tick function in preloader loop
 * @private
 */
Engine.prototype._preloaderTick = function() {
  this.preloaderId = window.requestAnimationFrame(this.preloaderTickFunc);

  var now = Time.now();
  var time = (now - this._time) / 1000;
  this._time = now;

  if (this.game.config.showPreloader) {
    this.game.video.clear();
    this.game.preloading(time);
  }
};

Engine.prototype._setDefaultStates = function() {
  var states = new StateManager();
  states.add('app', this.game);
  states.add('debug', this.game.debug);

  states.protect('app');
  states.protect('debug');
  states.hide('debug');

  this.game.states = states;
};

Engine.prototype._subclassGame = function(container, methods) {
  var GameClass = function(container) {
    Game.call(this, container);
  };

  GameClass.prototype = Object.create(Game.prototype);

  for (var method in methods) {
    GameClass.prototype[method] = methods[method];
  }

  return GameClass;
};

module.exports = Engine;
<|endoftext|>


<commit_before>/*
* Copyright(c) 2011 Eran Hammer-Lahav <eran@hueniverse.com>
* MIT Licensed
* Based on RFC-Draft: http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token
*/

var Crypto = require('crypto');
var URL = require('url');
var Base = require("./base");
var AuthUtils = require('../_authutils');

MAC = module.exports = function (options) {

    // Module setup

    var that = Base(options);
    that.name = options.name || 'mac';

    var my = {};
    my._getTokenAttributes = options.getTokenAttributes;
    my._isHTTPS = options.isHTTPS || false;
    my._isForwardedHost = options.isForwardedHost || false;

    // MAC authentication

    that.authenticate = function (request, response, callback) {

        var self = this;

        // Parse HTTP Authorization header

        if (request.headers.authorization == null ||
            request.headers.authorization.length == 0) {

            // Error: No authentication

            return replyUnauthorized('', 'No authentication', response, callback, self);
        }

        var credentials = AuthUtils.splitAuthorizationHeader(request.headers.authorization);

        // Verify MAC athentication scheme

        if (credentials.type == null ||
            credentials.type.toLowerCase() != "mac") {

            // Error: Wrong authentication scheme

            return replyUnauthorized('', 'Incorrect authentication scheme', response, callback, self);
        }

        // Verify required header attributes

        if (credentials.token == null ||
            credentials.timestamp == null ||
            credentials.nonce == null ||
            credentials.signature == null) {

            // Error: Missing authentication attribute

            return replyUnauthorized('invalid_request', 'Missing attributes', response, callback, self);
        }

        // Obtain host and port information

        var hostHeader = (my._isForwardedHost ? request.headers['x-forwarded-host'] : request.headers.host);

        if (hostHeader == null) {

            // Error: Missing Host header field

            return replyUnauthorized('invalid_request', 'Missing Host header', response, callback, self);
        }

        var hostHeaderRegex = /^(?:(?:\r\n)?[\t ])*([^:]+)(?::(\d+))*(?:(?:\r\n)?[\t ])*$/; // Does not support IPv6
        var hostParts = hostHeaderRegex.exec(hostHeader);

        if (hostParts == null ||
            hostParts[1] == null) {

            // Error: Bad Host header field

            return replyUnauthorized('invalid_request', 'Bad Host header', response, callback, self);
        }

        var host = hostParts[1];
        var port = (hostParts[2] ? hostParts[2] : (my._isHTTPS ? 443 : 80));

        // Fetch token secret

        var tokenAttributes = my._getTokenAttributes(credentials.token);

        if (tokenAttributes.secret == null ||
            tokenAttributes.algorithm == null ||
            (tokenAttributes.algorithm != 'hmac-sha-1' && tokenAttributes.algorithm != 'hmac-sha-256')) {

            // Error: Invalid token

            return replyUnauthorized('invlaid_token', 'Invalid token', response, callback, self);
        }

        // Calculate signature

        var signature = signRequest(request.method,
                                    request.url,
                                    host,
                                    port,
                                    credentials.token,
                                    tokenAttributes.secret,
                                    tokenAttributes.algorithm,
                                    credentials.timestamp,
                                    credentials.nonce);

        if (signature != credentials.signature) {

            // Error: Bad signature

            return replyUnauthorized('invalid_token', 'Bad signature', response, callback, self);
        }

        // Successful authentication

        self.success(tokenAttributes, callback);
    };

    that.getAuthenticateResponseHeader = function () {
        return "MAC";
    };

    return that;
};

function replyUnauthorized(error, message, response, callback, executionScope) {

    switch (error) {
        case 'invalid_request': code = 400; break;
        case 'invalid_token': code = 401; break;
        case 'insufficient_scope': code = 403; break;
        default: code = 401; break;
    }

    response.writeHead(code, { 'Content-Type': 'text/plain',
        'WWW-Authenticate': 'MAC ' + (error ? 'error="' + error + '", error-desc="' + message + '"' : '')
    });
    response.end('Authorization Required');
    executionScope.halt(callback);
}

function signRequest(method, URI, host, port, token, secret, algorithm, timestamp, nonce) {

    // Parse request URI

    var uri = URL.parse(URI, true);

    if (uri.pathname == null) {

        // Error: Bad request URI
        return "";
    }

    // Construct normalized request string

    var normalized = token + '\n' +
                     timestamp + '\n' +
                     nonce + '\n' +
                     method.toUpperCase() + '\n' +
                     host.toLowerCase() + '\n' +
                     port + '\n' +
                     uri.pathname + '\n';

    // Normalize parameters

    var params = new Array;

    if (uri.query) {

        var count = 0;
        for (var p in uri.query) {

            if (typeof uri.query[p] == 'string') {

                params[count++] = percentEscape(p) + "=" + percentEscape(uri.query[p]);
            }
            else {

                for (var i in uri.query[p]) {

                    params[count++] = percentEscape(p) + "=" + percentEscape(uri.query[p][i]);
                }
            }
        }

        params.sort();

        for (var i in params) {

            normalized += params[i] + '\n';
        }
    }

    // Sign normalized request string

    var hashMethod;
    switch (algorithm) {

        case 'hmac-sha-1': hashMethod = 'sha1'; break;
        case 'hmac-sha-256': hashMethod = 'sha256'; break;
        default: return "";                                     // Error: Unknown algorithm
    }

    var hmac = Crypto.createHmac(hashMethod, secret).update(normalized);
    var digest = hmac.digest(encoding = "base64");
    return digest;
}

function percentEscape(value) {

    // Percent-escape per specification

    var escapedString = '';

    for (var i = 0; i < value.length; i++) {

        var char = value.charCodeAt(i);

        if ((char >= 48 && char <= 57) ||       // 09
            (char >= 65 && char <= 90) ||       // AZ
            (char >= 97 && char <= 122) ||      // az
            char == 45 ||                       // -
            char == 95 ||                       // _
            char == 46 ||                       // .
            char == 126) {                      // ~

            escapedString += String.fromCharCode(char);
        }
        else {

            escapedString += '%' + char.toString(16).toUpperCase();
        }
    }

    return escapedString;
}

<commit_msg>Fixed token lookup to callback<commit_after>/*
* Copyright(c) 2011 Eran Hammer-Lahav <eran@hueniverse.com>
* MIT Licensed
* Based on RFC-Draft: http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token
*/

var Crypto = require('crypto');
var URL = require('url');
var Base = require("./base");
var AuthUtils = require('../_authutils');

MAC = module.exports = function (options) {

    // Module setup

    var that = Base(options);
    that.name = options.name || 'mac';

    var my = {};
    my._getTokenAttributes = options.getTokenAttributes;
    my._isHTTPS = options.isHTTPS || false;
    my._isForwardedHost = options.isForwardedHost || false;

    // MAC authentication

    that.authenticate = function (request, response, callback) {

        var self = this;

        // Parse HTTP Authorization header

        if (request.headers.authorization == null ||
            request.headers.authorization.length == 0) {

            // Error: No authentication

            return replyUnauthorized('', 'No authentication', response, callback, self);
        }

        var credentials = AuthUtils.splitAuthorizationHeader(request.headers.authorization);

        // Verify MAC athentication scheme

        if (credentials.type == null ||
            credentials.type.toLowerCase() != "mac") {

            // Error: Wrong authentication scheme

            return replyUnauthorized('', 'Incorrect authentication scheme', response, callback, self);
        }

        // Verify required header attributes

        if (credentials.token == null ||
            credentials.timestamp == null ||
            credentials.nonce == null ||
            credentials.signature == null) {

            // Error: Missing authentication attribute

            return replyUnauthorized('invalid_request', 'Missing attributes', response, callback, self);
        }

        // Obtain host and port information

        var hostHeader = (my._isForwardedHost ? request.headers['x-forwarded-host'] : request.headers.host);

        if (hostHeader == null) {

            // Error: Missing Host header field

            return replyUnauthorized('invalid_request', 'Missing Host header', response, callback, self);
        }

        var hostHeaderRegex = /^(?:(?:\r\n)?[\t ])*([^:]+)(?::(\d+))*(?:(?:\r\n)?[\t ])*$/; // Does not support IPv6
        var hostParts = hostHeaderRegex.exec(hostHeader);

        if (hostParts == null ||
            hostParts[1] == null) {

            // Error: Bad Host header field

            return replyUnauthorized('invalid_request', 'Bad Host header', response, callback, self);
        }

        var host = hostParts[1];
        var port = (hostParts[2] ? hostParts[2] : (my._isHTTPS ? 443 : 80));

        // Fetch token secret

        my._getTokenAttributes(credentials.token, function (tokenAttributes) {

            if (tokenAttributes.secret == null ||
                tokenAttributes.algorithm == null ||
                (tokenAttributes.algorithm != 'hmac-sha-1' && tokenAttributes.algorithm != 'hmac-sha-256')) {

                // Error: Invalid token

                return replyUnauthorized('invlaid_token', 'Invalid token', response, callback, self);
            }

            // Calculate signature

            var signature = signRequest(request.method,
                                        request.url,
                                        host,
                                        port,
                                        credentials.token,
                                        tokenAttributes.secret,
                                        tokenAttributes.algorithm,
                                        credentials.timestamp,
                                        credentials.nonce);

            if (signature != credentials.signature) {

                // Error: Bad signature

                return replyUnauthorized('invalid_token', 'Bad signature', response, callback, self);
            }

            // Successful authentication

            self.success(tokenAttributes, callback);
        });
    };

    that.getAuthenticateResponseHeader = function () {
        return "MAC";
    };

    return that;
};

function replyUnauthorized(error, message, response, callback, executionScope) {

    switch (error) {
        case 'invalid_request': code = 400; break;
        case 'invalid_token': code = 401; break;
        case 'insufficient_scope': code = 403; break;
        default: code = 401; break;
    }

    response.writeHead(code, { 'Content-Type': 'text/plain',
        'WWW-Authenticate': 'MAC ' + (error ? 'error="' + error + '", error-desc="' + message + '"' : '')
    });
    response.end('Authorization Required');
    executionScope.halt(callback);
}

function signRequest(method, URI, host, port, token, secret, algorithm, timestamp, nonce) {

    // Parse request URI

    var uri = URL.parse(URI, true);

    if (uri.pathname == null) {

        // Error: Bad request URI
        return "";
    }

    // Construct normalized request string

    var normalized = token + '\n' +
                     timestamp + '\n' +
                     nonce + '\n' +
                     method.toUpperCase() + '\n' +
                     host.toLowerCase() + '\n' +
                     port + '\n' +
                     uri.pathname + '\n';

    // Normalize parameters

    var params = new Array;

    if (uri.query) {

        var count = 0;
        for (var p in uri.query) {

            if (typeof uri.query[p] == 'string') {

                params[count++] = percentEscape(p) + "=" + percentEscape(uri.query[p]);
            }
            else {

                for (var i in uri.query[p]) {

                    params[count++] = percentEscape(p) + "=" + percentEscape(uri.query[p][i]);
                }
            }
        }

        params.sort();

        for (var i in params) {

            normalized += params[i] + '\n';
        }
    }

    // Sign normalized request string

    var hashMethod;
    switch (algorithm) {

        case 'hmac-sha-1': hashMethod = 'sha1'; break;
        case 'hmac-sha-256': hashMethod = 'sha256'; break;
        default: return "";                                     // Error: Unknown algorithm
    }

    var hmac = Crypto.createHmac(hashMethod, secret).update(normalized);
    var digest = hmac.digest(encoding = "base64");
    return digest;
}

function percentEscape(value) {

    // Percent-escape per specification

    var escapedString = '';

    for (var i = 0; i < value.length; i++) {

        var char = value.charCodeAt(i);

        if ((char >= 48 && char <= 57) ||       // 09
            (char >= 65 && char <= 90) ||       // AZ
            (char >= 97 && char <= 122) ||      // az
            char == 45 ||                       // -
            char == 95 ||                       // _
            char == 46 ||                       // .
            char == 126) {                      // ~

            escapedString += String.fromCharCode(char);
        }
        else {

            escapedString += '%' + char.toString(16).toUpperCase();
        }
    }

    return escapedString;
}

<|endoftext|>


<commit_before>// var response = prompt('Do you want to play battleship? Yes/No');

// if (response.toLowerCase() === 'yes') {
//     alert('Awesome! Let us begin!');
// } else {
//     alert('Doh!  Maybe next time :( ');
// }

// Object to represent player
var player = {
    shotCounter : 0,

    // Method to shoot at a guessed position.
    shootPosition: function(letter, number){
        this.shotCounter++;
        document.getElementById('shotCounter').innerHTML = 'Shots: ' + this.shotCounter;
        if (enemy.shootResponse(letter, number)){
            return true;
        } else {
            return false;
        }
    }
};

// Object to represent enemy
var enemy = {
    numShips : 4,
    carrierHP:    5,
    battleshipHP: 4,
    cruiserHP:    3,
    destroyerHP:  2,

    // 2D Array of ships.  Manual placement for now.  Will randomize later.
    //  x =  0  1  2  3  4  5  6
    board: [[0, 0, 0, 0, 0, 0, 0],     // y = 0
            [0, 0, 0, 0, 0, 0, 0],     // y = 1
            [0, 5, 5, 5, 5, 5, 0],     // y = 2
            [4, 0, 0, 0, 0, 0, 0],     // y = 3
            [4, 0, 0, 0, 0, 0, 0],     // y = 4
            [4, 0, 3, 3, 3, 0, 2],     // y = 5
            [4, 0, 0, 0, 0, 0, 2]],     // y = 6

    // Method to calculate whether a shot hits, and respond appropriately.
    shootResponse: function(x, y ){
        var shotValue = this.board[y][x];

        if (shotValue > 0){             // if shotValue > 0, then there is a ship.
            console.log('Hit!');
            switch (shotValue) {        // Check which type of ship it is.
                case 2:                 // Destroyer
                    this.destroyerHP--;
                    if (this.destroyerHP === 0) {
                        console.log('You sunk my destroyer!');
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
                case 3:                 // Cruiser
                    this.cruiserHP--;
                    if (this.cruiserHP === 0) {
                        console.log('You sunk my cruiser!');
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
                case 4:                 // Battleship
                    this.battleshipHP--;
                    if (this.battleshipHP === 0) {
                        console.log('You sunk my battleship!');
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
                case 5:                 // Carrier
                    this.carrierHP--;
                    if (this.carrierHP === 0) {
                        console.log('You sunk my carrier!');
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
            }
            this.board[y][x] = -1;
        } else if (shotValue == -1) {
            console.log('You\'ve already shot an enemy here!  Please select another square!');
            return true;
        }
         else {
            console.log('Miss!');
            return false;
        }

        // When number of ships is 0, game is over.
        if (this.numShips === 0){
            console.log('Congratulations, you won the game!');
            console.log('It only took you ' + player.shotCounter + ' shots!');
            alert('Congratulations, you won the game!\nIt only took you ' + player.shotCounter + ' shots!');
        }
        return true;
    }
};

// Object to represent HTML Elements
var boardUI = {
    createClickFire: function() {

        // Create anonymous function to pass in the i and j to use closure
        function createAnonFunction(i, j) {
            var anonFcn = function() {
                if(player.shootPosition(i,j)){
                    $(this).css('background-color', 'red');
                } else {
                    $(this).css('background-color', 'gray');
                }
            };
            return anonFcn;
        }

        // Loop to initialize all click handlers and hover functions
        for (var i = 0; i < 7; ++i) {
            for (var j = 0; j < 7; ++j) {
                $('#box' + i + j).click(createAnonFunction(i, j));
            }
        }
    }
};

$(document).ready(function() {
    boardUI.createClickFire();
});<commit_msg>Added text updating on html page<commit_after>// var response = prompt('Do you want to play battleship? Yes/No');

// if (response.toLowerCase() === 'yes') {
//     alert('Awesome! Let us begin!');
// } else {
//     alert('Doh!  Maybe next time :( ');
// }

// Object to represent player
var player = {
    shotCounter : 0,

    // Method to shoot at a guessed position.
    shootPosition: function(letter, number){
        this.shotCounter++;
        document.getElementById('shotCounter').innerHTML = 'Shots: ' + this.shotCounter;
        if (enemy.shootResponse(letter, number)){
            return true;
        } else {
            return false;
        }
    }
};

// Object to represent enemy
var enemy = {
    numShips : 4,
    carrierHP:    5,
    battleshipHP: 4,
    cruiserHP:    3,
    destroyerHP:  2,

    // 2D Array of ships.  Manual placement for now.  Will randomize later.
    //  x =  0  1  2  3  4  5  6
    board: [[0, 0, 0, 0, 0, 0, 0],     // y = 0
            [0, 0, 0, 0, 0, 0, 0],     // y = 1
            [0, 5, 5, 5, 5, 5, 0],     // y = 2
            [4, 0, 0, 0, 0, 0, 0],     // y = 3
            [4, 0, 0, 0, 0, 0, 0],     // y = 4
            [4, 0, 3, 3, 3, 0, 2],     // y = 5
            [4, 0, 0, 0, 0, 0, 2]],     // y = 6

    // Method to calculate whether a shot hits, and respond appropriately.
    shootResponse: function(x, y ){
        var shotValue = this.board[y][x];

        if (shotValue > 0){             // if shotValue > 0, then there is a ship.
            console.log('Hit!');
            boardUI.textOutput.innerHTML = 'Woohoo!  It\'s a hit!';
            switch (shotValue) {        // Check which type of ship it is.
                case 2:                 // Destroyer
                    this.destroyerHP--;
                    if (this.destroyerHP === 0) {
                        console.log('You sunk my destroyer!');
                        boardUI.textOutput.innerHTML += '
You sunk my destroyer!'
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
                case 3:                 // Cruiser
                    this.cruiserHP--;
                    if (this.cruiserHP === 0) {
                        console.log('You sunk my cruiser!');
                        boardUI.textOutput.innerHTML += '
You sunk my cruiser!'
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
                case 4:                 // Battleship
                    this.battleshipHP--;
                    if (this.battleshipHP === 0) {
                        console.log('You sunk my battleship!');
                        boardUI.textOutput.innerHTML += '
You sunk my battleship!'
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
                case 5:                 // Carrier
                    this.carrierHP--;
                    if (this.carrierHP === 0) {
                        console.log('You sunk my carrier!');
                        boardUI.textOutput.innerHTML += '
You sunk my carrier!'
                        this.numShips--;
                        document.getElementById('shipsRemaining').innerHTML = 'Ships Remaining: ' + this.numShips;
                    }
                    break;
            }
            this.board[y][x] = -1;
        } else if (shotValue == -1) {
            console.log('You\'ve already shot an enemy here!  Please select another square!');
            return true;
        }
         else {
            console.log('Miss!');
            boardUI.textOutput.innerHTML = 'Doh!  You missed.  Shoot again!';
            return false;
        }

        // When number of ships is 0, game is over.
        if (this.numShips === 0){
            console.log('Congratulations, you won the game!');
            console.log('It only took you ' + player.shotCounter + ' shots!');
            boardUI.textOutput.innerHTML += '
Congratulations!
It only took you ' + player.shotCounter + ' shots to win!';
            boardUI.textOutput.innerHTML += '
Hit refresh to play again!'
            alert('Congratulations, you won the game!\nIt only took you ' + player.shotCounter + ' shots!');
        }
        return true;
    }
};

// Object to represent HTML Elements
var boardUI = {
    textOutput : document.getElementById('textDisplay'),

    createClickFire: function() {

        // Create anonymous function to pass in the i and j to use closure
        function createAnonFunction(i, j) {
            var anonFcn = function() {
                if(player.shootPosition(i,j)){
                    $(this).css('background-color', 'red');
                } else {
                    $(this).css('background-color', 'gray');
                }
            };
            return anonFcn;
        }

        // Loop to initialize all click handlers and hover functions
        for (var i = 0; i < 7; ++i) {
            for (var j = 0; j < 7; ++j) {
                $('#box' + i + j).click(createAnonFunction(i, j));
            }
        }
    },
    preloadCards: function() {

        $.preloadImages = function() {
          for (var i = 0; i < arguments.length; i++) {
            $('').attr('src', arguments[i]);
          }
        };

        $.preloadImages('hoverimage1.jpg','hoverimage2.jpg');

    }
};

$(document).ready(function() {
    boardUI.createClickFire();
});<|endoftext|>


<commit_before>/*
 * PsychoMonkey
 * Copyright (C) 2012 Simon Kornblith
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var PTB = function(context) {
	this.ctx = context;
}
PTB.prototype = {
	"FillOval":function(color, rect) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "fillStyle", "white");
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				if(colorArray) this.ctx.fillStyle = this._colorToStyle(colorArray[i]);
				this._makeOvalPath(rects[i]);
				this.ctx.fill();
			}
		} finally {
			this.ctx.restore();
		}
	},
	"FrameOval":function(color, rect, penWidth) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "strokeStyle", "white");
			if(typeof penWidth !== "object") penWidth = [penWidth];
			if(penWidth.length === 1) this.ctx.lineWidth = penWidth ? penWidth : 1;
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				if(colorArray) this.ctx.strokeStyle = this._colorToStyle(colorArray[i]);
				if(penWith.length !== 1) this.ctx.lineWidth = penWidth[i];
				this._makeOvalPath(rects[i]);
				this.ctx.stroke();
			}
		} finally {
			this.ctx.restore();
		}
	},
	"FillRect":function(color, rect) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "fillStyle", "white");
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				var rect = rects[i];
				if(colorArray) this.ctx.fillStyle = this._colorToStyle(colorArray[i]);
				this.ctx.fillRect(rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1]);
			}
		} finally {
			this.ctx.restore();
		}
	},
	"FrameRect":function(color, rect, penWidth) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "strokeStyle", "white");
			if(typeof penWidth !== "object") penWidth = [penWidth];
			if(penWidth.length === 1) this.ctx.lineWidth = penWidth ? penWidth : 1;
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				var rect = rects[i];
				if(colorArray) this.ctx.strokeStyle = this._colorToStyle(colorArray[i]);
				if(penWidth.length !== 1) this.ctx.lineWidth = penWidth[i];
				this.ctx.strokeRect(rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1]);
			}
		} finally {
			this.ctx.restore();
		}
	},
	"DrawDots":function(xy, size, color, center, dot_type) {
		this.ctx.save();
		try {
			if(!size) size = 1;
			if(!dot_type) dot_type = 0;

			var colorArray = this._getColorArrayOrSetColor(color, "fillStyle", "black");
			if(center) this.ctx.translate(center[0], center[1]);

			var x = typeof xy[0] === "object" ? xy[0] : [xy[0]],
				y = typeof xy[1] === "object" ? xy[1] : [xy[1]];
			for(var i=0; i<x.length; i++) {
				if(colorArray) this.ctx.fillStyle = this._colorToStyle(colorArray[i]);
				var dotSize = typeof size === "object" ? size[i] : size;
				if(dot_type === 0) {
					this.ctx.fillRect(x[i]-dotSize/2, y[i]-dotSize/2,
						x[i]+dotSize/2, y[i]+dotSize/2);
				} else {
					this.ctx.beginPath();
					this.ctx.arc(x[i], y[i], dotSize/2, 0, Math.PI*2, false);
					this.ctx.closePath();
					this.ctx.fill();
				}
			}
		} finally {
			this.ctx.restore();
		}
	},
	"_transpose":function(array) {
		var newArray = [];
		for(var i=0; i<array[0].length; i++) {
			var newArrayX = [];
			for(var j=0; j<array.length; j++) {
				newArrayX.push(array[j][i]);
			}
			newArray.push(newArrayX);
		}
		return newArray;
	},
	"_makeOvalPath":function(rect) {
		var width = rect[3]-rect[1],
			height = rect[4]-rect[2];
		this.ctx.beginPath();
		this.ctx.translate(rect[1]+width/2, rect[2]+height/2);
		this.ctx.scale(width/2, height/2);
		this.ctx.arc(0, 0, 1, 0, Math.PI*2, false);
		this.ctx.closePath();
	},
	"_getColorArrayOrSetColor":function(color, style, defaultColor) {
		if(color === null || color === undefined) {
			this.ctx[style] = defaultColor;
			return undefined;
		}
		if(typeof color === "object" && typeof color[0] === "object") {
			return this._transpose(color);
		}
		this.ctx[style] = this._colorToStyle(color);
		return undefined;
	},
	"_getRectArray":function(rect) {
		if(!rect) {
			return [[0, 0, CONFIG.displaySize[0], CONFIG.displaySize[1]]];
		}
		if(typeof rect[0] === "object") {
			return this._transpose(rect);
		}
		return [rect];
	},
	"_colorToStyle":function(color) {
		if(color === null || color === undefined) {
			return "white";
		} else if(typeof color !== "object") {
			return "rgb("+color+", "+color+", "+color+")";
		} else if(color.length === 1) {
			return "rgb("+color[0]+", "+color[0]+", "+color[0]+")";
		} else if(color.length === 3) {
			return "rgb("+color[0]+", "+color[1]+", "+color[2]+")";
		} else if(color.length === 4) {
			return "rgba("+color[0]+", "+color[1]+", "+color[2]+", "+color[3]+")";
		} else {
			throw new Error("Invalid color");
		}
	}
};

var OSD = function(div) {
};
OSD.prototype.update = function(info) {
};

var Client = function(canvas) {
	this.canvas = canvas;
	this.ctx = canvas.getContext("2d");
	this.ptb = new PTB(this.ctx);
	this._lastEyePosition = null;
	this._textures = {};
}
Client.prototype = {
	/**
	 * Updates the on-screen display
	 */
	"OSD":function(info) {
		document.getElementById("osd-state").textContent = info.state;

		var longestKey = 0,
			keyInfoStrings = [];
		for(var i in info.keyInfo) {
			if(i.length > longestKey) longestKey = i.length;
		}
		for(var i in info.keyInfo) {
			var str = i;
			while(str.length < longestKey) str += " ";
			str += " - "+info.keyInfo[i];
			keyInfoStrings.push(str);
		}
		document.getElementById("osd-keyInfo").textContent = keyInfoStrings.join("\n");

		var performanceStrings = [];
		for(var i in info.performance) {
			var success = info.performance[i][0];
			var total = info.performance[i][1];
			if(total == 0) {
				var pct = 0;
			} else {
				var pct = Math.round(success/total*100);
			}
			performanceStrings.push(i+" "+success+"/"+total+" ("+pct+"%)");
		}
		document.getElementById("osd-performance").textContent = performanceStrings.join("\n");
	},

	/**
	 * Updates targets plotted over the canvas
	 */
	"TRG":function(payload) {
		for(var i=0; i<payload.targetRects.length; i++) {
			this.ptb[payload.targetIsOval[i] ? "FrameOval" : "FrameRect"]([255, 255, 0, 1],
				payload.targetRects[i]);
		}
	},

	/**
	 * Redraws the underlying image
	 */
	"DRW":function(directives) {
		this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
		if(!(directives instanceof Array)) directives = [directives];
		for(var i=0; i<directives.length; i++) {
			var directive = directives[i];
			if(directive.command === "DrawTexture") {
				this.ctx.save();
				var texture = this._textures[directive.arguments[0]],
					sourceRect = directive.arguments[1],
					destinationRect = directive.arguments[2],
					rotationAngle = directive.arguments[3],
					globalAlpha = directive.arguments[5];

				try {
					if(rotationAngle) this.ctx.rotate(rotationAngle*Math.PI/180);
					if(globalAlpha) this.ctx.globalAlpha = globalAlpha;

					if(sourceRect) {
						this.ctx.drawImage(texture, sourceRect[0], sourceRect[1],
							sourceRect[2]-sourceRect[0], sourceRect[3]-sourceRect[1],
							destinationRect[0], destinationRect[1],
							destinationRect[2]-destinationRect[0],
							destinationRect[3]-destinationRect[1]);
					} else {
						this.ctx.drawImage(texture, destinationRect[0], destinationRect[1],
							destinationRect[2]-destinationRect[0],
							destinationRect[3]-destinationRect[1]);
					}
				} finally {
					this.ctx.restore();
				}
			} else {
				this.ptb[directive.command].apply(this.ptb, directive.arguments);
			}
		}
	},

	/**
	 * Draws eye data
	 */
	"EYE":function(pos) {
		this.ctx.save();
		if(this._lastEyePosition) {
			this.ctx.fillColor = "rgb(0, 0, 255)";
			this.ctx.fillRect(this._lastEyePosition[0]-2, this._lastEyePosition[1]-2,
				this._lastEyePosition[0]+2, this._lastEyePosition[1]+2);
		}
		if(pos[0]-2 >= 0 && pos[1]-2 >= 0 && pos[0]+2 < CONFIG.displaySize[0] &&
				pos[1]+2 < CONFIG.displaySize[1]) {
			this.ctx.fillColor = "rgb(255, 0, 0)";
			this.ctx.fillRect(pos[0]-2, pos[1]-2, pos[0]+2, pos[1]+2);
		}
		this.ctx.restore();
	},

	/**
	 * Preloads textures
	 */
	"TXT":function(textureIndices) {
		for(var i=0; i<textureIndices.length; i++) {
			var textureIndex = textureIndices[i];
			if(!this._textures[textureIndex]) {
				var img = document.createElement("img");
				img.src = "/texture/"+textureIndex+".png";
				document.getElementById("textures").appendChild(img);
				this._textures[textureIndex] = img;
			}
		}
	}
};

window.addEventListener("DOMContentLoaded", function(event) {
	var canvas = document.createElement("canvas");
	canvas.width = CONFIG.displaySize[0];
	canvas.height = CONFIG.displaySize[1];
	canvas.id = "pmcanvas";
	document.body.appendChild(canvas);
	document.getElementById("osd").style.height = CONFIG.OSDHeight/CONFIG.displaySize[1]*100+"%";

	var client = new Client(canvas);

	var ws = new WebSocket("ws://"+window.location.hostname+":20557/");
	ws.onmessage = function(event) {
		var data = event.data,
			code = data.substr(0, 3),
			payload = JSON.parse(data.substr(5));
		console.log(data);
		if(code in client) {
			client[code](payload);
		} else {
			console.error("Could not parse message: "+data);
		}
	};
}, false);<commit_msg>Fixes<commit_after>/*
 * PsychoMonkey
 * Copyright (C) 2012 Simon Kornblith
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var PTB = function(context) {
	this.ctx = context;
}
PTB.prototype = {
	"FillOval":function(color, rect) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "fillStyle", "white");
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				if(colorArray) this.ctx.fillStyle = this._colorToStyle(colorArray[i]);
				this._makeOvalPath(rects[i]);
				this.ctx.fill();
			}
		} finally {
			this.ctx.restore();
		}
	},
	"FrameOval":function(color, rect, penWidth) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "strokeStyle", "white");
			if(typeof penWidth !== "object") penWidth = [penWidth];
			if(penWidth.length === 1) this.ctx.lineWidth = penWidth ? penWidth : 1;
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				if(colorArray) this.ctx.strokeStyle = this._colorToStyle(colorArray[i]);
				if(penWidth.length !== 1) this.ctx.lineWidth = penWidth[i];
				this._makeOvalPath(rects[i]);
				this.ctx.stroke();
			}
		} finally {
			this.ctx.restore();
		}
	},
	"FillRect":function(color, rect) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "fillStyle", "white");
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				var rect = rects[i];
				if(colorArray) this.ctx.fillStyle = this._colorToStyle(colorArray[i]);
				this.ctx.fillRect(rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1]);
			}
		} finally {
			this.ctx.restore();
		}
	},
	"FrameRect":function(color, rect, penWidth) {
		this.ctx.save();
		try {
			var colorArray = this._getColorArrayOrSetColor(color, "strokeStyle", "white");
			if(typeof penWidth !== "object") penWidth = [penWidth];
			if(penWidth.length === 1) this.ctx.lineWidth = penWidth ? penWidth : 1;
			var rects = this._getRectArray(rect);
			for(var i=0; i<rects.length; i++) {
				var rect = rects[i];
				if(colorArray) this.ctx.strokeStyle = this._colorToStyle(colorArray[i]);
				if(penWidth.length !== 1) this.ctx.lineWidth = penWidth[i];
				this.ctx.strokeRect(rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1]);
			}
		} finally {
			this.ctx.restore();
		}
	},
	"DrawDots":function(xy, size, color, center, dot_type) {
		this.ctx.save();
		try {
			if(!size) size = 1;
			if(!dot_type) dot_type = 0;

			var colorArray = this._getColorArrayOrSetColor(color, "fillStyle", "black");
			if(center) this.ctx.translate(center[0], center[1]);

			var x = typeof xy[0] === "object" ? xy[0] : [xy[0]],
				y = typeof xy[1] === "object" ? xy[1] : [xy[1]];
			for(var i=0; i<x.length; i++) {
				if(colorArray) this.ctx.fillStyle = this._colorToStyle(colorArray[i]);
				var dotSize = typeof size === "object" ? size[i] : size;
				if(dot_type === 0) {
					this.ctx.fillRect(x[i]-dotSize/2, y[i]-dotSize/2,
						x[i]+dotSize/2, y[i]+dotSize/2);
				} else {
					this.ctx.beginPath();
					this.ctx.arc(x[i], y[i], dotSize/2, 0, Math.PI*2, false);
					this.ctx.closePath();
					this.ctx.fill();
				}
			}
		} finally {
			this.ctx.restore();
		}
	},
	"_transpose":function(array) {
		var newArray = [];
		for(var i=0; i<array[0].length; i++) {
			var newArrayX = [];
			for(var j=0; j<array.length; j++) {
				newArrayX.push(array[j][i]);
			}
			newArray.push(newArrayX);
		}
		return newArray;
	},
	"_makeOvalPath":function(rect) {
		var width = rect[2]-rect[0],
			height = rect[3]-rect[1];
		this.ctx.beginPath();
		this.ctx.translate(rect[0]+width/2, rect[1]+height/2);
		this.ctx.scale(width/2, height/2);
		this.ctx.arc(0, 0, 1, 0, Math.PI*2, false);
		this.ctx.closePath();
	},
	"_getColorArrayOrSetColor":function(color, style, defaultColor) {
		if(color === null || color === undefined) {
			this.ctx[style] = defaultColor;
			return undefined;
		}
		if(typeof color === "object" && typeof color[0] === "object") {
			return this._transpose(color);
		}
		this.ctx[style] = this._colorToStyle(color);
		return undefined;
	},
	"_getRectArray":function(rect) {
		if(!rect) {
			return [[0, 0, CONFIG.displaySize[0], CONFIG.displaySize[1]]];
		}
		if(typeof rect[0] === "object") {
			return this._transpose(rect);
		}
		return [rect];
	},
	"_colorToStyle":function(color) {
		if(color === null || color === undefined) {
			return "white";
		} else if(typeof color !== "object") {
			return "rgb("+color+", "+color+", "+color+")";
		} else if(color.length === 1) {
			return "rgb("+color[0]+", "+color[0]+", "+color[0]+")";
		} else if(color.length === 3) {
			return "rgb("+color[0]+", "+color[1]+", "+color[2]+")";
		} else if(color.length === 4) {
			return "rgba("+color[0]+", "+color[1]+", "+color[2]+", "+color[3]+")";
		} else {
			throw new Error("Invalid color");
		}
	}
};

var OSD = function(div) {
};
OSD.prototype.update = function(info) {
};

var Client = function(canvas) {
	this.canvas = canvas;
	this.ctx = canvas.getContext("2d");
	this.ptb = new PTB(this.ctx);
	this._lastEyePosition = null;
	this._textures = {};
}
Client.prototype = {
	/**
	 * Updates the on-screen display
	 */
	"OSD":function(info) {
		document.getElementById("osd-state").textContent = info.state;

		var longestKey = 0,
			keyInfoStrings = [];
		for(var i in info.keyInfo) {
			if(i.length > longestKey) longestKey = i.length;
		}
		for(var i in info.keyInfo) {
			var str = i;
			while(str.length < longestKey) str += " ";
			str += " - "+info.keyInfo[i];
			keyInfoStrings.push(str);
		}
		document.getElementById("osd-keyInfo").textContent = keyInfoStrings.join("\n");

		var performanceStrings = [];
		for(var i in info.performance) {
			var success = info.performance[i][0];
			var total = info.performance[i][1];
			if(total == 0) {
				var pct = 0;
			} else {
				var pct = Math.round(success/total*100);
			}
			performanceStrings.push(i+" "+success+"/"+total+" ("+pct+"%)");
		}
		document.getElementById("osd-performance").textContent = performanceStrings.join("\n");
	},

	/**
	 * Updates targets plotted over the canvas
	 */
	"TRG":function(payload) {
		if(!payload.targetRects) return;
		if(typeof payload.targetRects[0] !== "object") {
			payload.targetRects = [payload.targetRects];
		}
		for(var i=0; i<payload.targetRects.length; i++) {
			this.ptb[payload.targetIsOval[i] ? "FrameOval" : "FrameRect"]([255, 255, 0, 1],
				payload.targetRects[i]);
		}
	},

	/**
	 * Redraws the underlying image
	 */
	"DRW":function(directives) {
		var cw = this.canvas.width, ch = this.canvas.height;
		this.ctx.clearRect(0, 0, cw, ch);
		if(!(directives instanceof Array)) directives = [directives];
		for(var i=0; i<directives.length; i++) {
			var directive = directives[i];
			if(directive.command === "DrawTexture") {
				this.ctx.save();
				var textureIndex = typeof directive.arguments[0] === "object" ? directive.arguments[0][0] : directive.arguments[0],
					texture = this._textures[textureIndex],
					sourceRect = directive.arguments[1],
					destinationRect = directive.arguments[2],
					rotationAngle = directive.arguments[3],
					globalAlpha = directive.arguments[5];

				try {
					if(!destinationRect) {
						var nw = texture.naturalWidth, nh = texture.naturalHeight;
						destinationRect = [cw/2-nw/2, ch/2-nh/2, cw/2+nw/2, cw/2+nh/2];
					}
					if(rotationAngle) this.ctx.rotate(rotationAngle*Math.PI/180);
					if(globalAlpha) this.ctx.globalAlpha = globalAlpha;

					if(sourceRect) {
						this.ctx.drawImage(texture, sourceRect[0], sourceRect[1],
							sourceRect[2]-sourceRect[0], sourceRect[3]-sourceRect[1],
							destinationRect[0], destinationRect[1],
							destinationRect[2]-destinationRect[0],
							destinationRect[3]-destinationRect[1]);
					} else {
						this.ctx.drawImage(texture, destinationRect[0], destinationRect[1],
							destinationRect[2]-destinationRect[0],
							destinationRect[3]-destinationRect[1]);
					}
				} finally {
					this.ctx.restore();
				}
			} else {
				this.ptb[directive.command].apply(this.ptb, directive.arguments);
			}
		}
	},

	/**
	 * Draws eye data
	 */
	"EYE":function(pos) {
		this.ctx.save();
		if(this._lastEyePosition) {
			this.ctx.fillColor = "rgb(0, 0, 255)";
			this.ctx.fillRect(this._lastEyePosition[0]-2, this._lastEyePosition[1]-2,
				this._lastEyePosition[0]+2, this._lastEyePosition[1]+2);
		}
		if(pos[0]-2 >= 0 && pos[1]-2 >= 0 && pos[0]+2 < this.canvas.width &&
				pos[1]+2 < this.canvas.height) {
			this.ctx.fillColor = "rgb(255, 0, 0)";
			this.ctx.fillRect(pos[0]-2, pos[1]-2, pos[0]+2, pos[1]+2);
			this._lastEyePosition = pos;
		}
		this.ctx.restore();
	},

	/**
	 * Preloads textures
	 */
	"TXT":function(textureIndices) {
		for(var i=0; i<textureIndices.length; i++) {
			var textureIndex = textureIndices[i];
			if(!this._textures[textureIndex]) {
				var img = document.createElement("img");
				img.src = "/texture/"+textureIndex+".png";
				document.getElementById("textures").appendChild(img);
				this._textures[textureIndex] = img;
			}
		}
	}
};

window.addEventListener("DOMContentLoaded", function(event) {
	var canvas = document.createElement("canvas");
	canvas.width = CONFIG.displaySize[0];
	canvas.height = CONFIG.displaySize[1];
	canvas.id = "pmcanvas";
	document.body.appendChild(canvas);
	document.getElementById("osd").style.height = CONFIG.OSDHeight/CONFIG.displaySize[1]*100+"%";

	var client = new Client(canvas);

	var ws = new WebSocket("ws://"+window.location.hostname+":20557/");
	ws.onmessage = function(event) {
		var data = event.data,
			code = data.substr(0, 3),
			payload = JSON.parse(data.substr(5));
		console.log(data);
		if(code in client) {
			client[code](payload);
		} else {
			console.error("Could not parse message: "+data);
		}
	};
}, false);<|endoftext|>


<commit_before>'use strict';

const es = require('vinyl-elasticsearch');

class ElasticSearchSink {
  constructor() {
    this._opts = {};
  }

  host(host) {
    this._opts.host = host;

    return this;
  }

  retries(retries) {
    this._opts.retries = retries;

    return this;
  }

  index(index) {
    this._index = index;

    return this;
  }

  type(type) {
    this._type = type;

    return this;
  }

  getStream() {
    let glob = {
      index: this._index,
      body: {
        query: {
          filtered: {
            filter: {
              bool: {
                'must': [
                  {
                    type: {
                      value: this._type
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
    return es.src(glob, this._opts);
  }
}

module.exports = ElasticSearchSink;
<commit_msg>fix name in ElasticSearchSource<commit_after>'use strict';

const es = require('vinyl-elasticsearch');

class ElasticSearchSource {
  constructor() {
    this._opts = {};
  }

  host(host) {
    this._opts.host = host;

    return this;
  }

  retries(retries) {
    this._opts.retries = retries;

    return this;
  }

  index(index) {
    this._index = index;

    return this;
  }

  type(type) {
    this._type = type;

    return this;
  }

  getStream() {
    let glob = {
      index: this._index,
      body: {
        query: {
          filtered: {
            filter: {
              bool: {
                'must': [
                  {
                    type: {
                      value: this._type
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
    return es.src(glob, this._opts);
  }
}

module.exports = ElasticSearchSource;
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is infoRSS.
 *
 * The Initial Developer of the Original Code is
 *   Didier Ernotte <didier@ernotte.com>.
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Didier Ernotte <didier@ernotte.com>.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
//------------------------------------------------------------------------------
// inforss_Utils
// Author : Tom Tanner 2017
//------------------------------------------------------------------------------
/* jshint globalstrict: true */
/* eslint-disable strict */
"use strict";

//This module provides assorted utilities

/* exported EXPORTED_SYMBOLS */
const EXPORTED_SYMBOLS = [
  "replace_without_children", /* exported replace_without_children */
  "remove_all_children", /* exported remove_all_children */
  "make_URI", /* exported make_URI */
  "htmlFormatConvert", /* exported htmlFormatConvert */
  "format_as_hh_mm_ss", /* exported format_as_hh_mm_ss */
  "open_option_window", /* exported open_option_window */
  "option_window_displayed", /* exported option_window_displayed */
  "should_reuse_current_tab", /* exported should_reuse_current_tab */
  "read_password", /* exported read_password */
  "store_password", /* exported store_password */
  "event_binder", /* exported event_binder */
  "add_event_listeners", /* exported add_event_listeners */
  "remove_event_listeners", /* exported remove_event_listeners */
];

const { debug } = Components.utils.import(
  "chrome://inforss/content/modules/inforss_Debug.jsm",
  {}
);

//const { console } = Components.utils.import(
//  "resource://gre/modules/Console.jsm",
//  {}
//);

const IoService = Components.classes[
  "@mozilla.org/network/io-service;1"].getService(
  Components.interfaces.nsIIOService);

const FormatConverter = Components.Constructor(
  "@mozilla.org/widget/htmlformatconverter;1",
  "nsIFormatConverter"
);

const WindowMediator = Components.classes[
  "@mozilla.org/appshell/window-mediator;1"].getService(
  Components.interfaces.nsIWindowMediator);

const WindowWatcher = Components.classes[
  "@mozilla.org/embedcomp/window-watcher;1"].getService(
  Components.interfaces.nsIWindowWatcher);

const SupportsString = Components.Constructor(
  "@mozilla.org/supports-string;1",
  "nsISupportsString"
);

const LoginManager = Components.classes[
  "@mozilla.org/login-manager;1"].getService(
  Components.interfaces.nsILoginManager);

const LoginInfo = Components.Constructor(
  "@mozilla.org/login-manager/loginInfo;1",
  Components.interfaces.nsILoginInfo,
  "init");

const As_HH_MM_SS = new Intl.DateTimeFormat(
  [],
  { hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false }
);

//------------------------------------------------------------------------------
/** Removes all the children of a node
 *
 * This is the most performant way of removing all the children of a node.
 * However, it doesn't seem to work well if the GUI already has its hands on the
 * node in question.
 *
 * @param {Object} node - original node
 *
 * @returns {Object} new node
 */
function replace_without_children(node)
{
  const new_node = node.cloneNode(false);
  node.parentNode.replaceChild(new_node, node);
  return new_node;
}

//------------------------------------------------------------------------------
function remove_all_children(node)
{
  while (node.lastChild != null)
  {
    node.removeChild(node.lastChild);
  }
}

/** Make a URI from a string
 *
 * @param {string} url - url to turn into a URI
 *
 * @returns {URI} URI object
 */
function make_URI(url)
{
  return IoService.newURI(url);
}

//FIXME the only place that passes extra parameters is nntp feed. Given that,
//perhaps we should drop all the parameters and give that its own function.
/** HTML string conversion
 *
 * @param {string} str - string to convert
 * @param {boolean} keep - keep < and > if set
 * @param {string} mimeTypeFrom - mime type of string (defaults to text/html)
 * @param {string} mimeTypeTo - mime type to convert to (defaults to
 *                 text/unicode
 *
 * @returns {string} converted string
 *
 */
function htmlFormatConvert(str, keep, mimeTypeFrom, mimeTypeTo)
{
  if (str == null)
  {
    return ""; //Seriously - this happens
  }

  let convertedString = null;

  //This is called from inforssNntp with keep false, converting from plain to
  //html. Arguably it should have its own method.
  if (keep == null)
  {
    keep = true;
  }

  if (mimeTypeFrom == null)
  {
    mimeTypeFrom = "text/html";
  }

  if (mimeTypeTo == null)
  {
    mimeTypeTo = "text/unicode";
  }

  if (keep)
  {
    str = str.replace(/</gi, "__LT__");
    str = str.replace(/>/gi, "__GT__");
  }

  const fromString = new SupportsString();
  fromString.data = str;
  let toString = { value: null };

  try
  {
    //This API is almost completely undocumented, so I've no idea how to rework
    //it it into something useful.
    const converter = new FormatConverter();
    converter.convert(mimeTypeFrom,
                      fromString,
                      fromString.toString().length,
                      mimeTypeTo,
                      toString,
                      {});
    if (toString.value)
    {
      toString = toString.value.QueryInterface(
        Components.interfaces.nsISupportsString);
      convertedString = toString.toString();
      if (keep)
      {
        convertedString = convertedString.replace(/__LT__/gi, "<");
        convertedString = convertedString.replace(/__GT__/gi, ">");
      }
    }
    else
    {
      convertedString = str;
    }
  }
  catch (err)
  {
    convertedString = str;
  }

  return convertedString;
}

/** Convert time to hh:mm:ss string
 *
 * @param {Date} date - time which we want to convert
 *
 * @returns {str} hh:mm:ss string in local time
 */
function format_as_hh_mm_ss(date)
{
  return As_HH_MM_SS.format(date);
}

/** Open or focus the option window */
function open_option_window()
{
  const option_window = WindowMediator.getMostRecentWindow("inforssOption");
  if (option_window == null)
  {
    WindowWatcher.openWindow(
      null,
      "chrome://inforss/content/inforssOption.xul",
      "_blank",
      "chrome,centerscreen,resizable=yes,dialog=no",
      null);
  }
  else
  {
    option_window.focus();
  }
}

/** Check if the option window is currently displayed
 *
 * @returns {boolean} true if the option window is currently displayed
 */
function option_window_displayed()
{
  return WindowMediator.getMostRecentWindow("inforssOption") != null;
}

/** Check if we should overwrite current tab rather than opening a new one
 *
 * @param {Object} window - the window in which you're interested.
 *
 * @returns {boolean} true if the current window contains a single empty tab
 */
function should_reuse_current_tab(window)
{
  const browser = window.gBrowser;
  return browser.browsers.length == 1 &&
         (browser.currentURI == null ||
          ((browser.currentURI.spec == "" ||
            browser.currentURI.spec == "about:blank") &&
           ! browser.selectedBrowser.webProgress.isLoadingDocument));
}

/** get the password for a user at a website
 *
 * @param {string} url - website url
 * @param {string} user - id of user
 *
 * @returns {string} password - might be an empty string
 */
function read_password(url, user)
{
  // Find users for the given parameters
  const logins = LoginManager.findLogins({}, url, 'User Registration', {});
  // Find user from returned array of nsILoginInfo objects
  for (let login of logins)
  {
    if (login.username == user)
    {
      return login.password;
    }
  }
  return "";
}

/** Record username and password for a website
 *
 * @param {string} url - website url
 * @param {string} user - id of user
 * @param {string} password - user's password
 *
 * @returns {string} password - might be an empty string
 */
function store_password(url, user, password)
{
  const loginInfo = new LoginInfo(url,
                                  'User Registration',
                                  null,
                                  user,
                                  password,
                                  "",
                                  "");
  try
  {
    LoginManager.removeLogin(loginInfo);
  }
  catch (err)
  {
    /* Do nothing - it's more than possible an exception will be thrown */
  }
  LoginManager.addLogin(loginInfo);
}

/** A wrapper for event listeners that catches and logs the exception
 * Used mainly because the only information you get in the console is the
 * exception text which is next to useless.
 *
 * @param {Function} func - function to call
 * @param {Object} params - extra params to bind
 *
 * @returns {Function} something that can be called
 */
function event_binder(func, ...params)
{
  if (func === undefined)
  {
    throw new Error("Attempting to bind undefined function");
  }
  return (...args) =>
  {
    try
    {
      func.bind(...params)(...args);
    }
    catch (err)
    {
      debug(err);
    }
  };
}

/** Add event listeners taking care of binding
 *
 * @param {Object} object - the class to which to bind all the listeners
 * @param {Document} document - the dom to which to listener
 * @param {Array} listeners - the listeners to add. This is an array of arrays,
 *                            element 0: The node id
 *                            element 1: The event to listen for
 *                            element 2: method to call. This will be bound to
 *                            the object
 *
 * @returns {Array} A list of event handlers to pass to remove_event_listeners
 */
function add_event_listeners(object, document, ...listeners)
{
  const to_remove = [];
  for (let listener of listeners)
  {
    const node = typeof listener[0] == 'string' ?
      document.getElementById("inforss." + listener[0]) :
      listener[0];
    const event = listener[1];
    /*jshint -W083*/
    const method = event_binder(listener[2], object);
    /*jshint -W083*/
    node.addEventListener(event, method);
    to_remove.push({ node, event, method });
  }
  return to_remove;
}

/** The counterpart to add_event_listeners, which can be called to deregister
 * all the registered event listeners
 *
 * @param {Array} listeners - result of calling add_event_listeners
 */
function remove_event_listeners(listeners)
{
  for (let listener of listeners)
  {
    listener.node.removeEventListener(listener.event, listener.method);
  }
}

<commit_msg>Fix typo messing up login manager<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is infoRSS.
 *
 * The Initial Developer of the Original Code is
 *   Didier Ernotte <didier@ernotte.com>.
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Didier Ernotte <didier@ernotte.com>.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
//------------------------------------------------------------------------------
// inforss_Utils
// Author : Tom Tanner 2017
//------------------------------------------------------------------------------
/* jshint globalstrict: true */
/* eslint-disable strict */
"use strict";

//This module provides assorted utilities

/* exported EXPORTED_SYMBOLS */
const EXPORTED_SYMBOLS = [
  "replace_without_children", /* exported replace_without_children */
  "remove_all_children", /* exported remove_all_children */
  "make_URI", /* exported make_URI */
  "htmlFormatConvert", /* exported htmlFormatConvert */
  "format_as_hh_mm_ss", /* exported format_as_hh_mm_ss */
  "open_option_window", /* exported open_option_window */
  "option_window_displayed", /* exported option_window_displayed */
  "should_reuse_current_tab", /* exported should_reuse_current_tab */
  "read_password", /* exported read_password */
  "store_password", /* exported store_password */
  "event_binder", /* exported event_binder */
  "add_event_listeners", /* exported add_event_listeners */
  "remove_event_listeners", /* exported remove_event_listeners */
];

const { debug } = Components.utils.import(
  "chrome://inforss/content/modules/inforss_Debug.jsm",
  {}
);

//const { console } = Components.utils.import(
//  "resource://gre/modules/Console.jsm",
//  {}
//);

const IoService = Components.classes[
  "@mozilla.org/network/io-service;1"].getService(
  Components.interfaces.nsIIOService);

const FormatConverter = Components.Constructor(
  "@mozilla.org/widget/htmlformatconverter;1",
  "nsIFormatConverter"
);

const WindowMediator = Components.classes[
  "@mozilla.org/appshell/window-mediator;1"].getService(
  Components.interfaces.nsIWindowMediator);

const WindowWatcher = Components.classes[
  "@mozilla.org/embedcomp/window-watcher;1"].getService(
  Components.interfaces.nsIWindowWatcher);

const SupportsString = Components.Constructor(
  "@mozilla.org/supports-string;1",
  "nsISupportsString"
);

const LoginManager = Components.classes[
  "@mozilla.org/login-manager;1"].getService(
  Components.interfaces.nsILoginManager);

const LoginInfo = Components.Constructor(
  "@mozilla.org/login-manager/loginInfo;1",
  Components.interfaces.nsILoginInfo,
  "init");

const As_HH_MM_SS = new Intl.DateTimeFormat(
  [],
  { hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false }
);

//------------------------------------------------------------------------------
/** Removes all the children of a node
 *
 * This is the most performant way of removing all the children of a node.
 * However, it doesn't seem to work well if the GUI already has its hands on the
 * node in question.
 *
 * @param {Object} node - original node
 *
 * @returns {Object} new node
 */
function replace_without_children(node)
{
  const new_node = node.cloneNode(false);
  node.parentNode.replaceChild(new_node, node);
  return new_node;
}

//------------------------------------------------------------------------------
function remove_all_children(node)
{
  while (node.lastChild != null)
  {
    node.removeChild(node.lastChild);
  }
}

/** Make a URI from a string
 *
 * @param {string} url - url to turn into a URI
 *
 * @returns {URI} URI object
 */
function make_URI(url)
{
  return IoService.newURI(url);
}

//FIXME the only place that passes extra parameters is nntp feed. Given that,
//perhaps we should drop all the parameters and give that its own function.
/** HTML string conversion
 *
 * @param {string} str - string to convert
 * @param {boolean} keep - keep < and > if set
 * @param {string} mimeTypeFrom - mime type of string (defaults to text/html)
 * @param {string} mimeTypeTo - mime type to convert to (defaults to
 *                 text/unicode
 *
 * @returns {string} converted string
 *
 */
function htmlFormatConvert(str, keep, mimeTypeFrom, mimeTypeTo)
{
  if (str == null)
  {
    return ""; //Seriously - this happens
  }

  let convertedString = null;

  //This is called from inforssNntp with keep false, converting from plain to
  //html. Arguably it should have its own method.
  if (keep == null)
  {
    keep = true;
  }

  if (mimeTypeFrom == null)
  {
    mimeTypeFrom = "text/html";
  }

  if (mimeTypeTo == null)
  {
    mimeTypeTo = "text/unicode";
  }

  if (keep)
  {
    str = str.replace(/</gi, "__LT__");
    str = str.replace(/>/gi, "__GT__");
  }

  const fromString = new SupportsString();
  fromString.data = str;
  let toString = { value: null };

  try
  {
    //This API is almost completely undocumented, so I've no idea how to rework
    //it it into something useful.
    const converter = new FormatConverter();
    converter.convert(mimeTypeFrom,
                      fromString,
                      fromString.toString().length,
                      mimeTypeTo,
                      toString,
                      {});
    if (toString.value)
    {
      toString = toString.value.QueryInterface(
        Components.interfaces.nsISupportsString);
      convertedString = toString.toString();
      if (keep)
      {
        convertedString = convertedString.replace(/__LT__/gi, "<");
        convertedString = convertedString.replace(/__GT__/gi, ">");
      }
    }
    else
    {
      convertedString = str;
    }
  }
  catch (err)
  {
    convertedString = str;
  }

  return convertedString;
}

/** Convert time to hh:mm:ss string
 *
 * @param {Date} date - time which we want to convert
 *
 * @returns {str} hh:mm:ss string in local time
 */
function format_as_hh_mm_ss(date)
{
  return As_HH_MM_SS.format(date);
}

/** Open or focus the option window */
function open_option_window()
{
  const option_window = WindowMediator.getMostRecentWindow("inforssOption");
  if (option_window == null)
  {
    WindowWatcher.openWindow(
      null,
      "chrome://inforss/content/inforssOption.xul",
      "_blank",
      "chrome,centerscreen,resizable=yes,dialog=no",
      null);
  }
  else
  {
    option_window.focus();
  }
}

/** Check if the option window is currently displayed
 *
 * @returns {boolean} true if the option window is currently displayed
 */
function option_window_displayed()
{
  return WindowMediator.getMostRecentWindow("inforssOption") != null;
}

/** Check if we should overwrite current tab rather than opening a new one
 *
 * @param {Object} window - the window in which you're interested.
 *
 * @returns {boolean} true if the current window contains a single empty tab
 */
function should_reuse_current_tab(window)
{
  const browser = window.gBrowser;
  return browser.browsers.length == 1 &&
         (browser.currentURI == null ||
          ((browser.currentURI.spec == "" ||
            browser.currentURI.spec == "about:blank") &&
           ! browser.selectedBrowser.webProgress.isLoadingDocument));
}

/** get the password for a user at a website
 *
 * @param {string} url - website url
 * @param {string} user - id of user
 *
 * @returns {string} password - might be an empty string
 */
function read_password(url, user)
{
  // Find users for the given parameters
  const logins = LoginManager.findLogins({}, url, 'User Registration', "", {});
  for (let login of logins)
  {
    if (login.username == user)
    {
      return login.password;
    }
  }
  return "";
}

/** Record username and password for a website
 *
 * @param {string} url - website url
 * @param {string} user - id of user
 * @param {string} password - user's password
 *
 * @returns {string} password - might be an empty string
 */
function store_password(url, user, password)
{
  const loginInfo = new LoginInfo(url,
                                  'User Registration',
                                  null,
                                  user,
                                  password,
                                  "",
                                  "");
  try
  {
    LoginManager.removeLogin(loginInfo);
  }
  catch (err)
  {
    /* Do nothing - it's more than possible an exception will be thrown */
  }
  LoginManager.addLogin(loginInfo);
}

/** A wrapper for event listeners that catches and logs the exception
 * Used mainly because the only information you get in the console is the
 * exception text which is next to useless.
 *
 * @param {Function} func - function to call
 * @param {Object} params - extra params to bind
 *
 * @returns {Function} something that can be called
 */
function event_binder(func, ...params)
{
  if (func === undefined)
  {
    throw new Error("Attempting to bind undefined function");
  }
  return (...args) =>
  {
    try
    {
      func.bind(...params)(...args);
    }
    catch (err)
    {
      debug(err);
    }
  };
}

/** Add event listeners taking care of binding
 *
 * @param {Object} object - the class to which to bind all the listeners
 * @param {Document} document - the dom to which to listener
 * @param {Array} listeners - the listeners to add. This is an array of arrays,
 *                            element 0: The node id
 *                            element 1: The event to listen for
 *                            element 2: method to call. This will be bound to
 *                            the object
 *
 * @returns {Array} A list of event handlers to pass to remove_event_listeners
 */
function add_event_listeners(object, document, ...listeners)
{
  const to_remove = [];
  for (let listener of listeners)
  {
    const node = typeof listener[0] == 'string' ?
      document.getElementById("inforss." + listener[0]) :
      listener[0];
    const event = listener[1];
    /*jshint -W083*/
    const method = event_binder(listener[2], object);
    /*jshint -W083*/
    node.addEventListener(event, method);
    to_remove.push({ node, event, method });
  }
  return to_remove;
}

/** The counterpart to add_event_listeners, which can be called to deregister
 * all the registered event listeners
 *
 * @param {Array} listeners - result of calling add_event_listeners
 */
function remove_event_listeners(listeners)
{
  for (let listener of listeners)
  {
    listener.node.removeEventListener(listener.event, listener.method);
  }
}

<|endoftext|>


<commit_before>//
// Provides interface logic for the crowdfunding payment form
// Depends on Stripe Checkout
//

var form = '.crowdfund-form';
var amount = 'input[name=amount]';
var button = '.crowdfund-form #crowdfund-button';
var prettyInput = 'input[name=pretty-input]';

// Stripe (should figure out how to divorce this from the file
function checkoutCrowdfund(event) {
    event.preventDefault();
    var a = $(amount).val();
    if (!a) {
        return false;
    }

    var b = $(button);
    var f = $(form);
    var key = b.data('key');
    var icon = b.data('icon');
    var email = b.data('email');
    var label = 'Contribute';
    var description = 'Contribute (' + $(prettyInput).val() + ')';
    var token = function(token) {
        $('a').click(function() { return false; });
        $('button').click(function() { return false; });
        f.append('<input type="hidden" name="token" value="' + token.id + '" />');
        f.append('<input type="hidden" name="email" value="' + token.email + '" />');
        f.submit();
    }
    StripeCheckout.open({
        key: key,
        image: icon,
        name: 'MuckRock',
        description: description,
        amount: a,
        bitcoin: true,
        email: email,
        panelLabel: label,
        token: token
    });

    return true;
}

function prettifyAmountInput(input, pretty) {
    // pretty_amount_input is used as a functional wrapper for the amount input field
    // progressive enhancement ftw!
    var prettyInputElement = '<input name="pretty-input" placeholder="$5.00" class="success" >';
    $(input).before(prettyInputElement);
    $(input).attr('hidden', true).hide();
    $(pretty).autoNumeric('init', {aSign:'$', pSign:'p'});
    function inputWrapper(input) {
        var value = $(input).autoNumeric('get') * 100;
        $(amount).attr('value', value);
    }
    $(pretty).change(function(e){
        inputWrapper(this);
    });
}

prettifyAmountInput(amount, prettyInput);
$(button).click(function(e){
    checkoutCrowdfund(e);
});
<commit_msg>adds ajax submission of crowdfund<commit_after>//
// Provides interface logic for the crowdfunding payment form
// Depends on Stripe Checkout
//

var form = '.crowdfund-form';
var amount = 'input[name=amount]';
var button = '.crowdfund-form #crowdfund-button';
var prettyInput = 'input[name=pretty-input]';

function submitForm() {

    var f = $(form);
    var formFields = f.serializeArray();
    var data = {};
    for (var i = 0; i < formFields.length; i++) {
      var field = formFields[i];
      data[field.name] = field.value;
    }
    f.ajaxStart(function(){
        this.parents('.crowdfund').addClass('pending');
    }).ajaxComplete(function(){
        this.parents('.crowdfund').removeClass('pending').addClass('complete');
    }).ajaxError(function(){
        this.parents('.crowdfund').removeClass('pending').addCLass('error');
    });
    $.ajax({
        url: f.attr('action'),
        type: 'post',
        data: data,
        success: function() {

        },
        dataType: 'json'
    });
}

// Stripe (should figure out how to divorce this from the file
function checkoutCrowdfund(event) {
    event.preventDefault();
    var a = $(amount).val();
    if (!a) {
        return false;
    }

    var b = $(button);
    var f = $(form);
    var key = b.data('key');
    var icon = b.data('icon');
    var email = b.data('email');
    var label = 'Contribute';
    var description = 'Contribute (' + $(prettyInput).val() + ')';
    var token = function(token) {
        f.append('<input type="hidden" name="token" value="' + token.id + '" />');
        f.append('<input type="hidden" name="email" value="' + token.email + '" />');
        submitForm();

    }
    StripeCheckout.open({
        key: key,
        image: icon,
        name: 'MuckRock',
        description: description,
        amount: a,
        bitcoin: true,
        email: email,
        panelLabel: label,
        token: token
    });

    return true;
}

function prettifyAmountInput(input, pretty) {
    // pretty_amount_input is used as a functional wrapper for the amount input field
    // progressive enhancement ftw!
    var prettyInputElement = '<input name="pretty-input" placeholder="$5.00" class="success" >';
    $(input).before(prettyInputElement);
    $(input).attr('hidden', true).hide();
    $(pretty).autoNumeric('init', {aSign:'$', pSign:'p'});
    function inputWrapper(input) {
        var value = $(input).autoNumeric('get') * 100;
        $(amount).attr('value', value);
    }
    $(pretty).change(function(e){
        inputWrapper(this);
    });
}

prettifyAmountInput(amount, prettyInput);
$(button).click(function(e){
    checkoutCrowdfund(e);
});
<|endoftext|>


<commit_before>const linebreaks = require('./utils/linebreaks');

module.exports = {
    'accessor-pairs': 'error',
    'array-bracket-spacing': [
        'error',
        'never'
    ],
    'arrow-body-style': 'error',
    'arrow-parens': 'error',
    'arrow-spacing': 'error',
    'block-scoped-var': 'error',
    'block-spacing': 'error',
    'brace-style': 'error',
    'callback-return': 'error',
    'camelcase': 'error',
    'comma-dangle': 'error',
    'comma-spacing': 'error',
    'comma-style': 'error',
    'complexity': [
        'error',
        4
    ],
    'computed-property-spacing': 'error',
    'consistent-return': 'error',
    'consistent-this': [
        'error',
        'self'
    ],
    'constructor-super': 'error',
    'curly': 'error',
    'default-case': 'error',
    'eol-last': 'error',
    'eqeqeq': [
        'error',
        'always'
    ],
    'for-direction': 'error',
    'func-call-spacing': 'error',
    'function-paren-newline': [
        'error',
        'multiline'
    ],
    'generator-star-spacing': 'error',
    'getter-return': 'error',
    'guard-for-in': 'error',
    'handle-callback-err': 'error',
    'indent': [
        'error',
        4,
        {
            SwitchCase: 1
        }
    ],
    'jsx-quotes': 'error',
    'key-spacing': 'error',
    'keyword-spacing': 'error',
    'linebreak-style': 'error',
    'lines-between-class-members': 'error',
    'max-depth': [
        'error',
        2
    ],
    'max-nested-callbacks': [
        'error',
        {
            max: 3
        }
    ],
    'max-params': [
        'error',
        {
            max: 3
        }
    ],
    'max-statements-per-line': 'error',
    'multiline-comment-style': 'error',
    'new-cap': 'error',
    'new-parens': 'error',
    'no-alert': 'error',
    'no-array-constructor': 'error',
    'no-bitwise': 'error',
    'no-buffer-constructor': 'error',
    'no-caller': 'error',
    'no-catch-shadow': 'error',
    'no-class-assign': 'error',
    'no-compare-neg-zero': 'error',
    'no-cond-assign': [
        'error',
        'always'
    ],
    'no-console': 'error',
    'no-const-assign': 'error',
    'no-constant-condition': [
        'error',
        {
            checkLoops: false
        }
    ],
    'no-continue': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-delete-var': 'error',
    'no-div-regex': 'error',
    'no-dupe-args': 'error',
    'no-dupe-class-members': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-duplicate-imports': [
        'error',
        {
            includeExports: true
        }
    ],
    'no-else-return': 'error',
    'no-empty-character-class': 'error',
    'no-empty-function': 'error',
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-ex-assign': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-extra-boolean-cast': 'error',
    'no-extra-label': 'error',
    'no-extra-parens': [
        'error',
        'all',
        {
            ignoreJSX: 'multi-line'
        }
    ],
    'no-extra-semi': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-global-assign': 'error',
    'no-implicit-coercion': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-inner-declarations': [
        'error',
        'both'
    ],
    'no-invalid-regexp': [
        'error',
        {
            allowConstructorFlags: [
                'u',
                'y'
            ]
        }
    ],
    'no-irregular-whitespace': 'error',
    'no-iterator': 'error',
    'no-label-var': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-lonely-if': 'error',
    'no-loop-func': 'error',
    'no-mixed-spaces-and-tabs': 'error',
    'no-multi-spaces': 'error',
    'no-multi-str': 'error',
    'no-multiple-empty-lines': [
        'error',
        {
            max: 1
        }
    ],
    'no-nested-ternary': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-object': 'error',
    'no-new-require': 'error',
    'no-new-symbol': 'error',
    'no-new-wrappers': 'error',
    'no-obj-calls': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': [
        'error',
        {
            props: true
        }
    ],
    'no-path-concat': 'error',
    'no-process-exit': 'error',
    'no-proto': 'error',
    'no-redeclare': [
        'error',
        {
            builtinGlobals: true
        }
    ],
    'no-restricted-globals': 'error',
    'no-return-assign': [
        'error',
        'always'
    ],
    'no-return-await': 'error',
    'no-script-url': 'error',
    'no-self-assign': [
        'error',
        {
            props: true
        }
    ],
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-shadow': 'error',
    'no-shadow-restricted-names': 'error',
    'no-sparse-arrays': 'error',
    'no-sync': 'error',
    'no-tabs': 'error',
    'no-template-curly-in-string': 'error',
    'no-this-before-super': 'error',
    'no-throw-literal': 'error',
    'no-trailing-spaces': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-unexpected-multiline': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unneeded-ternary': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'no-unsafe-negation': 'error',
    'no-unused-expressions': 'error',
    'no-unused-labels': 'error',
    'no-unused-vars': 'error',
    'no-use-before-define': 'error',
    'no-useless-call': 'error',
    'no-useless-computed-key': 'error',
    'no-useless-concat': 'error',
    'no-useless-constructor': 'error',
    'no-useless-escape': 'error',
    'no-useless-rename': 'error',
    'no-var': 'error',
    'no-void': 'error',
    'no-warning-comments': 'error',
    'no-whitespace-before-property': 'error',
    'no-with': 'error',
    'nonblock-statement-body-position': [
        'error',
        'below'
    ],
    'object-curly-spacing': 'error',
    'object-shorthand': 'error',
    'one-var': [
        'error',
        {
            const: 'never',
            let: 'always',
            var: 'always'
        }
    ],
    'one-var-declaration-per-line': [
        'error',
        'always'
    ],
    'padded-blocks': [
        'error',
        'never'
    ],
    'padding-line-between-statements': linebreaks,
    'prefer-const': 'error',
    'prefer-numeric-literals': 'error',
    'prefer-rest-params': 'error',
    'prefer-spread': 'error',
    'prefer-template': 'error',
    'quote-props': [
        'error',
        'as-needed',
        {
            numbers: true,
            unnecessary: false
        }
    ],
    'quotes': [
        'error',
        'single',
        {
            avoidEscape: true
        }
    ],
    'radix': [
        'error',
        'as-needed'
    ],
    'require-await': 'error',
    'require-yield': 'error',
    'rest-spread-spacing': 'error',
    'semi': 'error',
    'semi-spacing': [
        'error',
        {
            after: true,
            before: false
        }
    ],
    'semi-style': [
        'error',
        'last'
    ],
    'sort-keys': [
        'error',
        'asc',
        {
            caseSensitive: false,
            natural: true
        }
    ],
    'space-before-blocks': 'error',
    'space-before-function-paren': [
        'error',
        {
            anonymous: 'always',
            asyncArrow: 'always',
            named: 'never'
        }
    ],
    'space-in-parens': 'error',
    'space-infix-ops': 'error',
    'space-unary-ops': [
        'error',
        {
            nonwords: false,
            words: true
        }
    ],
    'spaced-comment': 'error',
    'strict': [
        'error',
        'never'
    ],
    'switch-colon-spacing': 'error',
    'symbol-description': 'error',
    'template-curly-spacing': 'error',
    'unicode-bom': 'error',
    'use-isnan': 'error',
    'valid-typeof': 'error',
    'vars-on-top': 'error',
    'wrap-iife': [
        'error',
        'any'
    ],
    'yield-star-spacing': [
        'error',
        'before'
    ],
    'yoda': [
        'error',
        'never'
    ]
};
<commit_msg>Removes `function-paren-newline`.<commit_after>const linebreaks = require('./utils/linebreaks');

module.exports = {
    'accessor-pairs': 'error',
    'array-bracket-spacing': [
        'error',
        'never'
    ],
    'arrow-body-style': 'error',
    'arrow-parens': 'error',
    'arrow-spacing': 'error',
    'block-scoped-var': 'error',
    'block-spacing': 'error',
    'brace-style': 'error',
    'callback-return': 'error',
    'camelcase': 'error',
    'comma-dangle': 'error',
    'comma-spacing': 'error',
    'comma-style': 'error',
    'complexity': [
        'error',
        4
    ],
    'computed-property-spacing': 'error',
    'consistent-return': 'error',
    'consistent-this': [
        'error',
        'self'
    ],
    'constructor-super': 'error',
    'curly': 'error',
    'default-case': 'error',
    'eol-last': 'error',
    'eqeqeq': [
        'error',
        'always'
    ],
    'for-direction': 'error',
    'func-call-spacing': 'error',
    'generator-star-spacing': 'error',
    'getter-return': 'error',
    'guard-for-in': 'error',
    'handle-callback-err': 'error',
    'indent': [
        'error',
        4,
        {
            SwitchCase: 1
        }
    ],
    'jsx-quotes': 'error',
    'key-spacing': 'error',
    'keyword-spacing': 'error',
    'linebreak-style': 'error',
    'lines-between-class-members': 'error',
    'max-depth': [
        'error',
        2
    ],
    'max-nested-callbacks': [
        'error',
        {
            max: 3
        }
    ],
    'max-params': [
        'error',
        {
            max: 3
        }
    ],
    'max-statements-per-line': 'error',
    'multiline-comment-style': 'error',
    'new-cap': 'error',
    'new-parens': 'error',
    'no-alert': 'error',
    'no-array-constructor': 'error',
    'no-bitwise': 'error',
    'no-buffer-constructor': 'error',
    'no-caller': 'error',
    'no-catch-shadow': 'error',
    'no-class-assign': 'error',
    'no-compare-neg-zero': 'error',
    'no-cond-assign': [
        'error',
        'always'
    ],
    'no-console': 'error',
    'no-const-assign': 'error',
    'no-constant-condition': [
        'error',
        {
            checkLoops: false
        }
    ],
    'no-continue': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-delete-var': 'error',
    'no-div-regex': 'error',
    'no-dupe-args': 'error',
    'no-dupe-class-members': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-duplicate-imports': [
        'error',
        {
            includeExports: true
        }
    ],
    'no-else-return': 'error',
    'no-empty-character-class': 'error',
    'no-empty-function': 'error',
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-ex-assign': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-extra-boolean-cast': 'error',
    'no-extra-label': 'error',
    'no-extra-parens': [
        'error',
        'all',
        {
            ignoreJSX: 'multi-line'
        }
    ],
    'no-extra-semi': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-global-assign': 'error',
    'no-implicit-coercion': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-inner-declarations': [
        'error',
        'both'
    ],
    'no-invalid-regexp': [
        'error',
        {
            allowConstructorFlags: [
                'u',
                'y'
            ]
        }
    ],
    'no-irregular-whitespace': 'error',
    'no-iterator': 'error',
    'no-label-var': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-lonely-if': 'error',
    'no-loop-func': 'error',
    'no-mixed-spaces-and-tabs': 'error',
    'no-multi-spaces': 'error',
    'no-multi-str': 'error',
    'no-multiple-empty-lines': [
        'error',
        {
            max: 1
        }
    ],
    'no-nested-ternary': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-object': 'error',
    'no-new-require': 'error',
    'no-new-symbol': 'error',
    'no-new-wrappers': 'error',
    'no-obj-calls': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': [
        'error',
        {
            props: true
        }
    ],
    'no-path-concat': 'error',
    'no-process-exit': 'error',
    'no-proto': 'error',
    'no-redeclare': [
        'error',
        {
            builtinGlobals: true
        }
    ],
    'no-restricted-globals': 'error',
    'no-return-assign': [
        'error',
        'always'
    ],
    'no-return-await': 'error',
    'no-script-url': 'error',
    'no-self-assign': [
        'error',
        {
            props: true
        }
    ],
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-shadow': 'error',
    'no-shadow-restricted-names': 'error',
    'no-sparse-arrays': 'error',
    'no-sync': 'error',
    'no-tabs': 'error',
    'no-template-curly-in-string': 'error',
    'no-this-before-super': 'error',
    'no-throw-literal': 'error',
    'no-trailing-spaces': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-unexpected-multiline': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unneeded-ternary': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'no-unsafe-negation': 'error',
    'no-unused-expressions': 'error',
    'no-unused-labels': 'error',
    'no-unused-vars': 'error',
    'no-use-before-define': 'error',
    'no-useless-call': 'error',
    'no-useless-computed-key': 'error',
    'no-useless-concat': 'error',
    'no-useless-constructor': 'error',
    'no-useless-escape': 'error',
    'no-useless-rename': 'error',
    'no-var': 'error',
    'no-void': 'error',
    'no-warning-comments': 'error',
    'no-whitespace-before-property': 'error',
    'no-with': 'error',
    'nonblock-statement-body-position': [
        'error',
        'below'
    ],
    'object-curly-spacing': 'error',
    'object-shorthand': 'error',
    'one-var': [
        'error',
        {
            const: 'never',
            let: 'always',
            var: 'always'
        }
    ],
    'one-var-declaration-per-line': [
        'error',
        'always'
    ],
    'padded-blocks': [
        'error',
        'never'
    ],
    'padding-line-between-statements': linebreaks,
    'prefer-const': 'error',
    'prefer-numeric-literals': 'error',
    'prefer-rest-params': 'error',
    'prefer-spread': 'error',
    'prefer-template': 'error',
    'quote-props': [
        'error',
        'as-needed',
        {
            numbers: true,
            unnecessary: false
        }
    ],
    'quotes': [
        'error',
        'single',
        {
            avoidEscape: true
        }
    ],
    'radix': [
        'error',
        'as-needed'
    ],
    'require-await': 'error',
    'require-yield': 'error',
    'rest-spread-spacing': 'error',
    'semi': 'error',
    'semi-spacing': [
        'error',
        {
            after: true,
            before: false
        }
    ],
    'semi-style': [
        'error',
        'last'
    ],
    'sort-keys': [
        'error',
        'asc',
        {
            caseSensitive: false,
            natural: true
        }
    ],
    'space-before-blocks': 'error',
    'space-before-function-paren': [
        'error',
        {
            anonymous: 'always',
            asyncArrow: 'always',
            named: 'never'
        }
    ],
    'space-in-parens': 'error',
    'space-infix-ops': 'error',
    'space-unary-ops': [
        'error',
        {
            nonwords: false,
            words: true
        }
    ],
    'spaced-comment': 'error',
    'strict': [
        'error',
        'never'
    ],
    'switch-colon-spacing': 'error',
    'symbol-description': 'error',
    'template-curly-spacing': 'error',
    'unicode-bom': 'error',
    'use-isnan': 'error',
    'valid-typeof': 'error',
    'vars-on-top': 'error',
    'wrap-iife': [
        'error',
        'any'
    ],
    'yield-star-spacing': [
        'error',
        'before'
    ],
    'yoda': [
        'error',
        'never'
    ]
};
<|endoftext|>