<commit_before>'use strict';

var bcrypt = require('bcrypt-nodejs'),
    Server = require('socket.io'),
    express = require('express'),
    http = require('http'),
    path = require('path'),
    mongo = require('mongojs');

var util = require('util');
var session = require('./session');
var _ = require('lodash');
var cors = require('cors');
var shortid = require('shortid');

var _validTokens = {};

function getDateForLog() {
    return new Date();
}

function throwErr (func) {
    return function(err, data) {
        if (err) {
            throw err;
        } else {
            func.call(null, data);
        }
    };
}

function validateScene (sceneData) {
    // convert _id so mongo recognizes it
    if (sceneData.hasOwnProperty('_id')) {
        sceneData._id = mongo.ObjectId(sceneData._id);
    }

    // add _ids to all mediaObjects
    if (sceneData.hasOwnProperty('scene')) {
        if (! Array.isArray(sceneData.scene) ) {
            throw new Error('"scene" property must be an array of objects');
        } else {
            sceneData.scene.forEach(function(mediaObject) {
                if (! mediaObject.hasOwnProperty('_id')) {
                    mediaObject._id = mongo.ObjectId();
                }
            });
        }
    }

    return sceneData;
}

function validateSceneGraph (sceneGraphData) {
    //convert _id so mongo recognizes it
    if (sceneGraphData.hasOwnProperty('_id')) {
        sceneGraphData._id = mongo.ObjectId(sceneGraphData._id);
    }

    //TODO most likely more detailed validation can occur

    return sceneGraphData;
}

