<commit_before>var _ = require("lodash");
var express = require("express");
var path = require("path");
var bodyParser = require("body-parser");
var jsonfile = require("jsonfile");
var request = require("request");
var uuid = require('node-uuid');

var file = "cloudhole.json";
var surge = require("surge")({ default: "publish" })

var saveClearances = function() {
  jsonfile.writeFile(file, clearances, {spaces: 2}, function(err) {
    if (err != null) {
      console.error(err);
    }
    else {
      surge([".", "cloudhole.surge.sh"]);
    }
  });
};

var clearances = [];
try {
  clearances = jsonfile.readFileSync(file);
  saveClearances();
}
catch(e) {
  var url = "https://cloudhole.surge.sh/cloudhole.json"
  request({
      url: url,
      json: true
  }, function (error, response, data) {
    if (!error && response.statusCode === 200) {
      clearances = data;
    }
    saveClearances();
  });
}

var app = express();
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.json());

// Initialize the app.
var server = app.listen(process.env.PORT || 8080, function () {
  var port = server.address().port;
  console.log("App now running on port", port);
});

// CLEARANCES API ROUTES BELOW

// Generic error handler used by all endpoints.
function handleError(res, reason, message, code) {
  console.log("ERROR: " + reason);
  res.status(code || 500).json({"error": message});
}

/*  "/clearances"
 *    GET: finds all clearances
 *    POST: creates a new clearance
 */

app.get("/clearances", function(req, res) {
  try {
    res.status(200).json(clearances);
  }
  catch(e) {
    res.status(204).json(e.message);
  }
});

app.post("/clearances", function(req, res) {
  var newClearance = req.body;
  newClearance.createDate = new Date();

  if (!(req.body.userAgent && req.body.cookies)) {
    handleError(res, "Invalid user input", "Must provide a User Agent and Cookies.", 400);
    return;
  }

  if (_.findIndex(clearances, {userAgent: req.body.userAgent, cookies: req.body.cookies}) != -1) {
    handleError(res, "Duplicate clearance", "UserAgent and cookies already exist.", 400);
    return;
  }

  try {
    newClearance._id = uuid.v4();
    clearances.push(newClearance);
    saveClearances();
    res.status(201).json(newClearance);
  }
  catch(err) {
    handleError(res, "Failed to create new clearance.", err.message, 500);
  }
});

app.post("/load", function(req, res) {
  var loadClearances = req.body;

  for (var i = 0; i < loadClearances.length; i++) {
    var clearance = loadClearances[i];
    if (_.findIndex(clearances, {userAgent: clearance.userAgent, cookies: clearance.cookies}) == -1) {
      clearances.push(clearance);
    }
  }
  res.status(201).end();
});

/*  "/clearances/:id"
 *    GET: find clearance by id
 *    PUT: update clearance by id
 *    DELETE: deletes clearance by id
 */

app.get("/clearances/:id", function(req, res) {
  try {
    var index = _.findIndex(clearances, {_id: req.params.id});
    res.status(200).json(clearances[index]);
  }
  catch(err) {
    handleError(res, "Failed to get clearance", err.message, 500);
  }
});

app.put("/clearances/:id", function(req, res) {
  var updateDoc = req.body;

  try {
    var index = _.findIndex(clearances, {_id: req.params.id});
    clearances[index] = updateDoc;
    saveClearances();
    res.status(204).end();
  }
  catch(err) {
    handleError(res, "Failed to update clearance", err.message, 500);
  }
});

app.delete("/clearances/:id", function(req, res) {
  try {
    var index = _.findIndex(clearances, {_id: req.params.id});
    clearances.splice(index, 1);
    saveClearances();
    res.status(204).end();
  }
  catch(err) {
    handleError(res, "Failed to delete clearance", err.message, 500);
  }
});
<commit_msg>filter duplicates on clearance only<commit_after>var _ = require("lodash");
var express = require("express");
var path = require("path");
var bodyParser = require("body-parser");
var jsonfile = require("jsonfile");
var request = require("request");
var uuid = require('node-uuid');

var file = "cloudhole.json";
var surge = require("surge")({ default: "publish" })

var saveClearances = function() {
  jsonfile.writeFile(file, clearances, {spaces: 2}, function(err) {
    if (err != null) {
      console.error(err);
    }
    else {
      surge([".", "cloudhole.surge.sh"]);
    }
  });
};

var clearances = [];
try {
  clearances = jsonfile.readFileSync(file);
  saveClearances();
}
catch(e) {
  var url = "https://cloudhole.surge.sh/cloudhole.json"
  request({
      url: url,
      json: true
  }, function (error, response, data) {
    if (!error && response.statusCode === 200) {
      clearances = data;
    }
    saveClearances();
  });
}

var app = express();
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.json());

// Initialize the app.
var server = app.listen(process.env.PORT || 8080, function () {
  var port = server.address().port;
  console.log("App now running on port", port);
});

// CLEARANCES API ROUTES BELOW

// Generic error handler used by all endpoints.
function handleError(res, reason, message, code) {
  console.log("ERROR: " + reason);
  res.status(code || 500).json({"error": message});
}

/*  "/clearances"
 *    GET: finds all clearances
 *    POST: creates a new clearance
 */

app.get("/clearances", function(req, res) {
  try {
    res.status(200).json(clearances);
  }
  catch(e) {
    res.status(204).json(e.message);
  }
});

app.post("/clearances", function(req, res) {
  var newClearance = req.body;
  newClearance.createDate = new Date();

  if (!(req.body.userAgent && req.body.cookies)) {
    handleError(res, "Invalid user input", "Must provide a User Agent and Cookies.", 400);
    return;
  }

  if (_.findIndex(clearances, {cookies: req.body.cookies}) != -1) {
    handleError(res, "Duplicate clearance", "UserAgent and cookies already exist.", 400);
    return;
  }

  try {
    newClearance._id = uuid.v4();
    clearances.push(newClearance);
    saveClearances();
    res.status(201).json(newClearance);
  }
  catch(err) {
    handleError(res, "Failed to create new clearance.", err.message, 500);
  }
});

app.post("/load", function(req, res) {
  var loadClearances = req.body;

  for (var i = 0; i < loadClearances.length; i++) {
    var clearance = loadClearances[i];
    if (_.findIndex(clearances, {cookies: clearance.cookies}) == -1) {
      clearances.push(clearance);
    }
  }
  res.status(201).end();
});

/*  "/clearances/:id"
 *    GET: find clearance by id
 *    PUT: update clearance by id
 *    DELETE: deletes clearance by id
 */

app.get("/clearances/:id", function(req, res) {
  try {
    var index = _.findIndex(clearances, {_id: req.params.id});
    res.status(200).json(clearances[index]);
  }
  catch(err) {
    handleError(res, "Failed to get clearance", err.message, 500);
  }
});

app.put("/clearances/:id", function(req, res) {
  var updateDoc = req.body;

  try {
    var index = _.findIndex(clearances, {_id: req.params.id});
    clearances[index] = updateDoc;
    saveClearances();
    res.status(204).end();
  }
  catch(err) {
    handleError(res, "Failed to update clearance", err.message, 500);
  }
});

app.delete("/clearances/:id", function(req, res) {
  try {
    var index = _.findIndex(clearances, {_id: req.params.id});
    clearances.splice(index, 1);
    saveClearances();
    res.status(204).end();
  }
  catch(err) {
    handleError(res, "Failed to delete clearance", err.message, 500);
  }
});
<|endoftext|>


<commit_before>var fs = require('fs');
var HydraHead           = require('./hydraHead.js').HydraHead,
    HydraHeadStatic     = require('./hydraHead.js').HydraHeadStatic,
    HydraHeadFilesystem = require('./hydraHead.js').HydraHeadFilesystem,
    HydraHeadProxy      = require('./hydraHead.js').HydraHeadProxy;
var serveStaticFile = require('./hydraUtils.js').serveStaticFile,
    proxyRequest    = require('./hydraUtils.js').proxyRequest;

var InvalidHydraPluginException = function(message) {
    this.name    = "InvalidHydraPluginException";
    this.message = message || 'Invalid or incomplete plugin';
};
InvalidHydraPluginException.prototype.toString = function() {
    return "InvalidHydraPluginException";
};

var DuplicateHydraPluginException = function(message) {
    this.name    = "DuplicateHydraPluginException";
    this.message = message || 'Duplicate or incomplete plugin';
};
DuplicateHydraPluginException.prototype.toString = function() {
    return "DuplicateHydraPluginException";
};

var DuplicateHydraHeadNameException = function(head) {
    this.name    = "DuplicateHydraHeadNameException";
    this.message = 'Duplicate Hydra head name "' + head + '"';
};
DuplicateHydraHeadNameException.prototype.toString = function() {
    return "DuplicateHydraHeadNameException";
};

var HydraHeadNotFoundException = function(pluginName, headName) {
    this.name    = "HydraHeadNotFoundException";
    this.message = 'Could not find the given head ("' + pluginName +
            '" / "' + headName + '")';
};
HydraHeadNotFoundException.prototype.toString = function() {
    return "HydraHeadNotFoundException";
};

var HydraPluginNotFoundException = function(pluginName) {
    this.name    = "HydraPluginNotFoundException";
    this.message = 'Could not find the given plugin ("' + pluginName + '")';
};
HydraPluginNotFoundException.prototype.toString = function() {
    return "HydraPluginNotFoundException";
};

var Hydra = function() {
    this._plugins = [];
    this._headMap = {};
    this._count = 0;
    // The first slash in "/./hydra..." is needed because this list
    // will always be appended to an absolute path (the current
    // directory or something else)
    this._pluginLoadPath = ['/./hydra/plugins',
                            '/usr/local/share/hydra/plugins',
                            '/usr/share/hydra/plugins'];
    var adminPlugin = require('./plugins/admin.js');
    adminPlugin.heads = adminPlugin.getBodyParts({hydra: this});
    this._registerPluginObject(adminPlugin);
};
Hydra.prototype._validatePluginName = function(pluginName) {
    return (typeof(pluginName) === 'string' &&
                pluginName.match(new RegExp('^[a-z0-9_-]+$', 'i')));
};
Hydra.prototype._registerPluginObject = function(plugin) {
    var name = plugin.name;
    if (this._plugins.some(function(v) { return v.plugin.name === name; })) {
        throw new DuplicateHydraPluginException();
    }

    var self = this;
    var anonymousHeadCount = 0;
    var headMap = {};
    plugin.heads.forEach(function(head) {
        // Calculate head name if not specified
        if (typeof(head.name) === 'undefined') {
            head.name = 'anonymousHydraHead' + anonymousHeadCount;
            anonymousHeadCount++;
        }

        if (headMap.hasOwnProperty(head.name)) {
            throw new DuplicateHydraHeadNameException(head.name);
        }
        headMap[head.name] = head;
    });
    this._plugins.push({headMap: headMap, plugin: plugin});
};
Hydra.prototype.registerPluginObject = function(plugin) {
    if (! this._validatePluginName(plugin.name))
        throw new InvalidHydraPluginException("Invalid plugin name '" +
                                              plugin.name + "'");
    if (typeof(plugin.heads) === 'undefined' || !plugin.heads.length)
        throw new InvalidHydraPluginException("Plugin doesn't have any heads");

    this._registerPluginObject(plugin);
};
Hydra.prototype.getPluginNames = function() {
    return this.getPlugins().map(function(p) { return p.name; });
};
Hydra.prototype.getPlugins = function() {
    return this._plugins.map(function(v) { return v.plugin; });
};
Hydra.prototype.getPlugin = function(pluginName) {
    var pluginList = this._plugins.filter(function(p) {
                         return p.plugin.name === pluginName;
                     });
    if (pluginList.length) {
        return pluginList[0].plugin;
    }
    throw new HydraPluginNotFoundException(pluginName);
};
Hydra.prototype.handle = function(req, res, cb) {
    var handled = false;
    outerloop:
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        var plugin = this._plugins[i].plugin;
        for (var j = 0, len2 = plugin.heads.length; j < len2; j++) {
            if (plugin.heads[j].canHandle(req.url)) {
                res.statusCode = 200;
                plugin.heads[j].handle(req, res, cb);
                handled = true;
                break outerloop;
            }
        }
    }
    if (! handled) {
        res.statusCode = 404;
        res.send("Not Found");
    }
};
Hydra.prototype.findHead = function(pluginName, headName) {
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === pluginName) {
            var head = this._plugins[i].headMap[headName];
            if (typeof(head) === 'undefined') {
                throw new HydraHeadNotFoundException(pluginName, headName);
            } else {
                return head;
            }
        }
    }
    throw new HydraHeadNotFoundException(pluginName, headName);
};
Hydra.prototype.detachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).detach();
};
Hydra.prototype.attachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).attach();
};
Hydra.prototype.addPluginLoadPath = function(path) {
    this._pluginLoadPath.unshift(path);
};
// Return an object with keys 'module', 'config' and 'name'. The
// 'config' value is another object with keys 'path', 'hydra' and any
// other values from the configuration. It throws an exception
// HydraPluginNotFoundException if the plugin could not be found
Hydra.prototype.requirePlugin = function(name, config, opts) {
    opts = opts || {};
    var rootDir = fs.realpathSync(opts.rootDir || '');
    var plugin = {};
    var stat = undefined, fullPath;
    for (var i = 0, len = this._pluginLoadPath.length; i < len; i++) {
        try {
            fullPath = rootDir + this._pluginLoadPath[i] + '/' + name;
            stat = fs.statSync(fullPath);
        } catch (e) {
            // It's ok if the plugin is not in this directory
            if (e.code !== 'ENOENT') {
                throw e;
            }
        }
        if (stat && stat.isDirectory()) {
            plugin.module = require(fullPath);
            break;
        }
    }
    if (plugin.module) {
        plugin.config = {hydra: this, path: fullPath};
        for (var p in config) plugin.config[p] = config[p];
        return plugin;
    } else {
        throw new HydraPluginNotFoundException(name);
    }
};

function headTypeToConstructor(headType) {
    var headTypeMap = {
        'generic': HydraHead,
        'static': HydraHeadStatic,
        'filesystem': HydraHeadFilesystem,
        'proxy': HydraHeadProxy
    };
    return headTypeMap[headType];
}

function summonHydraBodyParts(bodyPartDefinition) {
    if (typeof(bodyPartDefinition.heads) === 'undefined') {
        throw new InvalidHydraPluginException();
    } else {
        var bodyParts = {};
        bodyParts.heads =
            bodyPartDefinition.heads.map(function(part) {
                var params = {};
                for (var i in part) {
                    if (part.hasOwnProperty(i)) params[i] = part[i];
                }

                var constructorFunction = headTypeToConstructor(part.type);
                if (typeof(constructorFunction) === 'function') {
                    return new constructorFunction(params);
                } else {
                    throw new InvalidHydraPluginException("Unknown head type '" + part.type + "'");
                }
            });
        return bodyParts;
    }
}

exports.Hydra                = Hydra;
exports.summonHydraBodyParts = summonHydraBodyParts;
exports.serveStaticFile = serveStaticFile;
exports.proxyRequest = proxyRequest;
<commit_msg>Small refactoring in the handle method<commit_after>var fs = require('fs');
var HydraHead           = require('./hydraHead.js').HydraHead,
    HydraHeadStatic     = require('./hydraHead.js').HydraHeadStatic,
    HydraHeadFilesystem = require('./hydraHead.js').HydraHeadFilesystem,
    HydraHeadProxy      = require('./hydraHead.js').HydraHeadProxy;
var serveStaticFile = require('./hydraUtils.js').serveStaticFile,
    proxyRequest    = require('./hydraUtils.js').proxyRequest;

var InvalidHydraPluginException = function(message) {
    this.name    = "InvalidHydraPluginException";
    this.message = message || 'Invalid or incomplete plugin';
};
InvalidHydraPluginException.prototype.toString = function() {
    return "InvalidHydraPluginException";
};

var DuplicateHydraPluginException = function(message) {
    this.name    = "DuplicateHydraPluginException";
    this.message = message || 'Duplicate or incomplete plugin';
};
DuplicateHydraPluginException.prototype.toString = function() {
    return "DuplicateHydraPluginException";
};

var DuplicateHydraHeadNameException = function(head) {
    this.name    = "DuplicateHydraHeadNameException";
    this.message = 'Duplicate Hydra head name "' + head + '"';
};
DuplicateHydraHeadNameException.prototype.toString = function() {
    return "DuplicateHydraHeadNameException";
};

var HydraHeadNotFoundException = function(pluginName, headName) {
    this.name    = "HydraHeadNotFoundException";
    this.message = 'Could not find the given head ("' + pluginName +
            '" / "' + headName + '")';
};
HydraHeadNotFoundException.prototype.toString = function() {
    return "HydraHeadNotFoundException";
};

var HydraPluginNotFoundException = function(pluginName) {
    this.name    = "HydraPluginNotFoundException";
    this.message = 'Could not find the given plugin ("' + pluginName + '")';
};
HydraPluginNotFoundException.prototype.toString = function() {
    return "HydraPluginNotFoundException";
};

var Hydra = function() {
    this._plugins = [];
    this._headMap = {};
    this._count = 0;
    // The first slash in "/./hydra..." is needed because this list
    // will always be appended to an absolute path (the current
    // directory or something else)
    this._pluginLoadPath = ['/./hydra/plugins',
                            '/usr/local/share/hydra/plugins',
                            '/usr/share/hydra/plugins'];
    var adminPlugin = require('./plugins/admin.js');
    adminPlugin.heads = adminPlugin.getBodyParts({hydra: this});
    this._registerPluginObject(adminPlugin);
};
Hydra.prototype._validatePluginName = function(pluginName) {
    return (typeof(pluginName) === 'string' &&
                pluginName.match(new RegExp('^[a-z0-9_-]+$', 'i')));
};
Hydra.prototype._registerPluginObject = function(plugin) {
    var name = plugin.name;
    if (this._plugins.some(function(v) { return v.plugin.name === name; })) {
        throw new DuplicateHydraPluginException();
    }

    var self = this;
    var anonymousHeadCount = 0;
    var headMap = {};
    plugin.heads.forEach(function(head) {
        // Calculate head name if not specified
        if (typeof(head.name) === 'undefined') {
            head.name = 'anonymousHydraHead' + anonymousHeadCount;
            anonymousHeadCount++;
        }

        if (headMap.hasOwnProperty(head.name)) {
            throw new DuplicateHydraHeadNameException(head.name);
        }
        headMap[head.name] = head;
    });
    this._plugins.push({headMap: headMap, plugin: plugin});
};
Hydra.prototype.registerPluginObject = function(plugin) {
    if (! this._validatePluginName(plugin.name))
        throw new InvalidHydraPluginException("Invalid plugin name '" +
                                              plugin.name + "'");
    if (typeof(plugin.heads) === 'undefined' || !plugin.heads.length)
        throw new InvalidHydraPluginException("Plugin doesn't have any heads");

    this._registerPluginObject(plugin);
};
Hydra.prototype.getPluginNames = function() {
    return this.getPlugins().map(function(p) { return p.name; });
};
Hydra.prototype.getPlugins = function() {
    return this._plugins.map(function(v) { return v.plugin; });
};
Hydra.prototype.getPlugin = function(pluginName) {
    var pluginList = this._plugins.filter(function(p) {
                         return p.plugin.name === pluginName;
                     });
    if (pluginList.length) {
        return pluginList[0].plugin;
    }
    throw new HydraPluginNotFoundException(pluginName);
};
Hydra.prototype.headForPath = function(url) {
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        var plugin = this._plugins[i].plugin;
        for (var j = 0, len2 = plugin.heads.length; j < len2; j++) {
            if (plugin.heads[j].canHandle(url)) {
                return {plugin: plugin, head: plugin.heads[j]};
            }
        }
    }
    return undefined;
};
Hydra.prototype.handle = function(req, res, cb) {
    var r = this.headForPath(req.url);
    if (typeof(r) !== 'undefined') {
        res.statusCode = 200;
        r.head.handle(req, res, cb);
    } else {
        res.statusCode = 404;
        res.send("Not Found");
    }
};
Hydra.prototype.findHead = function(pluginName, headName) {
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === pluginName) {
            var head = this._plugins[i].headMap[headName];
            if (typeof(head) === 'undefined') {
                throw new HydraHeadNotFoundException(pluginName, headName);
            } else {
                return head;
            }
        }
    }
    throw new HydraHeadNotFoundException(pluginName, headName);
};
Hydra.prototype.detachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).detach();
};
Hydra.prototype.attachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).attach();
};
Hydra.prototype.addPluginLoadPath = function(path) {
    this._pluginLoadPath.unshift(path);
};
// Return an object with keys 'module', 'config' and 'name'. The
// 'config' value is another object with keys 'path', 'hydra' and any
// other values from the configuration. It throws an exception
// HydraPluginNotFoundException if the plugin could not be found
Hydra.prototype.requirePlugin = function(name, config, opts) {
    opts = opts || {};
    var rootDir = fs.realpathSync(opts.rootDir || '');
    var plugin = {};
    var stat = undefined, fullPath;
    for (var i = 0, len = this._pluginLoadPath.length; i < len; i++) {
        try {
            fullPath = rootDir + this._pluginLoadPath[i] + '/' + name;
            stat = fs.statSync(fullPath);
        } catch (e) {
            // It's ok if the plugin is not in this directory
            if (e.code !== 'ENOENT') {
                throw e;
            }
        }
        if (stat && stat.isDirectory()) {
            plugin.module = require(fullPath);
            break;
        }
    }
    if (plugin.module) {
        plugin.config = {hydra: this, path: fullPath};
        for (var p in config) plugin.config[p] = config[p];
        return plugin;
    } else {
        throw new HydraPluginNotFoundException(name);
    }
};