function addApiCalls (hub, io, socket) {
    function idSearch (id) {
        return {_id: mongo.ObjectId(id)};
    }

    function _findScene (sceneId, cb) {

        console.log(getDateForLog() + " - hub.js - _findScene");

        return hub.db.mediaScenes.findOne(idSearch(sceneId), cb);
    }

    function _findSceneGraph(sceneGraphId, cb) {

        console.log(getDateForLog() + " - hub.js - _findSceneGraph");

        return hub.db.mediaSceneGraphs.findOne(idSearch(sceneGraphId), cb);
    }

    socket.on('listScenes', function(callback) {

        console.log(getDateForLog() + " - hub.js - listScenes groupID: " + socket.groupID);

        //AJF: if the groupID is 0 (admin) then list all scenes
        if(socket.groupID == 0)
            hub.db.mediaScenes.find({'$query': {}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        else
        {
            hub.db.mediaScenes.find({'$query': {_groupID: socket.groupID}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        }

    });

    socket.on('listSceneGraphs', function(callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");
        hub.db.mediaSceneGraphs.find({'$query': {}}, callback);

    });

    socket.on('saveScene', function(sceneData, callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");

        try {
            var data = validateScene(sceneData);

            console.log(getDateForLog() + " - hub.js - saveScene after validation: ", data);

			//AJF: sanity check to stop client side CTRL+Z bug blank scene reaching the db
			if(data.hasOwnProperty('themes') || data.hasOwnProperty('style') || data.hasOwnProperty('scene'))
			{
				console.log("Valid");

            //AJF: save the groupID acquired from the socket if the groupID isn't already set
            console.log(getDateForLog() + " - hub.js - saveScene data._groupID: " + data._groupID);

            if(!data._groupID) {
                console.log(getDateForLog() + " - hub.js - saveScene data._groupID not set so setting to: " + socket.groupID);
                data._groupID = socket.groupID;
            }

            hub.db.mediaScenes.save(data, function(err, scene) {
                io.to(scene._id.toString()).emit('sceneUpdate', scene);

                if (callback) {
                    callback(err, scene);
                }
            });
			}
        } catch(err) {
            if (callback) {
                callback(err.message);
            }
        }
    });

    socket.on('saveSceneGraph', function(sceneGraphData, callback) {
        try {
            console.log(getDateForLog() + " - hub.js - saveSceneGraph");

            var data = validateSceneGraph(sceneGraphData);

            hub.db.mediaSceneGraphs.save(data, function(err, sceneGraph) {
                io.to(sceneGraph._id.toString()).emit('sceneGraphUpdate', sceneGraph);

                if (callback) {
                    callback(err, sceneGraph);
                }
            });

        } catch(err) {
            if(callback) {
                callback(err.message);
            }
        }
    });

    socket.on('loadScene', _findScene);

    socket.on('loadSceneGraph', _findSceneGraph);

    socket.on('loadSceneByName', function(name, callback) {

        console.log(getDateForLog() + " - hub.js - loadSceneByName");

        hub.db.mediaScenes.findOne({name: name}, callback);
    });

    socket.on('deleteScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - deleteScene");

        hub.db.mediaScenes.remove(idSearch(sceneId), function(err) {
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('deleteSceneGraph', function(sceneGraphId, callback){

        console.log(getDateForLog() + " - hub.js - deleteSceneGraph");

        hub.db.mediaSceneGraphs.remove(idSearch(sceneGraphId), function(err){
            if(callback) {
                callback(err);
            }
        });
    });

    socket.on('subScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - subScene");

        _findScene(sceneId, function(err, scene) {
            socket.join(sceneId);

            if (callback) {
                callback(err, scene);
            }
        });
    });

    socket.on('unsubScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - unsubScene");

        _findScene(sceneId, function(err, scene) {
            socket.leave(sceneId);
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('sendCommand', function(roomId, commandName, commandValue) {

        console.log(getDateForLog() + " - hub.js - sendCommand: ", {
            roomId: roomId,
            commandName: commandName,
            commandValue: commandValue
        });

        io.to(roomId).emit('command', {name: commandName, value: commandValue});
    });

    socket.on('register', function(roomId) {

        roomId = roomId.replace("/#", "");

        console.log(getDateForLog() + " - hub.js - REGISTER TO ROOM: ", roomId);

        socket.join(roomId);
    });
}

var Hub = function(config) {
    this.config = config;
    this.db = mongo.connect(config.mongo, ['mediaScenes', 'sessions', 'mediaSceneGraphs']);
    session.setClient(this.db);
};

Hub.prototype.listen = function(callback) {
    var self = this,
        app = express(),
        server = http.Server(app),
        io = new Server(server);

    this.server = server;

    app.use(cors());

    // require a valid session token for all api calls
    var validateSession =  function(req, res, next) {
        session.find(req.query.token, function(err, data) {
            if (err || ! data) {
                res.sendStatus(401);
            } else {
                next();
            }
        });
    };

    // allow cross origin requests
    io.set('origins', '*:*');
    io.sockets.on('connection', function (socket) {
        var disconnectTimer = setTimeout(function() {
            socket.disconnect();
        }, 10000);

        socket.on('auth', function (creds, callback) {

            function succeed (record) {

                //AJF: set the groupID on the socket to be used in further local calls

                //AJF: set the groupID on the socket to be used in further calls

                socket.groupID = record._groupID;
                addApiCalls(self, io, socket);
                clearTimeout(disconnectTimer);
                var roomId = shortid.generate(); // APEP: generate a user friendly shortid for roomID for graph and player to communicate
                callback(null, record._id.toString(), roomId, record._groupID.toString());//AJF: try to return the groupID...
            }

            function fail (msg) {
                callback(msg);
                socket.disconnect();
            }

            if (creds.hasOwnProperty('password') && creds.password && creds.password !== '') {
                //AJF: Compares the passwords and determines what group the user logging into belongs to
                if ( bcrypt.compareSync(creds.password, self.config.secret) ) {
                    session.create(0, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_1)) {
                    session.create(1, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_2)) {
                    session.create(2, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_101)) {
                    session.create(101, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_102)) {
                    session.create(102, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_103)) {
                    session.create(103, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_104)) {
                    session.create(104, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_105)) {
                    session.create(105, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_106)) {
                    session.create(106, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_107)) {
                    session.create(107, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_108)) {
                    session.create(108, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_109)) {
                    session.create(109, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_110)) {
                    session.create(110, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_111)) {
                    session.create(111, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_112)) {
                    session.create(112, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_113)) {
                    session.create(113, throwErr(succeed));
                } else {
                    fail('Invalid Password');
                }

            } else if (creds.hasOwnProperty('token') && creds.token && creds.token !== '') {
                console.log("Finding session via token");
                session.find(creds.token, function(err, data) {
                        if (data) {
                            succeed(data);
                        } else {
                            fail('Invalid Token');
                        }
                    });
            } else {
                fail('Password must be provided');
            }
        });

    });

    server.listen(self.config.port, callback);
};

Hub.prototype.close = function(cb) {
    this.server.close(cb);
};

module.exports = {
    createHub: function(mongoUrl) {
        return new Hub(mongoUrl);
    }
};
<commit_msg>usage of the new secrets<commit_after>'use strict';

var bcrypt = require('bcrypt-nodejs'),
    Server = require('socket.io'),
    express = require('express'),
    http = require('http'),
    path = require('path'),
    mongo = require('mongojs');

var util = require('util');
var session = require('./session');
var _ = require('lodash');
var cors = require('cors');
var shortid = require('shortid');

var _validTokens = {};

function getDateForLog() {
    return new Date();
}

function throwErr (func) {
    return function(err, data) {
        if (err) {
            throw err;
        } else {
            func.call(null, data);
        }
    };
}

function validateScene (sceneData) {
    // convert _id so mongo recognizes it
    if (sceneData.hasOwnProperty('_id')) {
        sceneData._id = mongo.ObjectId(sceneData._id);
    }

    // add _ids to all mediaObjects
    if (sceneData.hasOwnProperty('scene')) {
        if (! Array.isArray(sceneData.scene) ) {
            throw new Error('"scene" property must be an array of objects');
        } else {
            sceneData.scene.forEach(function(mediaObject) {
                if (! mediaObject.hasOwnProperty('_id')) {
                    mediaObject._id = mongo.ObjectId();
                }
            });
        }
    }

    return sceneData;
}

function validateSceneGraph (sceneGraphData) {
    //convert _id so mongo recognizes it
    if (sceneGraphData.hasOwnProperty('_id')) {
        sceneGraphData._id = mongo.ObjectId(sceneGraphData._id);
    }

    //TODO most likely more detailed validation can occur

    return sceneGraphData;
}

function addApiCalls (hub, io, socket) {
    function idSearch (id) {
        return {_id: mongo.ObjectId(id)};
    }

    function _findScene (sceneId, cb) {

        console.log(getDateForLog() + " - hub.js - _findScene");

        return hub.db.mediaScenes.findOne(idSearch(sceneId), cb);
    }

    function _findSceneGraph(sceneGraphId, cb) {

        console.log(getDateForLog() + " - hub.js - _findSceneGraph");

        return hub.db.mediaSceneGraphs.findOne(idSearch(sceneGraphId), cb);
    }

    socket.on('listScenes', function(callback) {

        console.log(getDateForLog() + " - hub.js - listScenes groupID: " + socket.groupID);

        //AJF: if the groupID is 0 (admin) then list all scenes
        if(socket.groupID == 0)
            hub.db.mediaScenes.find({'$query': {}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        else
        {
            hub.db.mediaScenes.find({'$query': {_groupID: socket.groupID}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        }

    });

    socket.on('listSceneGraphs', function(callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");
        hub.db.mediaSceneGraphs.find({'$query': {}}, callback);

    });

    socket.on('saveScene', function(sceneData, callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");

        try {
            var data = validateScene(sceneData);

            console.log(getDateForLog() + " - hub.js - saveScene after validation: ", data);

			//AJF: sanity check to stop client side CTRL+Z bug blank scene reaching the db
			if(data.hasOwnProperty('themes') || data.hasOwnProperty('style') || data.hasOwnProperty('scene'))
			{
				console.log("Valid");

            //AJF: save the groupID acquired from the socket if the groupID isn't already set
            console.log(getDateForLog() + " - hub.js - saveScene data._groupID: " + data._groupID);

            if(!data._groupID) {
                console.log(getDateForLog() + " - hub.js - saveScene data._groupID not set so setting to: " + socket.groupID);
                data._groupID = socket.groupID;
            }

            hub.db.mediaScenes.save(data, function(err, scene) {
                io.to(scene._id.toString()).emit('sceneUpdate', scene);

                if (callback) {
                    callback(err, scene);
                }
            });
			}
        } catch(err) {
            if (callback) {
                callback(err.message);
            }
        }
    });

    socket.on('saveSceneGraph', function(sceneGraphData, callback) {
        try {
            console.log(getDateForLog() + " - hub.js - saveSceneGraph");

            var data = validateSceneGraph(sceneGraphData);

            hub.db.mediaSceneGraphs.save(data, function(err, sceneGraph) {
                io.to(sceneGraph._id.toString()).emit('sceneGraphUpdate', sceneGraph);

                if (callback) {
                    callback(err, sceneGraph);
                }
            });

        } catch(err) {
            if(callback) {
                callback(err.message);
            }
        }
    });

    socket.on('loadScene', _findScene);

    socket.on('loadSceneGraph', _findSceneGraph);

    socket.on('loadSceneByName', function(name, callback) {

        console.log(getDateForLog() + " - hub.js - loadSceneByName");

        hub.db.mediaScenes.findOne({name: name}, callback);
    });

    socket.on('deleteScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - deleteScene");

        hub.db.mediaScenes.remove(idSearch(sceneId), function(err) {
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('deleteSceneGraph', function(sceneGraphId, callback){

        console.log(getDateForLog() + " - hub.js - deleteSceneGraph");

        hub.db.mediaSceneGraphs.remove(idSearch(sceneGraphId), function(err){
            if(callback) {
                callback(err);
            }
        });
    });

    socket.on('subScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - subScene");

        _findScene(sceneId, function(err, scene) {
            socket.join(sceneId);

            if (callback) {
                callback(err, scene);
            }
        });
    });

    socket.on('unsubScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - unsubScene");

        _findScene(sceneId, function(err, scene) {
            socket.leave(sceneId);
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('sendCommand', function(roomId, commandName, commandValue) {

        console.log(getDateForLog() + " - hub.js - sendCommand: ", {
            roomId: roomId,
            commandName: commandName,
            commandValue: commandValue
        });

        io.to(roomId).emit('command', {name: commandName, value: commandValue});
    });

    socket.on('register', function(roomId) {

        roomId = roomId.replace("/#", "");

        console.log(getDateForLog() + " - hub.js - REGISTER TO ROOM: ", roomId);

        socket.join(roomId);
    });
}

var Hub = function(config) {
    this.config = config;
    this.db = mongo.connect(config.mongo, ['mediaScenes', 'sessions', 'mediaSceneGraphs']);
    session.setClient(this.db);
};

Hub.prototype.listen = function(callback) {
    var self = this,
        app = express(),
        server = http.Server(app),
        io = new Server(server);

    this.server = server;

    app.use(cors());

    // require a valid session token for all api calls
    var validateSession =  function(req, res, next) {
        session.find(req.query.token, function(err, data) {
            if (err || ! data) {
                res.sendStatus(401);
            } else {
                next();
            }
        });
    };

    // allow cross origin requests
    io.set('origins', '*:*');
    io.sockets.on('connection', function (socket) {
        var disconnectTimer = setTimeout(function() {
            socket.disconnect();
        }, 10000);

        socket.on('auth', function (creds, callback) {

            function succeed (record) {

                //AJF: set the groupID on the socket to be used in further local calls

                //AJF: set the groupID on the socket to be used in further calls

                socket.groupID = record._groupID;
                addApiCalls(self, io, socket);
                clearTimeout(disconnectTimer);
                var roomId = shortid.generate(); // APEP: generate a user friendly shortid for roomID for graph and player to communicate
                callback(null, record._id.toString(), roomId, record._groupID.toString());//AJF: try to return the groupID...
            }

            function fail (msg) {
                callback(msg);
                socket.disconnect();
            }

            if (creds.hasOwnProperty('password') && creds.password && creds.password !== '') {
                //AJF: Compares the passwords and determines what group the user logging into belongs to
                if ( bcrypt.compareSync(creds.password, self.config.secret) ) {
                    session.create(0, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_1)) {
                    session.create(1, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_2)) {
                    session.create(2, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_101)) {
                    session.create(101, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_102)) {
                    session.create(102, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_103)) {
                    session.create(103, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_104)) {
                    session.create(104, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_105)) {
                    session.create(105, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_106)) {
                    session.create(106, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_107)) {
                    session.create(107, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_108)) {
                    session.create(108, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_109)) {
                    session.create(109, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_110)) {
                    session.create(110, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_111)) {
                    session.create(111, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_112)) {
                    session.create(112, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_113)) {
                    session.create(113, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_114)) {
                    session.create(111, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_115)) {
                    session.create(112, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_116)) {
                    session.create(113, throwErr(succeed));
                } else {
                    fail('Invalid Password');
                }

            } else if (creds.hasOwnProperty('token') && creds.token && creds.token !== '') {
                console.log("Finding session via token");
                session.find(creds.token, function(err, data) {
                        if (data) {
                            succeed(data);
                        } else {
                            fail('Invalid Token');
                        }
                    });
            } else {
                fail('Password must be provided');
            }
        });

    });

    server.listen(self.config.port, callback);
};

Hub.prototype.close = function(cb) {
    this.server.close(cb);
};

module.exports = {
    createHub: function(mongoUrl) {
        return new Hub(mongoUrl);
    }
};
<|endoftext|>


<commit_before>var ripple = require('ripple-lib');
/**
 *  opts
 *    remote
 *    tx_hash
 */
module.exports.getTx = function(opts, callback) {

  var remote = opts.remote,
    tx_hash = opts.tx_hash;

  ensureRemoteConnected(remote, function(err, connected){
    if (err) {
      callback(err);
      return;
    }

    remote.requestTx(tx_hash, function(err, tx){
      if (err) {
        callback(err);
        return;
      }

      // Get container ledger to find close_time
      remote.requestLedger(tx.inLedger, function(err, res){
        if (err) {
          callback(err);
          return;
        }

        tx.close_time_unix = ripple.utils.toTimestamp(res.ledger.close_time);

        callback(null, tx);

      });

    });

  });

};

/*
 *  opts
 *    remote:
 *    src_address: '...',
 *    secret: '...',
 *    tx_json: {...}
 */
module.exports.submitTx = function(opts, callback) {

  var remote = opts.remote,
    src_address = opts.src_address,
    secret = opts.secret,
    tx = opts.tx_json || opts.tx || opts,
    initial_hash;

  ensureRemoteConnected(remote, function(err, connected){
    if (err) {
      callback(err);
      return;
    }

    // Set secret
    try {
      remote.set_secret(src_address, secret);
    } catch (e) {
      callback(new Error('Invalid parameter: secret. Must provide valid Ripple account secret to sign transaction'));
      return;
    }

    // Determine if tx is already a ripple-lib Transaction or just json
    if (tx.constructor.name === 'Transaction') {

      tx.remote = remote;

    } else if (tx.constructor.name === 'Object') {

      // Special case for handling XRP given as an object
      // ripple-lib doesn't like it so pass it as a string
      Object.keys(tx).forEach(function(key){
        if (typeof tx[key] === 'object' && tx[key].currency === 'XRP' && !tx[key].issuer) {
          tx[key] = '' + tx[key].value + 'XRP';
        }
      });

      // Create transaction
      try {
        tx = remote.transaction(opts.tx);
      } catch (e) {
        callback(e);
        return;
      }
    }

    // Setup event handlers

    tx.once('error', callback);

    // Once tx has been submitted to rippled, send the initial hash
    // back to the user and save the entry into the db
    tx.once('proposed', function(proposed) {

      initial_hash = proposed.tx_json.hash;

      tx.removeListener('error', callback);

      // save to db
      OutgoingTx
        .create({
          initial_hash: initial_hash,
          submitted_at_ledger: remote._ledger_current_index - 1,
          src_address: src_address,
          tx_type: tx.type || tx.tx_json.TransactionType,
          tx_state: 'submitted'
        })
        .error(function(err){
          console.log('error updated initial OutgoingTx record: ' + err);
          callback(err);
        })
        .success(function(entry){
          // Send initial hash back to user
          callback(null, initial_hash);
        });

      });

    // Once the tx has been confirmed in the ledger, update the db entry
    // to associate the initial_hash with the final tx_hash
    tx.once('success', function(confirmed_tx) {

      // console.log('success: ' + JSON.stringify(confirmed_tx));

      // Update db entry with tx_hash and tx_result
      OutgoingTx
        .update({
          // UPDATE
          tx_hash: confirmed_tx.transaction.hash,
          tx_result: confirmed_tx.meta.TransactionResult
        }, {
          // WHERE
          initial_hash: initial_hash
        })
        .error(function(err){
          console.log('error updated OutgoingTx record: ' + err);
        })
        .success(function(){
          // console.log('update db entry for initial_hash: ' + initial_hash + ' with tx_hash: ' + confirmed_tx.transaction.hash);
        });

    });

    tx.submit();

  });

};

/* HELPER FUNCTIONS */

function ensureRemoteConnected(remote, callback) {

  if (!remote || typeof remote !== 'object') {
    callback(new Error('invalidRemote'));
    return;
  }

  if (remote._connected === true) {
    callback(null, true);
  } else {
    remote.connect();
    remote.once('ledger_closed', function(){
      callback(null, true);
    });
  }

}
<commit_msg>[CHORE] Refactored lib to inject model as dependency instead of using require<commit_after>var ripple = require('ripple-lib');
/**
 *  opts
 *    remote
 *    tx_hash
 */
module.exports.getTx = function(opts, callback) {

  var remote = opts.remote,
    tx_hash = opts.tx_hash;

  ensureRemoteConnected(remote, function(err, connected){
    if (err) {
      callback(err);
      return;
    }

    remote.requestTx(tx_hash, function(err, tx){
      if (err) {
        callback(err);
        return;
      }

      // Get container ledger to find close_time
      remote.requestLedger(tx.inLedger, function(err, res){
        if (err) {
          callback(err);
          return;
        }

        tx.close_time_unix = ripple.utils.toTimestamp(res.ledger.close_time);

        callback(null, tx);

      });

    });

  });

};

/*
 *  opts
 *    remote:
 *    src_address: '...',
 *    secret: '...',
 *    tx_json: {...}
 */
module.exports.submitTx = function(opts, callback) {

  var remote = opts.remote,
    OutgoingTx = opts.OutgoingTx,
    src_address = opts.src_address,
    secret = opts.secret,
    tx = opts.tx_json || opts.tx || opts,
    initial_hash;

  ensureRemoteConnected(remote, function(err, connected){
    if (err) {
      callback(err);
      return;
    }

    // Set secret
    try {
      remote.set_secret(src_address, secret);
    } catch (e) {
      callback(new Error('Invalid parameter: secret. Must provide valid Ripple account secret to sign transaction'));
      return;
    }

    // Determine if tx is already a ripple-lib Transaction or just json
    if (tx.constructor.name === 'Transaction') {

      tx.remote = remote;

    } else if (tx.constructor.name === 'Object') {

      // Special case for handling XRP given as an object
      // ripple-lib doesn't like it so pass it as a string
      Object.keys(tx).forEach(function(key){
        if (typeof tx[key] === 'object' && tx[key].currency === 'XRP' && !tx[key].issuer) {
          tx[key] = '' + tx[key].value + 'XRP';
        }
      });

      // Create transaction
      try {
        tx = remote.transaction(opts.tx);
      } catch (e) {
        callback(e);
        return;
      }
    }

    // Setup event handlers

    tx.once('error', callback);

    // Once tx has been submitted to rippled, send the initial hash
    // back to the user and save the entry into the db
    tx.once('proposed', function(proposed) {

      initial_hash = proposed.tx_json.hash;

      tx.removeListener('error', callback);

      // save to db
      if (OutgoingTx) {
        OutgoingTx
          .create({
            initial_hash: initial_hash,
            submitted_at_ledger: remote._ledger_current_index - 1,
            src_address: src_address,
            tx_type: tx.type || tx.tx_json.TransactionType,
            tx_state: 'submitted'
          })
          .error(function(err){
            console.log('error updated initial OutgoingTx record: ' + err);
            callback(err);
          })
          .success(function(entry){
            // Send initial hash back to user
            callback(null, initial_hash);
          });
      }

    });

    // Once the tx has been confirmed in the ledger, update the db entry
    // to associate the initial_hash with the final tx_hash
    tx.once('success', function(confirmed_tx) {

      // console.log('success: ' + JSON.stringify(confirmed_tx));

      // Update db entry with tx_hash and tx_result
      if (OutgoingTx) {
        OutgoingTx
          .update({
            // UPDATE
            tx_hash: confirmed_tx.transaction.hash,
            tx_result: confirmed_tx.meta.TransactionResult
          }, {
            // WHERE
            initial_hash: initial_hash
          })
          .error(function(err){
            console.log('error updated OutgoingTx record: ' + err);
          })
          .success(function(){
            // console.log('update db entry for initial_hash: ' + initial_hash + ' with tx_hash: ' + confirmed_tx.transaction.hash);
          });
      }

    });

    tx.submit();

  });

};

/* HELPER FUNCTIONS */

function ensureRemoteConnected(remote, callback) {

  if (!remote || typeof remote !== 'object') {
    callback(new Error('invalidRemote'));
    return;
  }

  if (remote._connected === true) {
    callback(null, true);
  } else {
    remote.connect();
    remote.once('ledger_closed', function(){
      callback(null, true);
    });
  }

}
<|endoftext|>


<commit_before>"use strict";

var assert = require("assert");
var path = require("path");
var parser = require("./parser");
var environment = require("./environment");
var errors = require("./errors");
var runtime = require("./runtime");
var State = environment.State;
var NodeType = parser.NodeType;

/**
 * @return {environment.Env}
 */
exports.createGlobal = function() {
    var env = new environment.Env();
    env.define("STDIN", runtime.STDIN);
    env.define("STDOUT", runtime.STDOUT);
    env.define("STDERR", runtime.STDERR);
    env.define("seq", runtime.seq);
    env.define("file", runtime.file);
    return env;
};

/**
 * @param {string} filename
 * @param {string} src
 * @param {Error} err
 */
exports.printError = function(filename, src, err) {
    var offset = (err.offset === undefined) ? src.length : err.offset;
    var lines = src.split("\n");
    var c = 0;
    for(var line = 0; line < lines.length; line++) {
        if(offset <= c + lines[line].length) {
            break;
        }
        c += lines[line].length + 1;
    }
    var errorAt = offset - c;
    filename = filename !== "<stdin>" ? path.resolve(filename) : filename;

    console.error("StreemError: %s (%s:%d:%d)", err.message, filename, line + 1, errorAt + 1);
    console.error(lines[line]);
    console.error(runtime.repeatString(" ", errorAt) + "^");
};

/**
 * @param {string} filename
 * @param {string} src
 */
exports.run = function(filename, src) {
    try {
        var ast = parser.parse(src);
        var env = exports.createGlobal();
        var value = evaluateStatements(env, ast.statements);
        return new StreemResult(value, null);

    } catch(err) {
        if(err instanceof errors.StreemError || err instanceof runtime.RuntimeError) {
            exports.printError(filename, src, err);
            return new StreemResult(null, err);
        }
        throw err;
    }
};

/**
 * @class
 * @param {*} value
 * @param {Error} err
 */
function StreemResult(value, err) {
    this.value = value;
    this.err = err;
}

function evaluate(env, node) {
    return evaluators[node.type](env, node);
}

function evaluateStatements(env, stmts) {
    var rv = null;
    for(var i = 0; i < stmts.length; i++) {
        rv = evaluate(env, stmts[i]);
        if(env.state === State.Skip) {
            return null;
        } else if(env.state === State.Return) {
            return rv;
        }
    }
    return rv;
}

/**
 * @callback invoker
 * @param {environment.Env} env
 * @param {parser.ASTNode} node
 * @return {*}
 */

/**
 * @type {Object.<string, invoker>}
 */
var evaluators = Object.create(null);

evaluators[NodeType.Statement] = function(env, node) {

};

evaluators[NodeType.Literal] = function(env, node) {
    return node.value;
};

evaluators[NodeType.Identifier] = function(env, node) {
    return env.getVar(node);
};

function getProperty(object, prop) {
    if(object === null) {
        throw new runtime.PropertyOfNull(prop.name, prop.offset);
    }
    var value = object[prop.name];
    if(value === undefined) {
        throw new runtime.UndefinedProperty(prop.name, object, prop.offset);
    }
    return value;

}

evaluators[NodeType.Property] = function(env, node) {
    var object = evaluate(env, node.object);
    var prop = node.property;
    return getProperty(object, prop);
};

evaluators[NodeType.BinaryOperator] = function(env, node) {
    var left = evaluate(env, node.left);
    var right = evaluate(env, node.right);
    var op = node.operator;
    var offset = node.offset;

    switch(op) {
        case "+"  : return runtime.add(left, right, offset);
        case "-"  : return runtime.sub(left, right, offset);
        case "*"  : return runtime.mul(left, right, offset);
        case "/"  : return runtime.div(left, right, offset);
        case "%"  : return runtime.mod(left, right, offset);
        case "&"  : return runtime.bitand(left, right, offset);
        case "|"  : return runtime.pipe(left, right, offset);
        case "^"  : return runtime.bitxor(left, right, offset);
        case "<<" : return runtime.lshift(left, right, offset);
        case ">>" : return runtime.rshift(left, right, offset);
        case "<"  : return runtime.lt(left, right, offset);
        case ">"  : return runtime.gt(left, right, offset);
        case "<=" : return runtime.le(left, right, offset);
        case ">=" : return runtime.ge(left, right, offset);
        case "==" : return runtime.eq(left, right, offset);
        case "!=" : return runtime.ne(left, right, offset);
        case "&&" : return runtime.and(left, right, offset);
        case "||" : return runtime.or(left, right, offset);
    }
    throw new errors.CriticalError();
};

evaluators[NodeType.If] = function(env, node) {
    var cond = evaluate(env, node.condition);
    if(runtime.toBoolean(cond)) {
        return evaluateStatements(env, node.statements);
    } else if(node.else !== null) {
        return evaluate(env, node.else);
    }
    return null;
};

evaluators[NodeType.Else] = function(env, node) {
    return evaluateStatements(env, node.statements);
};

evaluators[NodeType.Unary] = function(env, node) {
    var value = evaluate(env, node.expr);
    var offset = node.offset;
    switch(node.operator) {
        case "!": return runtime.not(value, offset);
        case "+": return runtime.positive(value, offset);
        case "-": return runtime.negative(value, offset);
        case "~": return runtime.inverse(value, offset);
    }
    throw new errors.CriticalError();
};

evaluators[NodeType.Assign] = function(env, node) {
    var rightValue = evaluate(env, node.right);
    if(node.left.type === NodeType.Identifier) {
        if(node.operator === "=") {
            env.setVar(node.left, rightValue);
        } else {
            var leftValue = env.getVar(node.left);
            var result;
            switch(node.operator) {
                case "+="  : result = runtime.add(leftValue, rightValue); break;
                case "-="  : result = runtime.sub(leftValue, rightValue); break;
                case "*="  : result = runtime.mul(leftValue, rightValue); break;
                case "/="  : result = runtime.div(leftValue, rightValue); break;
                case "%="  : result = runtime.mod(leftValue, rightValue); break;
                case "<<=" : result = runtime.lshift(leftValue, rightValue); break;
                case ">>=" : result = runtime.rshift(leftValue, rightValue); break;
                case "&="  : result = runtime.bitand(leftValue, rightValue); break;
                case "|="  : result = runtime.pipe(leftValue, rightValue); break;
                case "^="  : result = runtime.bitxor(leftValue, rightValue); break;
                default: throw new errors.CriticalError();
            }
            env.setVar(node.left, result);
        }
        return rightValue;
    } else {
        assert(node.left.type === NodeType.Property);
        var leftObject = evaluate(env, node.left.object);
        runtime.assignProperty(leftObject, node.left.property.name, node.operator, rightValue);
    }
    return rightValue;
};

evaluators[NodeType.Paren] = function(env, node) {
    return evaluate(env, node.expr);
};

evaluators[NodeType.Skip] = function(env, node) {
    env.skip();
    return null;
};

evaluators[NodeType.Return] = function(env, node) {
    var value = evaluate(env, node.value);
    env.return();
    return value;
};

evaluators[NodeType.Array] = function(env, node) {
    var array = [];
    for(var i = 0; i < node.elements.length; i++) {
        array.push(evaluate(env, node.elements[i]));
    }
    return array;
};

evaluators[NodeType.Emit] = function(env, node) {
    for(var i = 0; i < node.values.length; i++) {
        var value = evaluate(env, node.values[i]);
        env.emit(value);
    }
    return null;
};

evaluators[NodeType.Call] = function(env, node) {
    var func = node.object;
    while(func.type === NodeType.Paren) {
        func = func.expr;
    }

    var receiver = null;
    if(func.type === NodeType.Property) {
        receiver = evaluate(env, func.object);
        func = getProperty(receiver, func.property);
    } else if(func.type === NodeType.Identifier) {
        func = evaluate(env, func);
    } else if(func.type === NodeType.Block) {
        func = evaluate(env, func);
    } else {
        throw new runtime.NotCallable(func.offset);
    }

    if(func === null) {
        throw new runtime.NotCallable(func.offset);
    }

    var args = [];
    for(var i = 0; i < node.args.length; i++) {
        args.push(evaluate(env, node.args[i]));
    }

    if(typeof func === "function") {
        return func.apply(receiver, args);
    } else {
        throw new Error("What?");
    }
};

evaluators[NodeType.Block] = function(_env, node) {
    return function() {
        var env  = _env.create();
        if(arguments.length !== node.params.length) {
            throw new runtime.WrongNumberOfArguments(node.offset);
        }

        for(var i = 0; i < arguments.length; i++) {
            env.define(node.params[i], arguments[i]);
        }

        env.resetState();
        var rv = evaluateStatements(env, node.statements);

        if(this instanceof runtime.Streem) {
            for(i = 0; i < env.emitBuffer.length; i++) {
                this.queue.enqueue(env.emitBuffer[i]);
            }

            if(env.state === State.Skip) {
                this.skip();
            }
        }
        env.emitBuffer.length = 0;
        return rv;
    };
};
<commit_msg>Fix error message<commit_after>"use strict";

var assert = require("assert");
var path = require("path");
var parser = require("./parser");
var environment = require("./environment");
var errors = require("./errors");
var runtime = require("./runtime");
var State = environment.State;
var NodeType = parser.NodeType;

/**
 * @return {environment.Env}
 */
exports.createGlobal = function() {
    var env = new environment.Env();
    env.define("STDIN", runtime.STDIN);
    env.define("STDOUT", runtime.STDOUT);
    env.define("STDERR", runtime.STDERR);
    env.define("seq", runtime.seq);
    env.define("file", runtime.file);
    return env;
};

/**
 * @param {string} filename
 * @param {string} src
 * @param {Error} err
 */
exports.printError = function(filename, src, err) {
    var offset = (err.offset === undefined) ? src.length : err.offset;
    var lines = src.split("\n");
    var c = 0;
    for(var line = 0; line < lines.length; line++) {
        if(offset <= c + lines[line].length) {
            break;
        }
        c += lines[line].length + 1;
    }
    var errorAt = offset - c;
    filename = filename !== "<stdin>" ? path.resolve(filename) : filename;

    console.error("StreemError: %s (%s:%d:%d)", err.message, filename, line + 1, errorAt + 1);
    console.error(lines[line]);
    console.error(runtime.repeatString(" ", errorAt) + "^");
};

/**
 * @param {string} filename
 * @param {string} src
 */
exports.run = function(filename, src) {
    try {
        var ast = parser.parse(src);
        var env = exports.createGlobal();
        var value = evaluateStatements(env, ast.statements);
        return new StreemResult(value, null);

    } catch(err) {
        if(err instanceof errors.StreemError || err instanceof runtime.RuntimeError) {
            exports.printError(filename, src, err);
            return new StreemResult(null, err);
        }
        throw err;
    }
};

/**
 * @class
 * @param {*} value
 * @param {Error} err
 */
function StreemResult(value, err) {
    this.value = value;
    this.err = err;
}

function evaluate(env, node) {
    return evaluators[node.type](env, node);
}

function evaluateStatements(env, stmts) {
    var rv = null;
    for(var i = 0; i < stmts.length; i++) {
        rv = evaluate(env, stmts[i]);
        if(env.state === State.Skip) {
            return null;
        } else if(env.state === State.Return) {
            return rv;
        }
    }
    return rv;
}

/**
 * @callback invoker
 * @param {environment.Env} env
 * @param {parser.ASTNode} node
 * @return {*}
 */

/**
 * @type {Object.<string, invoker>}
 */
var evaluators = Object.create(null);

evaluators[NodeType.Statement] = function(env, node) {

};

evaluators[NodeType.Literal] = function(env, node) {
    return node.value;
};

evaluators[NodeType.Identifier] = function(env, node) {
    return env.getVar(node);
};

function getProperty(object, prop) {
    if(object === null) {
        throw new runtime.PropertyOfNull(prop.name, prop.offset);
    }
    var value = object[prop.name];
    if(value === undefined) {
        throw new runtime.UndefinedProperty(prop.name, object, prop.offset);
    }
    return value;

}

evaluators[NodeType.Property] = function(env, node) {
    var object = evaluate(env, node.object);
    var prop = node.property;
    return getProperty(object, prop);
};

evaluators[NodeType.BinaryOperator] = function(env, node) {
    var left = evaluate(env, node.left);
    var right = evaluate(env, node.right);
    var op = node.operator;
    var offset = node.offset;

    switch(op) {
        case "+"  : return runtime.add(left, right, offset);
        case "-"  : return runtime.sub(left, right, offset);
        case "*"  : return runtime.mul(left, right, offset);
        case "/"  : return runtime.div(left, right, offset);
        case "%"  : return runtime.mod(left, right, offset);
        case "&"  : return runtime.bitand(left, right, offset);
        case "|"  : return runtime.pipe(left, right, offset);
        case "^"  : return runtime.bitxor(left, right, offset);
        case "<<" : return runtime.lshift(left, right, offset);
        case ">>" : return runtime.rshift(left, right, offset);
        case "<"  : return runtime.lt(left, right, offset);
        case ">"  : return runtime.gt(left, right, offset);
        case "<=" : return runtime.le(left, right, offset);
        case ">=" : return runtime.ge(left, right, offset);
        case "==" : return runtime.eq(left, right, offset);
        case "!=" : return runtime.ne(left, right, offset);
        case "&&" : return runtime.and(left, right, offset);
        case "||" : return runtime.or(left, right, offset);
    }
    throw new errors.CriticalError();
};

evaluators[NodeType.If] = function(env, node) {
    var cond = evaluate(env, node.condition);
    if(runtime.toBoolean(cond)) {
        return evaluateStatements(env, node.statements);
    } else if(node.else !== null) {
        return evaluate(env, node.else);
    }
    return null;
};

evaluators[NodeType.Else] = function(env, node) {
    return evaluateStatements(env, node.statements);
};

evaluators[NodeType.Unary] = function(env, node) {
    var value = evaluate(env, node.expr);
    var offset = node.offset;
    switch(node.operator) {
        case "!": return runtime.not(value, offset);
        case "+": return runtime.positive(value, offset);
        case "-": return runtime.negative(value, offset);
        case "~": return runtime.inverse(value, offset);
    }
    throw new errors.CriticalError();
};

evaluators[NodeType.Assign] = function(env, node) {
    var rightValue = evaluate(env, node.right);
    if(node.left.type === NodeType.Identifier) {
        if(node.operator === "=") {
            env.setVar(node.left, rightValue);
        } else {
            var leftValue = env.getVar(node.left);
            var result;
            switch(node.operator) {
                case "+="  : result = runtime.add(leftValue, rightValue); break;
                case "-="  : result = runtime.sub(leftValue, rightValue); break;
                case "*="  : result = runtime.mul(leftValue, rightValue); break;
                case "/="  : result = runtime.div(leftValue, rightValue); break;
                case "%="  : result = runtime.mod(leftValue, rightValue); break;
                case "<<=" : result = runtime.lshift(leftValue, rightValue); break;
                case ">>=" : result = runtime.rshift(leftValue, rightValue); break;
                case "&="  : result = runtime.bitand(leftValue, rightValue); break;
                case "|="  : result = runtime.pipe(leftValue, rightValue); break;
                case "^="  : result = runtime.bitxor(leftValue, rightValue); break;
                default: throw new errors.CriticalError();
            }
            env.setVar(node.left, result);
        }
        return rightValue;
    } else {
        assert(node.left.type === NodeType.Property);
        var leftObject = evaluate(env, node.left.object);
        runtime.assignProperty(leftObject, node.left.property.name, node.operator, rightValue);
    }
    return rightValue;
};

evaluators[NodeType.Paren] = function(env, node) {
    return evaluate(env, node.expr);
};

evaluators[NodeType.Skip] = function(env, node) {
    env.skip();
    return null;
};

evaluators[NodeType.Return] = function(env, node) {
    var value = evaluate(env, node.value);
    env.return();
    return value;
};

evaluators[NodeType.Array] = function(env, node) {
    var array = [];
    for(var i = 0; i < node.elements.length; i++) {
        array.push(evaluate(env, node.elements[i]));
    }
    return array;
};

evaluators[NodeType.Emit] = function(env, node) {
    for(var i = 0; i < node.values.length; i++) {
        var value = evaluate(env, node.values[i]);
        env.emit(value);
    }
    return null;
};

evaluators[NodeType.Call] = function(env, node) {
    var funcNode = node.object;
    while(funcNode.type === NodeType.Paren) {
        funcNode = funcNode.expr;
    }

    var receiver = null;
    var func = null;
    if(funcNode.type === NodeType.Property) {
        receiver = evaluate(env, funcNode.object);
        func = getProperty(receiver, func.property);
    } else if(funcNode.type === NodeType.Identifier) {
        func = evaluate(env, funcNode);
    } else {
        func = evaluate(env, funcNode);
    }

    if(typeof func !== "function") {
        throw new runtime.NotCallable(funcNode.offset);
    }

    var args = [];
    for(var i = 0; i < node.args.length; i++) {
        args.push(evaluate(env, node.args[i]));
    }

    if(args.length !== func.paramLength) {
        throw new runtime.WrongNumberOfArguments(node.offset);
    }

    return func.apply(receiver, args);
};

evaluators[NodeType.Block] = function(_env, node) {
    // jshint validthis: true
    function blockFunction() {
        var env  = _env.create();
        for(var i = 0; i < arguments.length; i++) {
            env.define(node.params[i], arguments[i]);
        }

        env.resetState();
        var rv = evaluateStatements(env, node.statements);
        if(this instanceof runtime.Streem) {
            for(i = 0; i < env.emitBuffer.length; i++) {
                this.queue.enqueue(env.emitBuffer[i]);
            }

            if(env.state === State.Skip) {
                this.skip();
            }
        }
        env.emitBuffer.length = 0;
        return rv;
    }

    blockFunction.paramLength = node.params.length;
    return blockFunction;
};
<|endoftext|>


<commit_before>$(document).ready(function()
{
	$.ajax(	"http://api.susi.ai/aaa/login.json", {
	    data: { checkLogin: true },
		dataType: "jsonp",
		success: function (response) {
			if(response.loggedIn){
				$("#status-box").text(response.message);
				$("#status-box").addClass("error");
				$("#loginForm").addClass("hidden");
				$("#logoutForm").removeClass("hidden");
				$("#deleteForm").removeClass("hidden");
			}
		},
		error: function (xhr, ajaxOptions, thrownError) {
			$("#status-box").text(thrownError);
			$("#status-box").addClass("error");
		},
	});

    function setRemember(){
        if($("#remember").is(":checked")){
            $("#remember_hidden").val("cookie");
        }
        else{
            $("#remember_hidden").val("session");
        }
    }
    $("#remember").click(function(){setRemember();});
    setRemember();

	var optionsLogin = {
        url:        "http://api.susi.ai/aaa/login.json",
        type:       "get",
        dataType:   "jsonp",
        success(response) {
            window.location = "/apps/applist/index.html";
        },
        error(xhr, ajaxOptions, thrownError) {
            $("#status-box").text(thrownError);
            $("#status-box").addClass("error");
        }
    };

    $("#loginForm").submit(function() {
        $(this).ajaxSubmit(optionsLogin);
        return false;
    });

    var optionsLogout = {
        url:        "http://api.susi.ai/aaa/login.json",
        type:       "get",
        dataType:   "jsonp",
        success(response) {
            $("#loginForm").removeClass("hidden");
            $("#logoutForm").addClass("hidden");
            $("#deleteForm").addClass("hidden");
            $("#status-box").text("");
            $("#status-box").removeClass();
        },
        error(xhr, ajaxOptions, thrownError) {
            $("#status-box").text(thrownError);
            $("#status-box").addClass("error");
        }
    };

    $("#logoutForm").submit(function() {
        $(this).ajaxSubmit(optionsLogout);
        return false;
    });
    $("#deleteForm").submit(function() {
        $(this).ajaxSubmit(optionsLogout);
        return false;
    });
});
<commit_msg>updated reference index page after successful login<commit_after>$(document).ready(function()
{
	$.ajax(	"http://api.susi.ai/aaa/login.json", {
	    data: { checkLogin: true },
		dataType: "jsonp",
		success: function (response) {
			if(response.loggedIn){
				$("#status-box").text(response.message);
				$("#status-box").addClass("error");
				$("#loginForm").addClass("hidden");
				$("#logoutForm").removeClass("hidden");
				$("#deleteForm").removeClass("hidden");
			}
		},
		error: function (xhr, ajaxOptions, thrownError) {
			$("#status-box").text(thrownError);
			$("#status-box").addClass("error");
		},
	});

    function setRemember(){
        if($("#remember").is(":checked")){
            $("#remember_hidden").val("cookie");
        }
        else{
            $("#remember_hidden").val("session");
        }
    }
    $("#remember").click(function(){setRemember();});
    setRemember();

	var optionsLogin = {
        url:        "http://api.susi.ai/aaa/login.json",
        type:       "get",
        dataType:   "jsonp",
        success(response) {
            window.location = "../../apps/applist/index.html";
        },
        error(xhr, ajaxOptions, thrownError) {
            $("#status-box").text(thrownError);
            $("#status-box").addClass("error");
        }
    };

    $("#loginForm").submit(function() {
        $(this).ajaxSubmit(optionsLogin);
        return false;
    });

    var optionsLogout = {
        url:        "http://api.susi.ai/aaa/login.json",
        type:       "get",
        dataType:   "jsonp",
        success(response) {
            $("#loginForm").removeClass("hidden");
            $("#logoutForm").addClass("hidden");
            $("#deleteForm").addClass("hidden");
            $("#status-box").text("");
            $("#status-box").removeClass();
        },
        error(xhr, ajaxOptions, thrownError) {
            $("#status-box").text(thrownError);
            $("#status-box").addClass("error");
        }
    };

    $("#logoutForm").submit(function() {
        $(this).ajaxSubmit(optionsLogout);
        return false;
    });
    $("#deleteForm").submit(function() {
        $(this).ajaxSubmit(optionsLogout);
        return false;
    });
});
<|endoftext|>


<commit_before>/*-----------------------------------------------
  Requirements:
-----------------------------------------------*/
var sys    = require("sys")
  , http   = require("http")
  , events = require("events")
  , path   = require("path");

require.paths.unshift(__dirname);

var Manager = require("ws/manager")
  , Connection = require("ws/connection");

/*-----------------------------------------------
  Mixin:
-----------------------------------------------*/
var mixin = function(target, source) {
  for(var i = 0, keys = Object.keys(source), l = keys.length; i < l; ++i) {
    if(source.hasOwnProperty(keys[i])){
      target[keys[i]] = source[keys[i]];
    }
  }
  return target;
};

/*-----------------------------------------------
  WebSocket Server Exports:
-----------------------------------------------*/
exports.Server = Server;
exports.createServer = function(options){
  return new Server(options);
};

exports._Manager = Manager;
exports._Connection = Connection;

/*-----------------------------------------------
  WebSocket Server Implementation:
-----------------------------------------------*/

function Server(options){
  var ws = this;

  events.EventEmitter.call(this);

  this.options = mixin({
    debug: false,         // Boolean:       Show debug information.
    version: "auto",      // String:        Value must be either: draft75, draft76, auto
    origin: "*",          // String, Array: A match for a valid connection origin
    subprotocol: "*",     // String, Array: A match for a valid connection subprotocol.
    datastore: true,      // Object, Function, Boolean: If === true, then it is the default mem-store.
    server: new http.Server()
  }, options || {});

  this.manager = new Manager(this.options.debug);
  this.server  = this.options.server
  this.debug   = this.options.debug;

  this.server.addListener("upgrade", function(req, socket, upgradeHead){
    if( req.method == "GET" && ( "upgrade" in req.headers && "connection" in req.headers) &&
        req.headers.upgrade.toLowerCase() == "websocket" && req.headers.connection.toLowerCase() == "upgrade"
    ){
      // create a new connection, it'll handle everything else.
      new Connection(ws, req, socket, upgradeHead);
    } else {
      // Close the socket, it wasn't a valid connection.
      socket.end();
      socket.destroy();
    }
  });

  this.server.addListener("connection", function(socket){
    socket.setTimeout(0);
    socket.setNoDelay(true);
    socket.setKeepAlive(true, 0);
  });

  this.server.addListener("listening", function(req, res){
    ws.emit("listening");
  });

  this.server.addListener("close", function(errno){
    ws.emit("shutdown", errno);
  });

  this.server.addListener("request", function(req, res){
    ws.emit("request", req, res);
  });

  this.server.addListener("stream", function(stream){
    ws.emit("stream", stream);
  });

  this.server.addListener("clientError", function(e){
    ws.emit("clientError", e);
  });
};

sys.inherits(Server, events.EventEmitter);

/*-----------------------------------------------
  Public API
-----------------------------------------------*/
Server.prototype.setSecure = function (credentials) {
  this.server.setSecure.call(this.server, credentials);
}

Server.prototype.listen = function(){
  this.server.listen.apply(this.server, arguments);
};

Server.prototype.close = function(){
  this.server.close();
};

Server.prototype.send = function(id, data){
  this.manager.find(id, function(client){
    if(client && client._state === 4){
      client.write(data);
    }
  });
};

Server.prototype.broadcast = function(data){
  this.manager.forEach(function(client){
    if(client && client._state === 4){
      client.write(data);
    }
  });
};

Server.prototype.use = function(module){
  module.call(this, this.options);
};

<commit_msg>Use relative ids for referencing intra-package modules<commit_after>/*-----------------------------------------------
  Requirements:
-----------------------------------------------*/
var sys    = require("sys")
  , http   = require("http")
  , events = require("events")
  , path   = require("path");

require.paths.unshift(__dirname);

var Manager = require("./ws/manager")
  , Connection = require("./ws/connection");

/*-----------------------------------------------
  Mixin:
-----------------------------------------------*/
var mixin = function(target, source) {
  for(var i = 0, keys = Object.keys(source), l = keys.length; i < l; ++i) {
    if(source.hasOwnProperty(keys[i])){
      target[keys[i]] = source[keys[i]];
    }
  }
  return target;
};

/*-----------------------------------------------
  WebSocket Server Exports:
-----------------------------------------------*/
exports.Server = Server;
exports.createServer = function(options){
  return new Server(options);
};

exports._Manager = Manager;
exports._Connection = Connection;

/*-----------------------------------------------
  WebSocket Server Implementation:
-----------------------------------------------*/

function Server(options){
  var ws = this;

  events.EventEmitter.call(this);

  this.options = mixin({
    debug: false,         // Boolean:       Show debug information.
    version: "auto",      // String:        Value must be either: draft75, draft76, auto
    origin: "*",          // String, Array: A match for a valid connection origin
    subprotocol: "*",     // String, Array: A match for a valid connection subprotocol.
    datastore: true,      // Object, Function, Boolean: If === true, then it is the default mem-store.
    server: new http.Server()
  }, options || {});

  this.manager = new Manager(this.options.debug);
  this.server  = this.options.server
  this.debug   = this.options.debug;

  this.server.addListener("upgrade", function(req, socket, upgradeHead){
    if( req.method == "GET" && ( "upgrade" in req.headers && "connection" in req.headers) &&
        req.headers.upgrade.toLowerCase() == "websocket" && req.headers.connection.toLowerCase() == "upgrade"
    ){
      // create a new connection, it'll handle everything else.
      new Connection(ws, req, socket, upgradeHead);
    } else {
      // Close the socket, it wasn't a valid connection.
      socket.end();
      socket.destroy();
    }
  });

  this.server.addListener("connection", function(socket){
    socket.setTimeout(0);
    socket.setNoDelay(true);
    socket.setKeepAlive(true, 0);
  });

  this.server.addListener("listening", function(req, res){
    ws.emit("listening");
  });

  this.server.addListener("close", function(errno){
    ws.emit("shutdown", errno);
  });

  this.server.addListener("request", function(req, res){
    ws.emit("request", req, res);
  });

  this.server.addListener("stream", function(stream){
    ws.emit("stream", stream);
  });

  this.server.addListener("clientError", function(e){
    ws.emit("clientError", e);
  });
};

sys.inherits(Server, events.EventEmitter);

/*-----------------------------------------------
  Public API
-----------------------------------------------*/
Server.prototype.setSecure = function (credentials) {
  this.server.setSecure.call(this.server, credentials);
}

Server.prototype.listen = function(){
  this.server.listen.apply(this.server, arguments);
};

Server.prototype.close = function(){
  this.server.close();
};

Server.prototype.send = function(id, data){
  this.manager.find(id, function(client){
    if(client && client._state === 4){
      client.write(data);
    }
  });
};

Server.prototype.broadcast = function(data){
  this.manager.forEach(function(client){
    if(client && client._state === 4){
      client.write(data);
    }
  });
};

Server.prototype.use = function(module){
  module.call(this, this.options);
};

<|endoftext|>


<commit_before>class Container{
    constructor(){
        this.services = {};
    }

    destroy(){
        delete this.services;
        this.services = {};
    }

    /**
     * Defines a service on the container. The service is accessed
     * directly as a property, but is not actually instantiated
     * before it is called.
     *
     * The service is only instantiated once.
     */
    service(name, cb){
        Object.defineProperty(this, name, {
            get: () => {
                if(!this.services.hasOwnProperty(name)){
                    this.services[name] = cb(this);
                }

                return this.services[name];
            }
        });

        return this;
    }

    /**
     * Define a factory function on the container.
     * The factory is accessed directly as a property,
     * and is instantiated every time the property is used.
     */
    factory(name, cb){
        Object.defineProperty(this, name, {
            get: () => {
                return cb(this);
            }
        });

        return this;
    }

    /**
     * A service provider is a class that uses
     * a register function to register all its related dependencies.
     * The container is passed to this function when the provider
     * registers itself here.
     */
    register(provider){
        provider.register(this);
    }

    /**
     * Helper function for binding constructor arguments.
     *
     * We also need it in order to set static properties to the bound constructor,
     * since React expects to get those directly from the element type.
     *
     * And lastly, we don't need to pass props and context to the Component,
     * since those are also set after React has constructed the component.
     * Admittedly, this should be done, but is not strictly necessary.
     */
    bindElement(elem, ...args){
        let f = elem.bind(null, ...args);

        /*
         Need to change the display name so we get something
         better than "bound something something"
        */
        f.displayName = elem.name;

        /*
        Also need to set various other static properties
         */
        f.defaultProps = elem.defaultProps;
        f.propTypes = elem.propTypes;
        f.contextTypes = elem.contextTypes;
        f.childContextTypes = elem.childContextTypes;

        return f;
    }
}

module.exports = Container;<commit_msg>Remove old stuff that's not really needed<commit_after>class Container{
    constructor(){
        this.services = {};
    }

    /**
     * Defines a service on the container. The service is accessed
     * directly as a property, but is not actually instantiated
     * before it is called.
     *
     * The service is only instantiated once.
     */
    service(name, cb){
        Object.defineProperty(this, name, {
            get: () => {
                if(!this.services.hasOwnProperty(name)){
                    this.services[name] = cb(this);
                }

                return this.services[name];
            },
            configurable: true,
            enumerable: true
        });

        return this;
    }
}

module.exports = Container;
<|endoftext|>


<commit_before>// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

goog.setTestOnly();

goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');

var $ = goog.dom.getRequiredElement;

var test = {
  mockControl: new goog.testing.MockControl()
};

function setUp() {
  registry.testing.addToDocument('
');
  registry.testing.addToDocument('
');
  goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
    xsrfToken: 'test',
    username: 'blah',
    logoutUrl: 'omg',
    isAdmin: true,
    clientId: 'daddy',
    showPaymentLink: false,
    logoFilename: 'logo.png',
    productName: 'Nomulus',
    integrationEmail: 'integration@example.com',
    supportEmail: 'support@example.com',
    announcementsEmail: 'announcement@example.com',
    supportPhoneNumber: '+1 (888) 555 0123',
    technicalDocsUrl: 'http://example.com/techdocs'
  });
  registry.registrar.ConsoleTestUtil.setup(test);
}

function tearDown() {
  goog.dispose(test.console);
  test.mockControl.$tearDown();
}

/** Contact hash path should nav to contact page. */
function testVisitContact() {
  registry.registrar.ConsoleTestUtil.visit(test, {
    path: 'contact/pabloistrad',
    rspXml: '<?xml version="1.0"?>' +
        '<epp xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"' +
        '     xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"' +
        '     xmlns:host="urn:ietf:params:xml:ns:host-1.0"' +
        '     xmlns:launch="urn:ietf:params:xml:ns:launch-1.0"' +
        '     xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0"' +
        '     xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
        '     xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1"' +
        '     xmlns:mark="urn:ietf:params:xml:ns:mark-1.0">' +
        '  <response>' +
        '    <result code="1000">' +
        '      <msg>Command completed successfully</msg>' +
        '    </result>' +
        '    <resData>' +
        '      <contact:infData>' +
        '        <contact:id>pabloistrad</contact:id>' +
        '        <contact:roid>1-roid</contact:roid>' +
        '        <contact:status s="ok"/>' +
        '        <contact:postalInfo type="int">' +
        '          <contact:name>name2</contact:name>' +
        '          <contact:addr>' +
        '            <contact:street></contact:street>' +
        '            <contact:city>city2</contact:city>' +
        '            <contact:cc>US</contact:cc>' +
        '          </contact:addr>' +
        '        </contact:postalInfo>' +
        '        <contact:voice/>' +
        '        <contact:fax/>' +
        '        <contact:email>test2.ui@example.com</contact:email>' +
        '        <contact:clID>daddy</contact:clID>' +
        '        <contact:crID>daddy</contact:crID>' +
        '        <contact:crDate>2014-05-06T22:16:36Z</contact:crDate>' +
        '        <contact:upID>daddy</contact:upID>' +
        '        <contact:upDate>2014-05-07T16:20:07Z</contact:upDate>' +
        '       <contact:authInfo>' +
        '          <contact:pw>asdfasdf</contact:pw>' +
        '        </contact:authInfo>' +
        '      </contact:infData>' +
        '    </resData>' +
        '    <trID>' +
        '      <clTRID>abc-1234</clTRID>' +
        '      <svTRID>c4O3B0pRRKKSrrXsJvxP5w==-2</svTRID>' +
        '    </trID>' +
        '  </response>' +
        '</epp>'
  });
  assertEquals(3, $('contact-postalInfo').childNodes.length);
}

/** Contact hash path should nav to contact page. */
function testEdit() {
  testVisitContact();
  registry.testing.assertVisible($('reg-app-btns-edit'));
  registry.testing.click($('reg-app-btn-edit'));
  registry.testing.assertHidden($('reg-app-btns-edit'));
  registry.testing.assertVisible($('reg-app-btns-save'));
}

/** Contact hash path should nav to contact page. */
function testAddPostalInfo() {
  testEdit();
  var addPiBtn = $('domain-contact-postalInfo-add-button');
  assertNull(addPiBtn.getAttribute('disabled'));
  registry.testing.click(addPiBtn);
  assertTrue(addPiBtn.hasAttribute('disabled'));
  assertEquals(4, $('contact-postalInfo').childNodes.length);
}
<commit_msg>Fix foss build<commit_after>// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

goog.setTestOnly();

goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');

var $ = goog.dom.getRequiredElement;

var test = {
  mockControl: new goog.testing.MockControl()
};

function setUp() {
  registry.testing.addToDocument('
');
  registry.testing.addToDocument('
');
  goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
    xsrfToken: 'test',
    username: 'blah',
    logoutUrl: 'omg',
    isAdmin: true,
    clientId: 'daddy',
    showPaymentLink: false,
    logoFilename: 'logo.png',
    productName: 'Nomulus',
    integrationEmail: 'integration@example.com',
    supportEmail: 'support@example.com',
    announcementsEmail: 'announcement@example.com',
    supportPhoneNumber: '+1 (888) 555 0123',
    technicalDocsUrl: 'http://example.com/techdocs'
  });
  registry.registrar.ConsoleTestUtil.setup(test);
}

function tearDown() {
  goog.dispose(test.console);
  test.mockControl.$tearDown();
}

/** Contact hash path should nav to contact page. */
function testVisitContact() {
  registry.registrar.ConsoleTestUtil.visit(test, {
    path: 'contact/pabloistrad',
    rspXml: '<?xml version="1.0"?>' +
        '<epp xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"' +
        '     xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"' +
        '     xmlns:host="urn:ietf:params:xml:ns:host-1.0"' +
        '     xmlns:launch="urn:ietf:params:xml:ns:launch-1.0"' +
        '     xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0"' +
        '     xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
        '     xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1"' +
        '     xmlns:mark="urn:ietf:params:xml:ns:mark-1.0">' +
        '  <response>' +
        '    <result code="1000">' +
        '      <msg>Command completed successfully</msg>' +
        '    </result>' +
        '    <resData>' +
        '      <contact:infData>' +
        '        <contact:id>pabloistrad</contact:id>' +
        '        <contact:roid>1-roid</contact:roid>' +
        '        <contact:status s="ok"/>' +
        '        <contact:postalInfo type="int">' +
        '          <contact:name>name2</contact:name>' +
        '          <contact:addr>' +
        '            <contact:street></contact:street>' +
        '            <contact:city>city2</contact:city>' +
        '            <contact:cc>US</contact:cc>' +
        '          </contact:addr>' +
        '        </contact:postalInfo>' +
        '        <contact:voice/>' +
        '        <contact:fax/>' +
        '        <contact:email>test2.ui@example.com</contact:email>' +
        '        <contact:clID>daddy</contact:clID>' +
        '        <contact:crID>daddy</contact:crID>' +
        '        <contact:crDate>2014-05-06T22:16:36Z</contact:crDate>' +
        '        <contact:upID>daddy</contact:upID>' +
        '        <contact:upDate>2014-05-07T16:20:07Z</contact:upDate>' +
        '       <contact:authInfo>' +
        '          <contact:pw>asdfasdf</contact:pw>' +
        '        </contact:authInfo>' +
        '      </contact:infData>' +
        '    </resData>' +
        '    <trID>' +
        '      <clTRID>abc-1234</clTRID>' +
        '      <svTRID>c4O3B0pRRKKSrrXsJvxP5w==-2</svTRID>' +
        '    </trID>' +
        '  </response>' +
        '</epp>'
  });
  assertEquals(2, $('contact-postalInfo').childNodes.length);
}

/** Contact hash path should nav to contact page. */
function testEdit() {
  testVisitContact();
  registry.testing.assertVisible($('reg-app-btns-edit'));
  registry.testing.click($('reg-app-btn-edit'));
  registry.testing.assertHidden($('reg-app-btns-edit'));
  registry.testing.assertVisible($('reg-app-btns-save'));
}

/** Contact hash path should nav to contact page. */
function testAddPostalInfo() {
  testEdit();
  var addPiBtn = $('domain-contact-postalInfo-add-button');
  assertNull(addPiBtn.getAttribute('disabled'));
  registry.testing.click(addPiBtn);
  assertTrue(addPiBtn.hasAttribute('disabled'));
  assertEquals(3, $('contact-postalInfo').childNodes.length);
}
<|endoftext|>


<commit_before>
var tabooTable = function (elementName, taboo) {
    var tableElement = document.querySelector(elementName);

    // When changes occur in the taboo table, this updates the html
    function syncToHtml(taboo){
        var _this = this;
        this.clearTable();
        taboo.getColumnHeaders().forEach(function(header){
            _this.addColumn(header);
        });
        taboo.getRows({array:true}).forEach(function(row){
            _this.addRow(row);
        });
    };

    // when changes occur in the table this updates the taboo
    function syncToTaboo(){

    };

    // for updating the table
    // add/remove columns and rows
    function htmlTable(){

    };

    function registerCallbacks(){
        taboo.registerCallback('update', syncToHtml);
    }

    //
    var addRow = function(data){
        // add row
        var newTr = tableElement.querySelector('tbody').appendChild(document.createElement('tr'));
        var columns = tableElement.querySelector('tbody tr').childNodes.length;
        // add columns
        for (var i = 0; i < columns; i++){
            var elem = document.createElement('td');
            elem.textContent = data[i];
            newTr.appendChild();
        }
    };

    //
    var deleteRow = function(){
        var rows = tableElement.querySelectorAll('tbody tr');
        var lastRow = rows[rows.length -1];
        lastRow.parentNode.removeChild(lastRow);
    };

    var addColumn = function(columnHeader){
        var header = document.createElement('th');
        header.textContent = columnHeader;
        tableElement.querySelector('thead tr').appendChild(header);
        var rows = tableElement.querySelectorAll('tbody tr');
        for (var i = 0; i < rows.length; i++) {
            var elem = document.createElement('td');
            elem.tabIndex = '1';
            rows[i].appendChild(elem);
        }
    };

    var removeColumn = function(columnHeader){
        tableElement.querySelector('thead tr');
    };

    var clearTable = function(){
        tableElement.innerHTML = '

';
    };

    // allows cells in the html table to altered
    function Editor(elementName, options){
        var defaultOptions = {
	        cloneProperties: ['padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right',
					          'text-align', 'font', 'font-size', 'font-family', 'font-weight',
					          'border', 'border-top', 'border-bottom', 'border-left', 'border-right', 'height',
                              'width'],
	        editor: document.createElement('textarea')
        };
	    var buildDefaultOptions = function () {
		    var opts = _.extend({}, defaultOptions);
		    opts.editor = opts.editor.cloneNode();
		    return opts;
	    };
        var element = tableElement,
		    activeOptions = _.extend(buildDefaultOptions(), options),
		    ARROW_LEFT = 37, ARROW_UP = 38, ARROW_RIGHT = 39, ARROW_DOWN = 40, ENTER = 13, ESC = 27, TAB = 9,
	        editor,
		    active;

        var showEditor = function(event) {
			active = event.target;
			if (active) {
				editor.value = active.textContent;
                var activeStyle = window.getComputedStyle(active);
                window.activeStyle = activeStyle;
                activeOptions.cloneProperties.forEach(function(property){
                    editor.style[property] = activeStyle[property];
                });
			    editor.classList.remove('error');
			    editor.style.display = '';
                var rect = active.getBoundingClientRect();
                editor.style.top = rect.top + document.body.scrollTop + 'px';
                editor.style.left = rect.left + document.body.scrollLeft + 'px';
			    editor.focus();
            }
		};
        var setActiveText = function () {
            var newText = editor.value;
		    if (active.textContent === newText || editor.classList.contains('error')) {
			    return true;
		    } else {
                active.textContent = editor.value;
            }
            return undefined;
	    };
        var movement = function (element, keycode) {
            var currentIndex;
		    if (keycode === ARROW_RIGHT) {
			    return element.nextElementSibling;
		    } else if (keycode === ARROW_LEFT) {
			    return element.previousElementSibling;
		    } else if (keycode === ARROW_UP) {
                currentIndex = Array.prototype.indexOf.call(element.parentNode.children, element);
                var previous = element.parentNode.previousElementSibling;
                if (previous){
                    return previous.children[currentIndex];
                } else{
                    return false;
                }

		    } else if (keycode === ARROW_DOWN) {
                currentIndex = Array.prototype.indexOf.call(element.parentNode.children, element);
                var next = element.parentNode.nextElementSibling;
                if (next){
                    return next.children[currentIndex];
                } else {
                    return false;
                }

		    }
		    return false;
	    };

        editor = element.parentNode.appendChild(document.createElement('input'));
        editor.style.position= 'absolute';
        editor.style.display = 'none';

        // editor event listeners
        editor.addEventListener('blur', function () {
		    setActiveText();
		    editor.style.display = 'none';
	    });

        editor.addEventListener('keydown', function (e) {
            var atEnd = editor.selectionEnd === editor.value.length,
                atStart = editor.selectionEnd === 0;

		    if (e.which === ENTER) {
			    setActiveText();
			    editor.style.display = 'none';
			    active.focus();
			    e.preventDefault();
			    e.stopPropagation();
		    } else if (e.which === ESC) {
                // ignore typed values, hide input editor
			    editor.value = active.textContent;
			    e.preventDefault();
			    e.stopPropagation();
			    editor.style.display = 'none';
			    active.focus();
		    } else if (e.which === TAB) {
			    active.focus();
		    } else if ((atEnd && (e.which === ARROW_DOWN ||
                                  e.which === ARROW_RIGHT))
                        ||
                        atStart && (e.which === ARROW_UP ||
                                    e.which === ARROW_LEFT)) {
			    var possibleMove = movement(active, e.which);
			    if (possibleMove) {
                    window.possibleMove = possibleMove;
                    possibleMove.focus();
				    e.preventDefault();
				    e.stopPropagation();
			    }
		    }
	    });

        var validate = function () {

	    };
        editor.addEventListener('paste', validate);
        editor.addEventListener('input', validate);

        // element
        element.addEventListener('click', showEditor);
        element.addEventListener('keypress', showEditor);
        element.addEventListener('dblclick', showEditor);
        element.style.cursor = 'pointer';

        element.addEventListener('keydown', function(e) {
		    var prevent = true,
			    possibleMove = movement(e.target, e.which);
		    if (possibleMove) {
			    possibleMove.focus();
		    } else if (e.which === ENTER) {
			    showEditor(false);
		    } else if (e.which === 17 || e.which === 91 || e.which === 93) {
			    showEditor(true);
			    prevent = false;
		    } else {
			    prevent = false;
		    }
		    if (prevent) {
			    e.stopPropagation();
			    e.preventDefault();
		    }
	    });

        // add tabIndex to each td so it can be focused
        var tdElements = element.getElementsByTagName('td');
        for (var i = 0; i < tdElements.length; i++){
            tdElements[i].tabIndex = '1';
        }

	    window.addEventListener('resize', function () {
		    if (editor.style.display !== 'none') {
                var rect = active.getBoundingClientRect();
                editor.style.top = rect.top + document.body.scrollTop + 'px';
                editor.style.left = rect.left + document.body.scrollLeft + 'px';
                editor.style.width = active.offsetWidth + 'px';
                editor.style.height = active.offsetHeight + 'px';
		    }
	    });
    };

    // init
    (function (){
        Editor(elementName);
    })();

};

<commit_msg>Enter now moves down a row, rows automatically added at end<commit_after>
var tabooTable = function (elementName, taboo) {
    var tableElement = document.querySelector(elementName),
        _this = this,
        cloneProperties= ['padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right',
		                  'text-align', 'font', 'font-size', 'font-family', 'font-weight',
		                  'border', 'border-top', 'border-bottom', 'border-left', 'border-right', 'height',
                          'width'];

    this.taboo = taboo;

    function copyStyle(newElement, copyElement){
        var activeStyle = window.getComputedStyle(copyElement);
        cloneProperties.forEach(function(property){
            newElement.style[property] = activeStyle[property];
        });
    }

    // When changes occur in the taboo table, this updates the html
    function syncToHtml(taboo){
        clearTable();
        _this.taboo.getColumnHeaders().forEach(function(header){
            addColumn(header);
        });
        _this.taboo.getRows({array:true}).forEach(function(row){
            addRow(row);
        });
    };

    this.updateTaboo = function(newTaboo){
        this.taboo = newTaboo;
        syncToHtml();
    };

    // when changes occur in the table this updates the taboo table
    function syncToTaboo(){
        taboo.clear({silent:true});
        var headers = tableElement.querySelector('thead tr').children;
        for (var i = 0; i < headers.length; i++){
            taboo.addColumns([headers[i].textContent], {silent:true});
        }
        var rows = tableElement.querySelectorAll('tbody tr');
        for (i = 0; i < rows.length; i++){
            var row = rows[i];
            var cells = [];
            for (var j = 0; j < row.children.length; j++){
                cells.push(row.children[j].textContent);
            }
            taboo.addRows([cells], {silent:true});
        }
        // manually trigger taboo callbacks
        taboo.triggerCallbacks('update');
    };

    function registerCallbacks(){
        taboo.registerCallback('update', syncToHtml);
    }

    //
    var addRow = function(data){
        var currentTr = tableElement.querySelector('tbody tr'),
            currentTd;

        if (currentTr){
            currentTd = currentTr.querySelector('td');
        }

        if (data){
            // add row
            var newTr = tableElement.querySelector('tbody').appendChild(document.createElement('tr'));
            // add columns
            for (var i = 0; i < data.length; i++){
                var elem = document.createElement('td');
                if (currentTd){
                    copyStyle(elem, currentTd);
                };
                elem.textContent = data[i];
                elem.tabIndex = '1';
                newTr.appendChild(elem);
            }
            return newTr;
        } else {
            var newTr = tableElement.querySelector('tbody').appendChild(document.createElement('tr'));
            if (currentTr){
                for (var i = 0; i < currentTr.children.length; i++){
                    var elem = document.createElement('td');
                    if (currentTd){
                        copyStyle(elem, currentTd);
                    };

                    elem.tabIndex = '1';
                    newTr.appendChild(elem);
                }
            }
            return newTr;
        }
    };

    //
    var deleteRow = function(){
        var rows = tableElement.querySelectorAll('tbody tr');
        var lastRow = rows[rows.length -1];
        lastRow.parentNode.removeChild(lastRow);
    };

    var addColumn = function(columnHeader){
        var header = document.createElement('th');
        header.textContent = columnHeader;
        tableElement.querySelector('thead tr').appendChild(header);
        var rows = tableElement.querySelectorAll('tbody tr');
        for (var i = 0; i < rows.length; i++) {
            var elem = document.createElement('td');
            elem.tabIndex = '1';
            rows[i].appendChild(elem);
        }
    };

    var removeColumn = function(columnHeader){
        tableElement.querySelector('thead tr');
    };

    var clearTable = function(){
        tableElement.innerHTML = '

';
    };

    // allows cells in the html table to altered
    function Editor(elementName, options){
        var defaultOptions = {
	        cloneProperties: ['padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right',
					          'text-align', 'font', 'font-size', 'font-family', 'font-weight',
					          'border', 'border-top', 'border-bottom', 'border-left', 'border-right', 'height',
                              'width'],
	        editor: document.createElement('textarea')
        };
	    var buildDefaultOptions = function () {
		    var opts = _.extend({}, defaultOptions);
		    return opts;
	    };
        var element = tableElement,
		    activeOptions = _.extend(buildDefaultOptions(), options),
		    ARROW_LEFT = 37, ARROW_UP = 38, ARROW_RIGHT = 39, ARROW_DOWN = 40, ENTER = 13, ESC = 27, TAB = 9,
	        editor,
		    active;

        var showEditor = function(event) {

			active = event.target;
            if (active === element){
                // user has clicked the table itself, not a cell within the table
                return;
            }

			if (active) {
				editor.value = active.textContent;
                var activeStyle = window.getComputedStyle(active);
                activeOptions.cloneProperties.forEach(function(property){
                    editor.style[property] = activeStyle[property];
                });
			    editor.classList.remove('error');
			    editor.style.display = '';
                var rect = active.getBoundingClientRect();
                editor.style.top = rect.top + document.body.scrollTop + 'px';
                editor.style.left = rect.left + document.body.scrollLeft + 'px';
			    editor.focus();
            }
		};
        var setActiveText = function () {
            var newText = editor.value;
		    if (active.textContent === newText || editor.classList.contains('error')) {
			    return true;
		    } else {
                active.textContent = editor.value;
            }
            // update the taboo instance to which this table is linked
            syncToTaboo();
            return undefined;
	    };

        var movement = function (cell, keycode) {
            var currentIndex;
		    if (keycode === ARROW_RIGHT) {
			    return cell.nextElementSibling;
		    } else if (keycode === ARROW_LEFT) {
			    return cell.previousElementSibling;
		    } else if (keycode === ARROW_UP) {
                currentIndex = Array.prototype.indexOf.call(cell.parentNode.children, cell);
                var previous = cell.parentNode.previousElementSibling;
                if (previous){
                    return previous.children[currentIndex];
                } else{
                    return false;
                }
		    } else if (keycode === ARROW_DOWN) {
                currentIndex = Array.prototype.indexOf.call(cell.parentNode.children, cell);
                var nextRow = cell.parentNode.nextElementSibling;
                // if there is another row beneath this one, move to it
                if (nextRow){
                    return nextRow.children[currentIndex];
                } else {
                    // otherwise create a new row below it
                    nextRow = addRow();
                    return nextRow.children[currentIndex];
                }
		    }
		    return false;
	    };

        editor = element.parentNode.appendChild(document.createElement('input'));
        editor.style.position= 'absolute';
        editor.style.display = 'none';

        // editor event listeners
        editor.addEventListener('blur', function () {
		    setActiveText();
		    editor.style.display = 'none';
	    });

        editor.addEventListener('keydown', function (e) {
            var atEnd = editor.selectionEnd === editor.value.length,
                atStart = editor.selectionEnd === 0;
		    if (e.which === ENTER) {
			    setActiveText();
			    editor.style.display = 'none';
                // move down in addition to setting the text
                var move = movement(active, ARROW_DOWN);
                move.focus();
			    e.preventDefault();
			    e.stopPropagation();
		    } else if (e.which === ESC) {
                // ignore typed values, hide input editor
			    editor.value = active.textContent;
			    e.preventDefault();
			    e.stopPropagation();
			    editor.style.display = 'none';
			    active.focus();
		    } else if (e.which === TAB) {
			    active.focus();
		    } else if ((atEnd && (e.which === ARROW_DOWN ||
                                  e.which === ARROW_RIGHT))
                        ||
                        atStart && (e.which === ARROW_UP ||
                                    e.which === ARROW_LEFT)) {
			    var possibleMove = movement(active, e.which);
			    if (possibleMove) {
                    window.possibleMove = possibleMove;
                    possibleMove.focus();
				    e.preventDefault();
				    e.stopPropagation();
			    }
		    }
	    });

        var validate = function () {

	    };
        editor.addEventListener('paste', validate);
        editor.addEventListener('input', validate);

        // element
        element.addEventListener('click', showEditor);
        element.addEventListener('keypress', showEditor);
        element.addEventListener('dblclick', showEditor);
        element.style.cursor = 'pointer';

        element.addEventListener('keydown', function(e) {
		    var prevent = true,
			    possibleMove = movement(e.target, e.which);
		    if (possibleMove) {
			    possibleMove.focus();
		    } else if (e.which === ENTER) {
			    showEditor(false);
		    } else if (e.which === 17 || e.which === 91 || e.which === 93) {
			    showEditor(true);
			    prevent = false;
		    } else {
			    prevent = false;
		    }
		    if (prevent) {
			    e.stopPropagation();
			    e.preventDefault();
		    }
	    });

        // add tabIndex to each td so it can be focused
        var tdElements = element.getElementsByTagName('td');
        for (var i = 0; i < tdElements.length; i++){
            tdElements[i].tabIndex = '1';
        }

	    window.addEventListener('resize', function () {
		    if (editor.style.display !== 'none') {
                var rect = active.getBoundingClientRect();
                editor.style.top = rect.top + document.body.scrollTop + 'px';
                editor.style.left = rect.left + document.body.scrollLeft + 'px';
                editor.style.width = active.offsetWidth + 'px';
                editor.style.height = active.offsetHeight + 'px';
		    }
	    });
    };

    // init

    var e = new Editor(elementName);
    syncToHtml(taboo);
    registerCallbacks();

};

<|endoftext|>