function headTypeToConstructor(headType) {
    var headTypeMap = {
        'generic': HydraHead,
        'static': HydraHeadStatic,
        'filesystem': HydraHeadFilesystem,
        'proxy': HydraHeadProxy
    };
    return headTypeMap[headType];
}

function summonHydraBodyParts(bodyPartDefinition) {
    if (typeof(bodyPartDefinition.heads) === 'undefined') {
        throw new InvalidHydraPluginException();
    } else {
        var bodyParts = {};
        bodyParts.heads =
            bodyPartDefinition.heads.map(function(part) {
                var params = {};
                for (var i in part) {
                    if (part.hasOwnProperty(i)) params[i] = part[i];
                }

                var constructorFunction = headTypeToConstructor(part.type);
                if (typeof(constructorFunction) === 'function') {
                    return new constructorFunction(params);
                } else {
                    throw new InvalidHydraPluginException("Unknown head type '" + part.type + "'");
                }
            });
        return bodyParts;
    }
}

exports.Hydra                = Hydra;
exports.summonHydraBodyParts = summonHydraBodyParts;
exports.serveStaticFile = serveStaticFile;
exports.proxyRequest = proxyRequest;
<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var app = express();
var http = require('http');
var Q = require('q');

var MOVE_WAIT = parseInt(process.env.MOVE_WAIT) || 10000;
var CAM_IP = '192.168.178.54';
var CAM_CREDENTIALS = 'root:shIt7Bu8';
var CAM_RES_W = 704;
var CAM_RES_H = 576;
var CAM_FACTOR_X = parseInt(process.env.CAM_FACTOR) || 10;
var CAM_FACTOR_Y = parseInt(process.env.CAM_FACTOR) || 12;
var CAM_START_POS = {
  x: 50,
  y: -30
};

var lastMotionTime;
var schedulePositionResetId;

var extractPosition = function(req) {
  console.log('Query Params: ' + JSON.stringify(req.query));
  if (!req.query || !req.query.x || !req.query.y) {
    return;
  }
  return {
    x: Math.round(-(CAM_RES_W / 2 - req.query.x) / CAM_FACTOR_X),
    y: Math.round((CAM_RES_H / 2 - req.query.y) / CAM_FACTOR_Y)
  };
};

var moveCameraRelative = function(newPosition) {
  var deferred = Q.defer();
  http.get('http://' + CAM_CREDENTIALS + '@' + CAM_IP +
    '/axis-cgi/com/ptz.cgi?rpan=' + newPosition.x +
    '&rtilt=' + newPosition.y,
    function() {
      console.log('Camera moved.');
      deferred.resolve();
    }).on('error', function(e) {
    console.log("Got error: " + e.message);
    deferred.reject();
  });
  return deferred.promise;
};

var moveCamera = function(newPosition) {
  var deferred = Q.defer();
  http.get('http://' + CAM_CREDENTIALS + '@' + CAM_IP +
    '/axis-cgi/com/ptz.cgi?pan=' + newPosition.x +
    '&tilt=' + newPosition.y,
    function() {
      console.log('Camera moved.');
      deferred.resolve();
    }).on('error', function(e) {
    console.log("Got error: " + e.message);
    deferred.reject();
  });
  return deferred.promise;
};

var schedulePositionReset = function() {
  console.log('Camera position reset scheduled.');
  if (schedulePositionResetId) {
    clearTimeout(schedulePositionResetId);
  }
  schedulePositionResetId = setTimeout(function() {
    moveCamera(CAM_START_POS).then(function() {
      console.log('Camera position reset!');
    });
  }, 60000);
};

app.get('/', function(req, res) {
  var now = (new Date()).getTime();
  if (!lastMotionTime || lastMotionTime + MOVE_WAIT < now) {
    lastMotionTime = now;

    var newPosition = extractPosition(req);
    console.log('New position: ' + JSON.stringify(newPosition));
    if (newPosition) {
      schedulePositionReset();
      moveCameraRelative(newPosition).then(function() {
        return res.status(200).send('Camera moved.');
      }, function() {
        return res.status(500);
      });
    } else {
      console.log('New position missing.');
      return res.status(500).send('New position missing.');
    }
  } else {
    console.log('Skipping request.');
    return res.status(200).send('Skipping request.');
  }
});

var server = app.listen(3000, function() {
  moveCamera(CAM_START_POS).then(function() {
    console.log('Camera position reset!');
  });
  var port = server.address().port;
  console.log('Server listening at http://127.0.0.1:%s', port);
  return;
});
<commit_msg>small fix<commit_after>'use strict';

var express = require('express');
var app = express();
var http = require('http');
var Q = require('q');

var MOVE_WAIT = parseInt(process.env.MOVE_WAIT) || 10000;
var CAM_IP = '192.168.178.54';
var CAM_CREDENTIALS = 'root:shIt7Bu8';
var CAM_RES_W = 704;
var CAM_RES_H = 576;
var CAM_FACTOR_X = parseInt(process.env.CAM_FACTOR) || 10;
var CAM_FACTOR_Y = parseInt(process.env.CAM_FACTOR) || 12;
var CAM_START_POS = {
  x: 50,
  y: -30
};

var lastMotionTime;
var schedulePositionResetId;

var extractPosition = function(req) {
  console.log('Query Params: ' + JSON.stringify(req.query));
  if (!req.query || !req.query.x || !req.query.y) {
    return;
  }
  return {
    x: Math.round(-(CAM_RES_W / 2 - req.query.x) / CAM_FACTOR_X),
    y: Math.round((CAM_RES_H / 2 - req.query.y) / CAM_FACTOR_Y)
  };
};

var moveCameraRelative = function(newPosition) {
  var deferred = Q.defer();
  http.get('http://' + CAM_CREDENTIALS + '@' + CAM_IP +
    '/axis-cgi/com/ptz.cgi?rpan=' + newPosition.x +
    '&rtilt=' + newPosition.y,
    function() {
      console.log('Camera moved.');
      deferred.resolve();
    }).on('error', function(e) {
    console.log("Got error: " + e.message);
    deferred.reject();
  });
  return deferred.promise;
};

var moveCamera = function(newPosition) {
  var deferred = Q.defer();
  http.get('http://' + CAM_CREDENTIALS + '@' + CAM_IP +
    '/axis-cgi/com/ptz.cgi?pan=' + newPosition.x +
    '&tilt=' + newPosition.y,
    function() {
      console.log('Camera moved.');
      deferred.resolve();
    }).on('error', function(e) {
    console.log("Got error: " + e.message);
    deferred.reject();
  });
  return deferred.promise;
};

var schedulePositionReset = function() {
  console.log('Camera position reset scheduled.');
  if (schedulePositionResetId) {
    clearTimeout(schedulePositionResetId);
  }
  schedulePositionResetId = setTimeout(function() {
    var now = (new Date()).getTime();
    lastMotionTime = now;
    moveCamera(CAM_START_POS).then(function() {
      console.log('Camera position reset!');
    });
  }, 30000);
};

app.get('/', function(req, res) {
  var now = (new Date()).getTime();
  if (!lastMotionTime || lastMotionTime + MOVE_WAIT < now) {
    lastMotionTime = now;

    var newPosition = extractPosition(req);
    console.log('New position: ' + JSON.stringify(newPosition));
    if (newPosition) {
      schedulePositionReset();
      moveCameraRelative(newPosition).then(function() {
        return res.status(200).send('Camera moved.');
      }, function() {
        return res.status(500);
      });
    } else {
      console.log('New position missing.');
      return res.status(500).send('New position missing.');
    }
  } else {
    console.log('Skipping request.');
    return res.status(200).send('Skipping request.');
  }
});

var server = app.listen(3000, function() {
  moveCamera(CAM_START_POS).then(function() {
    console.log('Camera position reset!');
  });
  var port = server.address().port;
  console.log('Server listening at http://127.0.0.1:%s', port);
  return;
});
<|endoftext|>


<commit_before>/*
 * iduri
 * https://spmjs.org
 *
 * Hsiaoming Yang <me@lepture.com>
 * Nuintun <nuintun@qq.com>
 */
// path
var template,
    path = require('path'),
    FILE_EXT = ['js', 'css'], // file extension
    RELPATH_RE = /^\.{1,2}[\\/]/, // relative path
    RESOLVE_RE = /^([a-z][a-z0-9\-]*(?:\/|\.))?([a-zA-Z][a-zA-Z0-9\-]*)((?:@|#).*)?$/; // resolve

// micro template engine
template = (function (){
    var TMPLENG_RE = /\{\{\s*(.*?)\s*\}\}/g;

    function getData(source, key){
        var keys = key.split('.');

        for (var i = 0, len = keys.length; i < len; i++) {
            key = keys[i];

            if (source && source.hasOwnProperty(key)) {
                source = source[key];
                break;
            }
        }

        return source || '';
    }

    return function (format, data){
        return format.replace(TMPLENG_RE, function (holder, key){
            return getData(data, key);
        });
    }
}());

// add support file extension
exports.addFileExt = function (ext){
    if (typeof ext !== 'string' || ext === 'js'
        || ext === 'css' || FILE_EXT.indexOf(ext) !== -1) return;

    FILE_EXT.push(ext);
};

// remove support file extension
exports.removeFileExt = function (ext){
    var index;

    if (typeof ext !== 'string' || ext === 'js' || ext === 'css') return;

    index = FILE_EXT.indexOf(ext);

    if (index === -1) return;

    FILE_EXT.splice(index, 1);
};

// is unknown file extension
function unknownFile(uri){
    for (var i = 0, len = FILE_EXT.length; i < len; i++) {
        if (uri.lastIndexOf('.' + FILE_EXT[i]) !== -1) return false;
    }

    return true;
}

// transform path to unix mode
function unixPath(uri){
    var isCurDir = /^\.[\\/]/.test(uri);

    uri = path.normalize(uri);
    uri = isCurDir ? './' + uri : uri;
    uri = uri.replace(/(:[\\/])/g, '$1/');

    return uri.replace(/\\/g, '/');
}
exports.unixPath = unixPath;

// resolve uri to meta info
exports.resolve = function (uri){
    // family/name@version
    // family/name#version
    // family.name@version
    // family.name#version
    var m, family, name, version;

    m = uri.match(RESOLVE_RE);

    if (!m) return null;

    family = m[1] || '';
    family = family.replace(/\/|\.$/, '');
    name = m[2] || '';
    version = m[3] || '';
    version = version.replace(/^@|#/, '');

    if (!family) {
        if (/^[a-z][a-z0-9]*$/.test(name)) {
            family = name;
        } else {
            return null;
        }
    }

    if (!family && !name && !version) return null;

    return {
        family: family,
        name: name,
        version: version
    };
};

// normalize uri
// make sure the uri to be pretty,
// for example a//b/../c should be a/c.
function normalize(uri){
    var lastChar, searchIndex;

    uri = unixPath(uri);

    lastChar = uri.slice(-1);

    if (lastChar === '/') return uri;

    // if it ends with #, we should return the uri without #
    if (lastChar === '#') return uri.slice(0, -1);

    // if it has with ?, we should return the uri without search params
    if ((searchIndex = uri.indexOf('?')) !== -1) return uri.slice(0, searchIndex);

    // TODO ext logical
    return uri;
}
exports.normalize = normalize;

// join path
exports.join = function (){
    return unixPath(path.join.apply(path, arguments));
};

// dirname
exports.dirname = function (uri){
    return unixPath(path.dirname(uri));
};

// basename
exports.basename = function (uri){
    return unixPath(path.basename(uri));
};

// this is very different from node's path.relative.
// if uri starts with /, it's absolute uri, we don't relative it.
// if base is `path/to/a', uri is `static/a.js`
// relative is: ../../../static/a.js
exports.relative = function (base, uri){
    var bits, dots, len;

    uri = unixPath(uri);

    if (uri.charAt(0) === '/') return uri;

    dots = '';
    bits = normalize(base).split('/');
    len = bits.length;

    if (len > 1) {
        for (var i = 0; i < len - 1; i++) {
            dots += '../';
        }

        return dots + uri;
    }

    return uri;
};

// base is `arale/base/1.0.0/parser`
// uri is `./base`
// the result should be `arale/base/1.0.0/base`
exports.absolute = function (base, uri){
    if (!RELPATH_RE.test(uri)) return unixPath(uri);
    uri = path.join(path.dirname(base), uri);
    return unixPath(uri);
};

// this is very different from node's path.extname.
exports.extname = function (uri){
    var index, ext;

    if (uri.slice(-1) === '#') {
        uri = uri.slice(0, -1);
    }

    if ((index = uri.indexOf('?')) !== -1) {
        uri = uri.substring(0, index);
    }

    ext = path.extname(uri);

    // default ext is js
    return ext ? ext : '.js';
};

exports.appendext = function (uri){
    // Add the default `.js` extension except that the uri ends with `#` or has '?'
    if (uri.slice(-1) !== '#' && uri.indexOf('?') === -1 && unknownFile(uri)) {
        uri += '.js';
    }

    return unixPath(uri);
};

// parse alias
function getAlias(pkg){
    return pkg.alias || {};
}

exports.parseAlias = function (pkg, name){
    var alias;

    // relative name: ./class
    if (RELPATH_RE.test(name)) {
        name = name.replace(/\.js$/i, '');
    }

    alias = getAlias(pkg);

    if (alias.hasOwnProperty(name)) {
        name = alias[name];
    }

    return name;
};

exports.isAlias = function (pkg, name){
    var alias = getAlias(pkg);
    return alias.hasOwnProperty(name);
};

// parse id
exports.idFromPackage = function (pkg, filename, format){
    if (filename && !format && filename.indexOf('{{') !== -1) {
        format = filename;
        filename = '';
    }

    if (!filename) {
        filename = pkg.filename || '';
    }

    if (RELPATH_RE.test(filename)) {
        return filename.replace(/\.js$/i, '');
    }

    format = format || '{{family}}/{{name}}/{{version}}/{{filename}}';
    pkg.filename = filename.replace(/\.js$/i, '');

    return template(format, pkg);
};<commit_msg>normalize id from package<commit_after>/*
 * iduri
 * https://spmjs.org
 *
 * Hsiaoming Yang <me@lepture.com>
 * Nuintun <nuintun@qq.com>
 */
// path
var template,
    path = require('path'),
    FILE_EXT = ['js', 'css'], // file extension
    RELPATH_RE = /^\.{1,2}[\\/]/, // relative path
    RESOLVE_RE = /^([a-z][a-z0-9\-]*(?:\/|\.))?([a-zA-Z][a-zA-Z0-9\-]*)((?:@|#).*)?$/; // resolve

// micro template engine
template = (function (){
    var TMPLENG_RE = /\{\{\s*(.*?)\s*\}\}/g;

    function getData(source, key){
        var keys = key.split('.');

        for (var i = 0, len = keys.length; i < len; i++) {
            key = keys[i];

            if (source && source.hasOwnProperty(key)) {
                source = source[key];
                break;
            }
        }

        return source || '';
    }

    return function (format, data){
        return format.replace(TMPLENG_RE, function (holder, key){
            return getData(data, key);
        });
    }
}());

// add support file extension
exports.addFileExt = function (ext){
    if (typeof ext !== 'string' || ext === 'js'
        || ext === 'css' || FILE_EXT.indexOf(ext) !== -1) return;

    FILE_EXT.push(ext);
};

// remove support file extension
exports.removeFileExt = function (ext){
    var index;

    if (typeof ext !== 'string' || ext === 'js' || ext === 'css') return;

    index = FILE_EXT.indexOf(ext);

    if (index === -1) return;

    FILE_EXT.splice(index, 1);
};

// is unknown file extension
function unknownFile(uri){
    for (var i = 0, len = FILE_EXT.length; i < len; i++) {
        if (uri.lastIndexOf('.' + FILE_EXT[i]) !== -1) return false;
    }

    return true;
}

// transform path to unix mode
function unixPath(uri){
    var isCurDir = /^\.[\\/]/.test(uri);

    uri = path.normalize(uri);
    uri = isCurDir ? './' + uri : uri;
    uri = uri.replace(/(:[\\/])/g, '$1/');

    return uri.replace(/\\/g, '/');
}
exports.unixPath = unixPath;

// resolve uri to meta info
exports.resolve = function (uri){
    // family/name@version
    // family/name#version
    // family.name@version
    // family.name#version
    var m, family, name, version;

    m = uri.match(RESOLVE_RE);

    if (!m) return null;

    family = m[1] || '';
    family = family.replace(/\/|\.$/, '');
    name = m[2] || '';
    version = m[3] || '';
    version = version.replace(/^@|#/, '');

    if (!family) {
        if (/^[a-z][a-z0-9]*$/.test(name)) {
            family = name;
        } else {
            return null;
        }
    }

    if (!family && !name && !version) return null;

    return {
        family: family,
        name: name,
        version: version
    };
};

// normalize uri
// make sure the uri to be pretty,
// for example a//b/../c should be a/c.
function normalize(uri){
    var lastChar, searchIndex;

    uri = unixPath(uri);

    lastChar = uri.slice(-1);

    if (lastChar === '/') return uri;

    // if it ends with #, we should return the uri without #
    if (lastChar === '#') return uri.slice(0, -1);

    // if it has with ?, we should return the uri without search params
    if ((searchIndex = uri.indexOf('?')) !== -1) return uri.slice(0, searchIndex);

    // TODO ext logical
    return uri;
}
exports.normalize = normalize;

// join path
exports.join = function (){
    return unixPath(path.join.apply(path, arguments));
};

// dirname
exports.dirname = function (uri){
    return unixPath(path.dirname(uri));
};

// basename
exports.basename = function (uri){
    return unixPath(path.basename(uri));
};

// this is very different from node's path.relative.
// if uri starts with /, it's absolute uri, we don't relative it.
// if base is `path/to/a', uri is `static/a.js`
// relative is: ../../../static/a.js
exports.relative = function (base, uri){
    var bits, dots, len;

    uri = unixPath(uri);

    if (uri.charAt(0) === '/') return uri;

    dots = '';
    bits = normalize(base).split('/');
    len = bits.length;

    if (len > 1) {
        for (var i = 0; i < len - 1; i++) {
            dots += '../';
        }

        return dots + uri;
    }

    return uri;
};

// base is `arale/base/1.0.0/parser`
// uri is `./base`
// the result should be `arale/base/1.0.0/base`
exports.absolute = function (base, uri){
    if (!RELPATH_RE.test(uri)) return unixPath(uri);
    uri = path.join(path.dirname(base), uri);
    return unixPath(uri);
};

// this is very different from node's path.extname.
exports.extname = function (uri){
    var index, ext;

    if (uri.slice(-1) === '#') {
        uri = uri.slice(0, -1);
    }

    if ((index = uri.indexOf('?')) !== -1) {
        uri = uri.substring(0, index);
    }

    ext = path.extname(uri);

    // default ext is js
    return ext ? ext : '.js';
};

exports.appendext = function (uri){
    // Add the default `.js` extension except that the uri ends with `#` or has '?'
    if (uri.slice(-1) !== '#' && uri.indexOf('?') === -1 && unknownFile(uri)) {
        uri += '.js';
    }

    return unixPath(uri);
};

// parse alias
function getAlias(pkg){
    pkg = pkg || {};
    return pkg.alias || {};
}

exports.parseAlias = function (pkg, name){
    var alias;

    // relative name: ./class
    if (RELPATH_RE.test(name)) {
        return unixPath(name.replace(/\.js$/i, ''));
    }

    alias = getAlias(pkg);

    if (alias.hasOwnProperty(name)) {
        name = alias[name];
    }

    return unixPath(name);
};

exports.isAlias = function (pkg, name){
    var alias = getAlias(pkg);
    return alias.hasOwnProperty(name);
};

// parse id
exports.idFromPackage = function (pkg, filename, format){
    if (filename && !format && filename.indexOf('{{') !== -1) {
        format = filename;
        filename = '';
    }

    if (!filename) {
        filename = pkg.filename || '';
    }

    if (RELPATH_RE.test(filename)) {
        return filename.replace(/\.js$/i, '');
    }

    format = format || '{{family}}/{{name}}/{{version}}/{{filename}}';
    pkg.filename = filename.replace(/\.js$/i, '');

    return unixPath(template(format, pkg));
};<|endoftext|>


<commit_before>goog.provide('lime.events.EventDispatcher');

goog.require('lime.events.Event');

/**
 * EventDispatcher object. Deals with event handlers
 * @param {lime.Director} director Director object.
 * @constructor
 */
lime.events.EventDispatcher = function(director) {
    this.director = director;
    this.handlers = {};
    this.swallows = {};

};

/**
 * Register the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to listen.
 */
lime.events.EventDispatcher.prototype.register = function(node, eventType) {
    if (!goog.isDef(this.handlers[eventType])) {
        this.handlers[eventType] = [node];
        //base element switch here because safari fires touchend on
        //dom tree changes otherwise
        goog.events.listen(eventType.substring(0, 5) == 'touch' && node!=this.director ?
            document : (eventType.substring(0, 3) == 'key' ?
            window : this.director.domElement.parentNode), eventType,
            this, false, this);
    }
    else {
        if (!goog.array.contains(this.handlers[eventType], node)) {
            this.handlers[eventType].push(node);
            this.handlers[eventType].sort(lime.Node.compareNode);
        }
    }
};

/**
 * Release the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to release.
 */
lime.events.EventDispatcher.prototype.release = function(node, eventType) {
    if (goog.isDef(this.handlers[eventType])) {
         goog.array.remove(this.handlers[eventType], node);
         if (!this.handlers[eventType].length) {
             goog.events.unlisten(this.director.domElement.parentNode,
                 eventType, this, false, this);
            delete this.handlers[eventType];
         }
    }
};

/**
 * Update order of handler nodes. Called on tree changes.
 * @param {lime.Node} node Node that has changed.
 */
lime.events.EventDispatcher.prototype.updateDispatchOrder = function(node){
    for(var eventType in this.handlers){
        var handlers = this.handlers[eventType];
        if(goog.array.contains(handlers,node)){
            handlers.sort(lime.Node.compareNode);
        }
    }
}

/**
 * Setup swallow rule for an event. Swallow means that next events from
 * same interaction will go straight to the handler
 * @param {lime.events.Event} e Event.
 * @param {string} type Event type.
 * @param {function(lime.events.Event)} handler Function to call.
 */
lime.events.EventDispatcher.prototype.swallow = function(e, type, handler) {
   /*
   // don't remember why this check was needed
   if (e.type != 'mousedown' && e.type != 'touchstart' &&
        e.type != 'touchmove' && e.type != 'keydown') return;*/
    var id = e.identifier;
    if (!goog.isDef(this.swallows[id])) {
        this.swallows[id] = [];
    }
    this.swallows[id].push([e.targetObject, type, handler]);
    //console.log('listen');
    goog.events.listen(e.targetObject, type, goog.nullFunction);
};

/**
 * Handle DOM event
 * @param {Event} e Event.
 */
lime.events.EventDispatcher.prototype.handleEvent = function(e) {

    if (!goog.isDef(this.handlers[e.type])) return;

    var handlers = this.handlers[e.type].slice(), didhandle = false;

    var touchIndex = 0, doBreak = 0;

    while (!doBreak) {

    var ee = new lime.events.Event(this);
    ee.type = e.type;
    ee.event = e;

    if (e.type.substring(0, 5) == 'touch') {
        var touch = e.getBrowserEvent().changedTouches[touchIndex];
        ee.screenPosition = new goog.math.Coordinate(touch.pageX, touch.pageY);
        ee.identifier = touch.identifier;
        touchIndex++;

        if (touchIndex >= e.getBrowserEvent().changedTouches.length) {
            doBreak = 1;
        }
    }
    else {
        ee.screenPosition = new goog.math.Coordinate(e.clientX, e.clientY);
        doBreak = 1;
    }

    if (goog.isDef(this.swallows[ee.identifier])) {
        var s = this.swallows[ee.identifier];

        for (var i = 0; i < s.length; i++) {
            if (s[i][1] == e.type || (goog.isArray(s[i][1]) &&
                    goog.array.contains(s[i][1], e.type))) {

                var handler = s[i][0];
                ee.targetObject = handler;
                ee.position = handler.screenToLocal(ee.screenPosition);
                s[i][2].call(handler, ee);
                didhandle = true;
            }
        }
        //handler.dispatchEvent(ee);

        if (e.type == 'touchend' || e.type == 'touchcancel' ||
            e.type == 'mouseup' || e.type == 'keyup') {
            delete ee.targetObject;
            ee.release();
        }
    }
    else {
        for (var i = 0; i < handlers.length; i++) {

            var handler = handlers[i];

            if (this.director.getCurrentScene() != handler.getScene() &&
                handler != this.director) continue;

            if (handler.getHidden() || !handler.inTree_) continue;

            ee.targetObject = handler;

            if (handler.hitTest(ee) || e.type.substring(0, 3) == 'key') {

                ee.targetObject = handler;
                handler.dispatchEvent(ee);
                didhandle = true;

                if (ee.event.propagationStopped_) break;
            }

        }

    }

    }

    if (didhandle)
    e.preventDefault();

};
<commit_msg>Add scroll offset support for screenPosition <commit_after>goog.provide('lime.events.EventDispatcher');

goog.require('lime.events.Event');

/**
 * EventDispatcher object. Deals with event handlers
 * @param {lime.Director} director Director object.
 * @constructor
 */
lime.events.EventDispatcher = function(director) {
    this.director = director;
    this.handlers = {};
    this.swallows = {};

};

/**
 * Register the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to listen.
 */
lime.events.EventDispatcher.prototype.register = function(node, eventType) {
    if (!goog.isDef(this.handlers[eventType])) {
        this.handlers[eventType] = [node];
        //base element switch here because safari fires touchend on
        //dom tree changes otherwise
        goog.events.listen(eventType.substring(0, 5) == 'touch' && node!=this.director ?
            document : (eventType.substring(0, 3) == 'key' ?
            window : this.director.domElement.parentNode), eventType,
            this, false, this);
    }
    else {
        if (!goog.array.contains(this.handlers[eventType], node)) {
            this.handlers[eventType].push(node);
            this.handlers[eventType].sort(lime.Node.compareNode);
        }
    }
};

/**
 * Release the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to release.
 */
lime.events.EventDispatcher.prototype.release = function(node, eventType) {
    if (goog.isDef(this.handlers[eventType])) {
         goog.array.remove(this.handlers[eventType], node);
         if (!this.handlers[eventType].length) {
             goog.events.unlisten(this.director.domElement.parentNode,
                 eventType, this, false, this);
            delete this.handlers[eventType];
         }
    }
};

/**
 * Update order of handler nodes. Called on tree changes.
 * @param {lime.Node} node Node that has changed.
 */
lime.events.EventDispatcher.prototype.updateDispatchOrder = function(node){
    for(var eventType in this.handlers){
        var handlers = this.handlers[eventType];
        if(goog.array.contains(handlers,node)){
            handlers.sort(lime.Node.compareNode);
        }
    }
}

/**
 * Setup swallow rule for an event. Swallow means that next events from
 * same interaction will go straight to the handler
 * @param {lime.events.Event} e Event.
 * @param {string} type Event type.
 * @param {function(lime.events.Event)} handler Function to call.
 */
lime.events.EventDispatcher.prototype.swallow = function(e, type, handler) {
   /*
   // don't remember why this check was needed
   if (e.type != 'mousedown' && e.type != 'touchstart' &&
        e.type != 'touchmove' && e.type != 'keydown') return;*/
    var id = e.identifier;
    if (!goog.isDef(this.swallows[id])) {
        this.swallows[id] = [];
    }
    this.swallows[id].push([e.targetObject, type, handler]);
    //console.log('listen');
    goog.events.listen(e.targetObject, type, goog.nullFunction);
};

/**
 * Handle DOM event
 * @param {Event} e Event.
 */
lime.events.EventDispatcher.prototype.handleEvent = function(e) {

    if (!goog.isDef(this.handlers[e.type])) return;

    var handlers = this.handlers[e.type].slice(), didhandle = false;

    var touchIndex = 0, doBreak = 0;

    while (!doBreak) {

    var ee = new lime.events.Event(this);
    ee.type = e.type;
    ee.event = e;

    if (e.type.substring(0, 5) == 'touch') {
        var touch = e.getBrowserEvent().changedTouches[touchIndex];
        ee.screenPosition = new goog.math.Coordinate(touch.pageX, touch.pageY);
        ee.identifier = touch.identifier;
        touchIndex++;

        if (touchIndex >= e.getBrowserEvent().changedTouches.length) {
            doBreak = 1;
        }
    }
    else {
        ee.screenPosition = new goog.math.Coordinate(
            e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
            e.clientY + document.body.scrollTop + document.documentElement.scrollTop
        );
        doBreak = 1;
    }

    if (goog.isDef(this.swallows[ee.identifier])) {
        var s = this.swallows[ee.identifier];

        for (var i = 0; i < s.length; i++) {
            if (s[i][1] == e.type || (goog.isArray(s[i][1]) &&
                    goog.array.contains(s[i][1], e.type))) {

                var handler = s[i][0];
                ee.targetObject = handler;
                ee.position = handler.screenToLocal(ee.screenPosition);
                s[i][2].call(handler, ee);
                didhandle = true;
            }
        }
        //handler.dispatchEvent(ee);

        if (e.type == 'touchend' || e.type == 'touchcancel' ||
            e.type == 'mouseup' || e.type == 'keyup') {
            delete ee.targetObject;
            ee.release();
        }
    }
    else {
        for (var i = 0; i < handlers.length; i++) {

            var handler = handlers[i];

            if (this.director.getCurrentScene() != handler.getScene() &&
                handler != this.director) continue;

            if (handler.getHidden() || !handler.inTree_) continue;

            ee.targetObject = handler;

            if (handler.hitTest(ee) || e.type.substring(0, 3) == 'key') {

                ee.targetObject = handler;
                handler.dispatchEvent(ee);
                didhandle = true;

                if (ee.event.propagationStopped_) break;
            }

        }

    }

    }

    if (didhandle)
    e.preventDefault();

};
<|endoftext|>


<commit_before>var commander = require('commander');
var fs = require('fs');
var path = require('path');

commander.
  option('-p, --port <port>', 'Port to run on', Number).
  parse(process.argv);

require('http').createServer(function (request, response) {
  request.addListener('end', function() {
    console.log(request.url);
    // Backwards-compatible support for wordpress, because wordpress allows
    // URLs like `/2013/06/06/61/` to map to the blog post `61`
    if (request.url.length > 1 &&
        request.url.charAt(request.url.length - 1) === '/') {
      request.url = request.url.substr(0, request.url.length - 1);
    }

    var p = path.join('./bin', request.url);
    fs.stat(p, function(err, stats) {
      if (err || !stats) {
        response.writeHead(404, {
          'Cache-Control': 'max-age=7200',
          'Content-Type': 'text/plain'
        });
        return response.end("Not found");
      }
      if (stats.isFile()) {
        var type = path.extname(p);
        response.writeHead(200, {
          'Cache-Control': 'max-age=7200',
          'Content-Type': type || 'text/html'
        });
        fs.createReadStream(p).pipe(response);
      } else {
        var indexPath = path.join(p, 'index');
        fs.stat(indexPath, function(err, stats) {
          if (err || !stats || !stats.isFile()) {
            response.writeHead(404, {
              'Cache-Control': 'max-age=7200',
              'Content-Type': 'text/plain'
            });
            return response.end("Not found");
          }

          response.writeHead(200, {
            'Cache-Control': 'max-age=7200',
            'Content-Type': type || 'text/html'
          });
          fs.createReadStream(indexPath).pipe(response);
        });
      }
    });
  }).resume();
}).listen(commander.port || 8080);

console.log('Server listening on port ' + (commander.port || 8080));
<commit_msg>Can now set port with environment var<commit_after>var commander = require('commander');
var fs = require('fs');
var path = require('path');

commander.
  option('-p, --port <port>', 'Port to run on', Number).
  parse(process.argv);

require('http').createServer(function (request, response) {
  request.addListener('end', function() {
    console.log(request.url);
    // Backwards-compatible support for wordpress, because wordpress allows
    // URLs like `/2013/06/06/61/` to map to the blog post `61`
    if (request.url.length > 1 &&
        request.url.charAt(request.url.length - 1) === '/') {
      request.url = request.url.substr(0, request.url.length - 1);
    }

    var p = path.join('./bin', request.url);
    fs.stat(p, function(err, stats) {
      if (err || !stats) {
        response.writeHead(404, {
          'Cache-Control': 'max-age=7200',
          'Content-Type': 'text/plain'
        });
        return response.end("Not found");
      }
      if (stats.isFile()) {
        var type = path.extname(p);
        response.writeHead(200, {
          'Cache-Control': 'max-age=7200',
          'Content-Type': type || 'text/html'
        });
        fs.createReadStream(p).pipe(response);
      } else {
        var indexPath = path.join(p, 'index');
        fs.stat(indexPath, function(err, stats) {
          if (err || !stats || !stats.isFile()) {
            response.writeHead(404, {
              'Cache-Control': 'max-age=7200',
              'Content-Type': 'text/plain'
            });
            return response.end("Not found");
          }

          response.writeHead(200, {
            'Cache-Control': 'max-age=7200',
            'Content-Type': type || 'text/html'
          });
          fs.createReadStream(indexPath).pipe(response);
        });
      }
    });
  }).resume();
}).listen(process.env.TCB_PORT || commander.port || 8080);

console.log('Server listening on port ' + (process.env.TCB_PORT || commander.port || 8080));
<|endoftext|>


<commit_before>/**
 *
 * @author Andriy Oblivantsev <eslider@gmail.com>
 * @copyright 08.04.2015 by WhereGroup GmbH & Co. KG
 */
/**
 *
 * @author Andriy Oblivantsev <eslider@gmail.com>
 * @copyright 05.04.15 by WhereGroup GmbH & Co. KG
 */
(function($) {

    /**
     * Check if object has a key
     *
     * @param obj
     * @param key
     * @returns {boolean}
     */
    function has(obj, key) {
        return typeof obj[key] !== 'undefined';
    }

    /**
     * Add jquery events to element by declration
     *
     * @param element
     * @param declaration
     */
    function addEvents(element, declaration) {
        $.each(declaration, function(k, value) {
            if(typeof value == 'function') {
                element.on(k, value);
            }
        });
    }

    $.widget('mapbender.generateElements', {
        options:      {},
        declarations: {
            popup: function(item, declarations, widget) {
                var popup = $("
");
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        popup.append(widget.genElement(item));
                    });
                }
                window.setTimeout(function() {
                    popup.popupDialog(item)
                }, 1);

                return popup;
            },
            form: function(item, declarations, widget) {
                var form = $('<form/>');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        form.append(widget.genElement(item));
                    })
                }
                return form;
            },
            fluidContainer: function(item, declarations, widget) {
                var container = $('
');
                var hbox = $('
');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        hbox.append(widget.genElement(item));
                    })
                }
                container.append(hbox);
                return container;
            },
            inline: function(item, declarations, widget) {
                var container = $('
');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        container.append(widget.genElement(item));
                    })
                }
                return container;
            },
            html:      function(item, declarations) {
                var container = $('
');
                if (typeof item === 'string'){
                    container.html(item);
                }else if(has(item,'html')){
                    container.html(item.html);
                }else{
                    container.html(JSON.stringify(item));
                }
                return container;
            },
            button:    function(item, declarations) {
                var title = has(item, 'title') ? item.title : 'Submit';
                var button = $('<button class="btn button">' + title + '</button>');
                return button;
            },
            submit:    function(item, declarations) {
                var button = declarations.button(item, declarations);
                button.attr('type', 'submit');
                return button;
            },
            input:     function(item, declarations) {
                var inputField = $('<input class="form-control"/>');
                var container = $('
');
                var type = has(declarations, 'type') ? declarations.type : 'text';
                var icon = '';

                inputField.attr('type', type);
                inputField.data('declaration',item);

                if(has(item, 'name')) {
                    inputField.attr('name', item.name);
                }

                if(has(item, 'placeholder')) {
                    inputField.attr('placeholder', item.placeholder);
                }

                if(has(item, 'value')) {
                    inputField.val(item.value);
                }

                if(has(item, 'text')) {
                    container.append(declarations.label(item, declarations));
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    inputField.data('warn',function(){
                        var hasValue = $.trim(inputField.val()) != '';
                        if(hasValue){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return hasValue;
                    });
                }

                container.append(inputField);
                //container.append(icon);

                return container;
            },
            label:     function(item, declarations) {
                var label = $('');
                if(_.has(item, 'text')) {
                    label.html(item.text);
                }
                if(_.has(item, 'name')) {
                    label.attr('for', item.name);
                }
                return label;
            },
            checkbox:  function(item, declarations) {
                var container = $('
');
                var label = $('');
                var input = $('<input type="checkbox"/>');

                input.data('declaration',item);

                label.append(input);

                if(has(item, 'name')) {
                    input.attr('name', item.name);
                }

                if(has(item, 'value')) {
                    input.val(item.value);
                }

                if(has(item, 'text')) {
                    label.append(item.text);
                }

                if(has(item, 'checked')) {
                    input.attr('checked', "checked");
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    input.data('warn',function(){
                        var isChecked = input.is(':checked');
                        if(isChecked){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return isChecked;
                    });
                }

                container.append(label);
                return container;
            },
            radio:     function(item, declarations) {
                var container = $('
');
                var label = $('');
                var input = $('<input type="radio"/>');

                input.data('declaration',item);

                label.append(input);

                if(has(item, 'name')) {
                    input.attr('name', item.name);
                }

                if(has(item, 'text')) {
                    label.append(item.text);
                }

                if(has(item, 'value')) {
                    input.val(item.value);
                }

                if(has(item, 'checked')) {
                    input.attr('checked', "checked");
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    input.data('warn',function(value){
                        var isChecked = input.is(':checked');
                        if(isChecked){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return isChecked;
                    });
                }

                container.append(label);
                return container;
            },
            formGroup: function(item, declarations, widget) {
                var container = $('
');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        container.append(widget.genElement(item));
                    });
                }
                return container;
            },
            textArea:  function(item, declarations) {
                var input = $('<textarea class="form-control" rows="3"/>');
                input.data('declaration',item);

                if(has(item, 'value')) {
                    input.val(item.value);
                }

                $.each(['name', 'rows', 'placeholder'], function(i, key) {
                    if(has(item, key)) {
                        input.attr(key, item[key]);
                    }
                });

                return input;
            },
            select:    function(item, declarations) {
                var container = $('
');
                var select = $('<select class="form-control"/>');

                select.data('declaration',item);

                $.each(['name'], function(i, key) {
                    if(has(item, key)) {
                        select.attr(key, item[key]);
                    }
                });

                if(has(item, 'multiple') && item.multiple) {
                    select.attr('multiple', 'multiple');
                }

                if(has(item, 'options')) {
                    $.each(item.options, function(value, title) {
                        var option = $("<option/>");
                        option.attr('value', value);
                        option.html(title);
                        option.data(this);
                        select.append(option);
                    });
                }

                if(has(item, 'value')) {
                    window.setTimeout(function(){
                        select.val(item.value);
                    },1)
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    select.data('warn',function(){
                        var hasValue = $.trim(select.val()) != '';
                        if(hasValue){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return hasValue;
                    });
                }

                container.append(select);

                return container;
            },
            file:      function(item, declarations) {
                var container = $('
');
                var label = $('');
                var input = $('<input type="file"/>');

                input.data('declaration',item);

                if(has(item, 'name') && item.multiple) {
                    label.attr('for', item.name);
                    input.attr('name', item.name);
                }

                if(has(item, 'text')) {
                    label.html(item.text);
                    container.append(label);
                }

                container.append(input);
                return container;
            },
            tabs: function(item, declarations, widget) {
                var container = $('
');
                var tabs = [];
                if(has(item, 'items') ) {
                    $.each(item.items, function(k, subItem) {
                        var htmlElement = widget.genElement(subItem);
                        var tab = {
                            html: htmlElement
                        };

                        if(has(subItem, 'title')) {
                            tab.title = subItem.title;
                        }
                        tabs.push(tab);
                    });
                }
                container.tabNavigator({items: tabs});

                return container;
            },
            fieldSet: function(item, declarations, widget) {
                var fieldSet = $("<fieldset/>");
                if(has(item, 'items')) {
                    $.each(item.items, function(k, subItem) {
                        var htmlElement = widget.genElement(subItem);
                        var tab = {
                            html: htmlElement
                        };

                        if(has(subItem, 'title')) {
                            tab.title = subItem.title;
                        }
                        tabs.push(tab);
                    });
                }
                return fieldSet;
            }
        },

        _create:      function() {
            this._setOptions(this.options);
        },

        /**
         * Generate element by declaration
         *
         * @param item declaration
         * @return jquery html object
         */
        genElement: function(item) {
            var widget = this;
            var type = has(widget.declarations, item.type) ? item.type : 'html';
            var declaration = widget.declarations[type];
            var element = declaration(item, widget.declarations, widget);

            if(has(item, 'cssClass')) {
                element.addClass(item.cssClass);
            }

            if(typeof item == "object") {
                addEvents(element, item);
            }

            if(has(item, 'css')) {

                element.css(item.css);
            }

            element.data('item', item);

            return element;
        },

        /**
         * Generate elements
         *
         * @param element jQuery object
         * @param items declarations
         */
        genElements: function(element, items) {
            var widget = this;
            $.each(items, function(k, item) {
                var subElement = widget.genElement(item);
                element.append(subElement);

            })
        },

        _setOption:  function(key, value) {
            var element = $(this.element);
            var widget = this;
            if(key === "items") {
                widget.genElements(element, value);
            }

            this._super(key, value);
        },
        _setOptions: function(options) {
            this._super(options);
            this.refresh();
        },
        refresh:     function() {
            this._trigger('refresh');
        }
    });

})(jQuery);
<commit_msg>add label to select by generating form<commit_after>/**
 *
 * @author Andriy Oblivantsev <eslider@gmail.com>
 * @copyright 08.04.2015 by WhereGroup GmbH & Co. KG
 */
/**
 *
 * @author Andriy Oblivantsev <eslider@gmail.com>
 * @copyright 05.04.15 by WhereGroup GmbH & Co. KG
 */
(function($) {

    /**
     * Check if object has a key
     *
     * @param obj
     * @param key
     * @returns {boolean}
     */
    function has(obj, key) {
        return typeof obj[key] !== 'undefined';
    }

    /**
     * Add jquery events to element by declration
     *
     * @param element
     * @param declaration
     */
    function addEvents(element, declaration) {
        $.each(declaration, function(k, value) {
            if(typeof value == 'function') {
                element.on(k, value);
            }
        });
    }

    $.widget('mapbender.generateElements', {
        options:      {},
        declarations: {
            popup: function(item, declarations, widget) {
                var popup = $("
");
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        popup.append(widget.genElement(item));
                    });
                }
                window.setTimeout(function() {
                    popup.popupDialog(item)
                }, 1);

                return popup;
            },
            form: function(item, declarations, widget) {
                var form = $('<form/>');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        form.append(widget.genElement(item));
                    })
                }
                return form;
            },
            fluidContainer: function(item, declarations, widget) {
                var container = $('
');
                var hbox = $('
');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        hbox.append(widget.genElement(item));
                    })
                }
                container.append(hbox);
                return container;
            },
            inline: function(item, declarations, widget) {
                var container = $('
');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        container.append(widget.genElement(item));
                    })
                }
                return container;
            },
            html:      function(item, declarations) {
                var container = $('
');
                if (typeof item === 'string'){
                    container.html(item);
                }else if(has(item,'html')){
                    container.html(item.html);
                }else{
                    container.html(JSON.stringify(item));
                }
                return container;
            },
            button:    function(item, declarations) {
                var title = has(item, 'title') ? item.title : 'Submit';
                var button = $('<button class="btn button">' + title + '</button>');
                return button;
            },
            submit:    function(item, declarations) {
                var button = declarations.button(item, declarations);
                button.attr('type', 'submit');
                return button;
            },
            input:     function(item, declarations) {
                var inputField = $('<input class="form-control"/>');
                var container = $('
');
                var type = has(declarations, 'type') ? declarations.type : 'text';
                var icon = '';

                inputField.attr('type', type);
                inputField.data('declaration',item);

                if(has(item, 'name')) {
                    inputField.attr('name', item.name);
                }

                if(has(item, 'placeholder')) {
                    inputField.attr('placeholder', item.placeholder);
                }

                if(has(item, 'value')) {
                    inputField.val(item.value);
                }

                if(has(item, 'text')) {
                    container.append(declarations.label(item, declarations));
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    inputField.data('warn',function(){
                        var hasValue = $.trim(inputField.val()) != '';
                        if(hasValue){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return hasValue;
                    });
                }

                container.append(inputField);
                //container.append(icon);

                return container;
            },
            label:     function(item, declarations) {
                var label = $('');
                if(_.has(item, 'text')) {
                    label.html(item.text);
                }
                if(_.has(item, 'name')) {
                    label.attr('for', item.name);
                }
                return label;
            },
            checkbox:  function(item, declarations) {
                var container = $('
');
                var label = $('');
                var input = $('<input type="checkbox"/>');

                input.data('declaration',item);

                label.append(input);

                if(has(item, 'name')) {
                    input.attr('name', item.name);
                }

                if(has(item, 'value')) {
                    input.val(item.value);
                }

                if(has(item, 'text')) {
                    label.append(item.text);
                }

                if(has(item, 'checked')) {
                    input.attr('checked', "checked");
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    input.data('warn',function(){
                        var isChecked = input.is(':checked');
                        if(isChecked){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return isChecked;
                    });
                }

                container.append(label);
                return container;
            },
            radio:     function(item, declarations) {
                var container = $('
');
                var label = $('');
                var input = $('<input type="radio"/>');

                input.data('declaration',item);

                label.append(input);

                if(has(item, 'name')) {
                    input.attr('name', item.name);
                }

                if(has(item, 'text')) {
                    label.append(item.text);
                }

                if(has(item, 'value')) {
                    input.val(item.value);
                }

                if(has(item, 'checked')) {
                    input.attr('checked', "checked");
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    input.data('warn',function(value){
                        var isChecked = input.is(':checked');
                        if(isChecked){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return isChecked;
                    });
                }

                container.append(label);
                return container;
            },
            formGroup: function(item, declarations, widget) {
                var container = $('
');
                if(has(item, 'items')) {
                    $.each(item.items, function(k, item) {
                        container.append(widget.genElement(item));
                    });
                }
                return container;
            },
            textArea:  function(item, declarations) {
                var input = $('<textarea class="form-control" rows="3"/>');
                input.data('declaration',item);

                if(has(item, 'value')) {
                    input.val(item.value);
                }

                $.each(['name', 'rows', 'placeholder'], function(i, key) {
                    if(has(item, key)) {
                        input.attr(key, item[key]);
                    }
                });

                return input;
            },
            select:    function(item, declarations) {
                var container = $('
');
                var select = $('<select class="form-control"/>');

                select.data('declaration',item);

                $.each(['name'], function(i, key) {
                    if(has(item, key)) {
                        select.attr(key, item[key]);
                    }
                });

                if(has(item, 'multiple') && item.multiple) {
                    select.attr('multiple', 'multiple');
                }

                if(has(item, 'options')) {
                    $.each(item.options, function(value, title) {
                        var option = $("<option/>");
                        option.attr('value', value);
                        option.html(title);
                        option.data(this);
                        select.append(option);
                    });
                }

                if(has(item, 'value')) {
                    window.setTimeout(function(){
                        select.val(item.value);
                    },1)
                }

                if(has(item, 'mandatory') && item.mandatory) {
                    select.data('warn',function(){
                        var hasValue = $.trim(select.val()) != '';
                        if(hasValue){
                            container.removeClass('has-error');
                        }else{
                            container.addClass('has-error');
                        }
                        return hasValue;
                    });
                }

                if(has(item, 'text')) {
                    container.append(declarations.label(item, declarations));
                }

                container.append(select);

                return container;
            },
            file:      function(item, declarations) {
                var container = $('
');
                var label = $('');
                var input = $('<input type="file"/>');

                input.data('declaration',item);

                if(has(item, 'name') && item.multiple) {
                    label.attr('for', item.name);
                    input.attr('name', item.name);
                }

                if(has(item, 'text')) {
                    label.html(item.text);
                    container.append(label);
                }

                container.append(input);
                return container;
            },
            tabs: function(item, declarations, widget) {
                var container = $('
');
                var tabs = [];
                if(has(item, 'items') ) {
                    $.each(item.items, function(k, subItem) {
                        var htmlElement = widget.genElement(subItem);
                        var tab = {
                            html: htmlElement
                        };

                        if(has(subItem, 'title')) {
                            tab.title = subItem.title;
                        }
                        tabs.push(tab);
                    });
                }
                container.tabNavigator({items: tabs});

                return container;
            },
            fieldSet: function(item, declarations, widget) {
                var fieldSet = $("<fieldset/>");
                if(has(item, 'items')) {
                    $.each(item.items, function(k, subItem) {
                        var htmlElement = widget.genElement(subItem);
                        var tab = {
                            html: htmlElement
                        };

                        if(has(subItem, 'title')) {
                            tab.title = subItem.title;
                        }
                        tabs.push(tab);
                    });
                }
                return fieldSet;
            }
        },

        _create:      function() {
            this._setOptions(this.options);
        },

        /**
         * Generate element by declaration
         *
         * @param item declaration
         * @return jquery html object
         */
        genElement: function(item) {
            var widget = this;
            var type = has(widget.declarations, item.type) ? item.type : 'html';
            var declaration = widget.declarations[type];
            var element = declaration(item, widget.declarations, widget);

            if(has(item, 'cssClass')) {
                element.addClass(item.cssClass);
            }

            if(typeof item == "object") {
                addEvents(element, item);
            }

            if(has(item, 'css')) {

                element.css(item.css);
            }

            element.data('item', item);

            return element;
        },

        /**
         * Generate elements
         *
         * @param element jQuery object
         * @param items declarations
         */
        genElements: function(element, items) {
            var widget = this;
            $.each(items, function(k, item) {
                var subElement = widget.genElement(item);
                element.append(subElement);

            })
        },

        _setOption:  function(key, value) {
            var element = $(this.element);
            var widget = this;
            if(key === "items") {
                widget.genElements(element, value);
            }

            this._super(key, value);
        },
        _setOptions: function(options) {
            this._super(options);
            this.refresh();
        },
        refresh:     function() {
            this._trigger('refresh');
        }
    });

})(jQuery);
<|endoftext|>


<commit_before>goog.provide('lime.events.EventDispatcher');

goog.require('lime.events.Event');

/**
 * EventDispatcher object. Deals with event handlers
 * @param {lime.Director} director Director object.
 * @constructor
 */
lime.events.EventDispatcher = function(director) {
    this.director = director;
    this.handlers = {};
    this.swallows = {};

};

/**
 * Register the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to listen.
 */
lime.events.EventDispatcher.prototype.register = function(node, eventType) {
    if (!goog.isDef(this.handlers[eventType])) {
        this.handlers[eventType] = [node];
        //base element switch here because safari fires touchend on
        //dom tree changes otherwise
        goog.events.listen(eventType.substring(0, 5) == 'touch' ?
            document : (eventType.substring(0, 3) == 'key'?window:this.director.domElement.parentNode), eventType,
            this, false, this);
    }
    else {
        if (!goog.array.contains(this.handlers[eventType], node)) {
            this.handlers[eventType].push(node);
            this.handlers[eventType].sort(lime.Node.compareNode).reverse();
        }
    }
};

/**
 * Release the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to release.
 */
lime.events.EventDispatcher.prototype.release = function(node, eventType) {
    if (goog.isDef(this.handlers[eventType])) {
         goog.array.remove(this.handlers[eventType], node);
         if (!this.handlers[eventType].length) {
             goog.events.unlisten(this.director.domElement.parentNode,
                 eventType, this, false, this);
            delete this.handlers[eventType];
         }
    }
};

/**
 * Setup swallow rule for an event. Swallow means that next events from
 * same interaction will go straight to the handler
 * @param {lime.events.Event} e Event.
 * @param {string} type Event type.
 * @param {function(lime.events.Event)} handler Function to call.
 */
lime.events.EventDispatcher.prototype.swallow = function(e, type, handler) {
   /*
   // don't remember why this check was needed
   if (e.type != 'mousedown' && e.type != 'touchstart' &&
        e.type != 'touchmove' && e.type != 'keydown') return;*/
    var id = e.identifier;
    if (!goog.isDef(this.swallows[id])) {
        this.swallows[id] = [];
    }
    this.swallows[id].push([e.targetObject, type, handler]);
    //console.log('listen');
    goog.events.listen(e.targetObject, type, handler);
};

/**
 * Handle DOM event
 * @param {Event} e Event.
 */
lime.events.EventDispatcher.prototype.handleEvent = function(e) {

    if (!goog.isDef(this.handlers[e.type])) return;

    var handlers = this.handlers[e.type].slice(), didhandle = false;

    var touchIndex = 0, doBreak = 0;

    while (!doBreak) {

    var ee = new lime.events.Event(this);
    ee.type = e.type;
    ee.event = e;

    if (e.type.substring(0, 5) == 'touch') {
        var touch = e.getBrowserEvent().changedTouches[touchIndex];
        ee.screenPosition = new goog.math.Coordinate(touch.pageX, touch.pageY);
        ee.identifier = touch.identifier;
        touchIndex++;

        if (touchIndex >= e.getBrowserEvent().changedTouches.length) {
            doBreak = 1;
        }
    }
    else {
        ee.screenPosition = new goog.math.Coordinate(e.clientX, e.clientY);
        doBreak = 1;
    }

    if (goog.isDef(this.swallows[ee.identifier])) {
        var s = this.swallows[ee.identifier];

        for (var i = 0; i < s.length; i++) {
            if (s[i][1] == e.type || (goog.isArray(s[i][1]) &&
                    goog.array.contains(s[i][1], e.type))){

                var handler = s[i][0];
                ee.targetObject = handler;
                ee.position = handler.screenToLocal(ee.screenPosition);
                s[i][2].call(handler, ee);
                didhandle = true;
            }
        }
        //handler.dispatchEvent(ee);

        if (e.type == 'touchend' || e.type == 'touchcancel' ||
            e.type == 'mouseup' || e.type=='keyup') {
            delete ee.targetObject;
            ee.release();
        }
    }
    else {
        for (var i = 0; i < handlers.length; i++) {

            var handler = handlers[i];

            if (this.director.getCurrentScene() != handler.getScene() &&
                handler != this.director) continue;

            ee.targetObject = handler;

            if (handler.hitTest(ee) || e.type.substring(0,3)=='key') {

                ee.targetObject = handler;
                handler.dispatchEvent(ee);
                didhandle = false;

                if (ee.event.propagationStopped_) break;
            }

        }

    }

    }

    if (didhandle)
    e.preventDefault();

};
<commit_msg>Fix swallowed event independence requirement<commit_after>goog.provide('lime.events.EventDispatcher');

goog.require('lime.events.Event');

/**
 * EventDispatcher object. Deals with event handlers
 * @param {lime.Director} director Director object.
 * @constructor
 */
lime.events.EventDispatcher = function(director) {
    this.director = director;
    this.handlers = {};
    this.swallows = {};

};

/**
 * Register the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to listen.
 */
lime.events.EventDispatcher.prototype.register = function(node, eventType) {
    if (!goog.isDef(this.handlers[eventType])) {
        this.handlers[eventType] = [node];
        //base element switch here because safari fires touchend on
        //dom tree changes otherwise
        goog.events.listen(eventType.substring(0, 5) == 'touch' ?
            document : (eventType.substring(0, 3) == 'key'?window:this.director.domElement.parentNode), eventType,
            this, false, this);
    }
    else {
        if (!goog.array.contains(this.handlers[eventType], node)) {
            this.handlers[eventType].push(node);
            this.handlers[eventType].sort(lime.Node.compareNode).reverse();
        }
    }
};

/**
 * Release the event listener for node
 * @param {lime.Node} node Node that responds to events.
 * @param {string} eventType type of event to release.
 */
lime.events.EventDispatcher.prototype.release = function(node, eventType) {
    if (goog.isDef(this.handlers[eventType])) {
         goog.array.remove(this.handlers[eventType], node);
         if (!this.handlers[eventType].length) {
             goog.events.unlisten(this.director.domElement.parentNode,
                 eventType, this, false, this);
            delete this.handlers[eventType];
         }
    }
};

/**
 * Setup swallow rule for an event. Swallow means that next events from
 * same interaction will go straight to the handler
 * @param {lime.events.Event} e Event.
 * @param {string} type Event type.
 * @param {function(lime.events.Event)} handler Function to call.
 */
lime.events.EventDispatcher.prototype.swallow = function(e, type, handler) {
   /*
   // don't remember why this check was needed
   if (e.type != 'mousedown' && e.type != 'touchstart' &&
        e.type != 'touchmove' && e.type != 'keydown') return;*/
    var id = e.identifier;
    if (!goog.isDef(this.swallows[id])) {
        this.swallows[id] = [];
    }
    this.swallows[id].push([e.targetObject, type, handler]);
    //console.log('listen');
    goog.events.listen(e.targetObject, type, goog.nullFunction);
};

/**
 * Handle DOM event
 * @param {Event} e Event.
 */
lime.events.EventDispatcher.prototype.handleEvent = function(e) {

    if (!goog.isDef(this.handlers[e.type])) return;

    var handlers = this.handlers[e.type].slice(), didhandle = false;

    var touchIndex = 0, doBreak = 0;

    while (!doBreak) {

    var ee = new lime.events.Event(this);
    ee.type = e.type;
    ee.event = e;

    if (e.type.substring(0, 5) == 'touch') {
        var touch = e.getBrowserEvent().changedTouches[touchIndex];
        ee.screenPosition = new goog.math.Coordinate(touch.pageX, touch.pageY);
        ee.identifier = touch.identifier;
        touchIndex++;

        if (touchIndex >= e.getBrowserEvent().changedTouches.length) {
            doBreak = 1;
        }
    }
    else {
        ee.screenPosition = new goog.math.Coordinate(e.clientX, e.clientY);
        doBreak = 1;
    }

    if (goog.isDef(this.swallows[ee.identifier])) {
        var s = this.swallows[ee.identifier];

        for (var i = 0; i < s.length; i++) {
            if (s[i][1] == e.type || (goog.isArray(s[i][1]) &&
                    goog.array.contains(s[i][1], e.type))){

                var handler = s[i][0];
                ee.targetObject = handler;
                ee.position = handler.screenToLocal(ee.screenPosition);
                s[i][2].call(handler, ee);
                didhandle = true;
            }
        }
        //handler.dispatchEvent(ee);

        if (e.type == 'touchend' || e.type == 'touchcancel' ||
            e.type == 'mouseup' || e.type=='keyup') {
            delete ee.targetObject;
            ee.release();
        }
    }
    else {
        for (var i = 0; i < handlers.length; i++) {

            var handler = handlers[i];

            if (this.director.getCurrentScene() != handler.getScene() &&
                handler != this.director) continue;

            ee.targetObject = handler;

            if (handler.hitTest(ee) || e.type.substring(0,3)=='key') {

                ee.targetObject = handler;
                handler.dispatchEvent(ee);
                didhandle = false;

                if (ee.event.propagationStopped_) break;
            }

        }

    }

    }

    if (didhandle)
    e.preventDefault();

};
<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import isEmpty from 'lodash/isEmpty';
import uniqBy from 'lodash/uniqBy';
import groupBy from 'lodash/groupBy';

const getIso = state => state.iso || null;
const getTimeline = state => state.timeline || null;

export const getDates = createSelector(
  [getIso, getTimeline],
  (iso, timeline) => {
    const { data } = timeline;
    if (isEmpty(data) || !data[iso]) return null;
    const documents = [];
    uniqBy(data[iso], 'link').forEach(d => {
      if (d.date) {
        documents.push({
          year: d.date.split('-')[0],
          link: d.link,
          label: d.label
        });
      }
    });
    // add year 2020 as due date for new NDCs submissions
    documents.push({
      year: '2020',
      link: 'http://www.wri.org/sites/default/files/WRI17_NDC.pdf',
      label: 'All Parties are requested to communicate new NDCs by 2020'
    });
    return groupBy(documents, 'year');
  }
);

export default {
  getDates
};
<commit_msg>Updates text for future submissions<commit_after>import { createSelector } from 'reselect';
import isEmpty from 'lodash/isEmpty';
import uniqBy from 'lodash/uniqBy';
import groupBy from 'lodash/groupBy';

const getIso = state => state.iso || null;
const getTimeline = state => state.timeline || null;

export const getDates = createSelector(
  [getIso, getTimeline],
  (iso, timeline) => {
    const { data } = timeline;
    if (isEmpty(data) || !data[iso]) return null;
    const documents = [];
    uniqBy(data[iso], 'link').forEach(d => {
      if (d.date) {
        documents.push({
          year: d.date.split('-')[0],
          link: d.link,
          label: d.label
        });
      }
    });
    // add year 2020 as due date for new NDCs submissions
    documents.push({
      year: '2020',
      link: 'http://www.wri.org/sites/default/files/WRI17_NDC.pdf',
      label: 'Parties are requested to communicate new or updated NDCs by 2020'
    });
    return groupBy(documents, 'year');
  }
);

export default {
  getDates
};
<|endoftext|>