<commit_before>var File, PLUGIN_NAME, ProgressBar, async, atom, childProcess, fs, getApmPath, grs, isFile, path, semver, spawn, through2, util, wrench;

fs = require('fs');

grs = require('grs');

path = require('path');

async = require('async');

wrench = require('wrench');

util = require('gulp-util');

through2 = require('through2');

childProcess = require('child_process');

ProgressBar = require('progress');

File = require('vinyl');

semver = require('semver');

PLUGIN_NAME = 'gulp-atom-shell';

module.exports = atom = function(options) {
  var isElectron, pkgName, platforms, stream;
  options = options || {};
  if (!options.releasePath || !options.version || !options.srcPath || !options.cachePath) {
    throw new util.PluginError('Miss version or release path.');
  }
  if (options.platforms == null) {
    options.platforms = ['darwin'];
  }
  if (options.apm == null) {
    options.apm = getApmPath();
  }
  if (options.symbols == null) {
    options.symbols = false;
  }
  if (options.rebuild == null) {
    options.rebuild = false;
  }
  if (options.ext == null) {
    options.ext = 'zip';
  }
  if (typeof options.platforms === 'string') {
    options.platforms = [options.platforms];
  }
  isElectron = semver.gte(options.version.replace('v', ''), '0.24.0');
  pkgName = isElectron ? "Electron" : "Atom";
  stream = through2.obj();
  platforms = ['darwin', 'win32', 'linux', 'darwin-x64', 'linux-ia32', 'linux-x64', 'win32-ia32', 'win32-x64'];
  async.eachSeries(options.platforms, function(platform, callback) {
    var cacheFile, cachePath, pkg, releasePath, repo;
    if (platform === 'osx') {
      platform = 'darwin';
    }
    if (platform === 'win') {
      platform = 'win32';
    }
    if (platforms.indexOf(platform) < 0) {
      stream.emit('error', "Not support platform " + platform);
      return callback();
    }
    if (options.version == null) {
      options.version = "v0.24.0";
    }
    repo = isElectron ? 'electron' : 'atom-shell';
    pkg = "" + repo + "-" + options.version + "-" + platform;
    if (options.symbols) {
      pkg += '-symbols';
    }
    pkg += "." + options.ext;
    cachePath = path.resolve(options.cachePath, options.version);
    cacheFile = path.resolve(cachePath, pkg);
    releasePath = path.resolve(options.releasePath, options.version, platform);
    return async.series([
      function(next) {
        var bar;
        if (!isFile(cacheFile)) {
          wrench.mkdirSyncRecursive(cachePath);
          bar = null;
          return grs({
            repo: "atom/electron",
            tag: options.version,
            name: pkg
          }).on('error', function(error) {
            return stream.emit('error', error);
          }).on('size', function(size) {
            return bar = new ProgressBar("" + pkg + " [:bar] :percent :etas", {
              complete: '>',
              incomplete: ' ',
              width: 20,
              total: size
            });
          }).pipe(through2(function(chunk, enc, cb) {
            bar.tick(chunk.length);
            this.push(chunk);
            return cb();
          })).pipe(fs.createWriteStream(cacheFile)).on('close', function() {
            return next();
          }).on('error', next);
        } else {
          return next();
        }
      }, function(next) {
        if (!isFile(path.resolve(releasePath, 'version'))) {
          wrench.mkdirSyncRecursive(releasePath);
          util.log(PLUGIN_NAME, "unzip " + platform + " " + options.version + " atom-shell.");
          return spawn({
            cmd: 'unzip',
            args: ['-o', cacheFile, '-d', releasePath]
          }, next);
        } else {
          return next();
        }
      }, function(next) {
        if (options.rebuild) {
          util.log(PLUGIN_NAME, "Rebuilding modules");
          return spawn({
            cmd: options.apm,
            args: ['rebuild']
          }, next);
        } else {
          return next();
        }
      }, function(next) {
        var _src;
        util.log(PLUGIN_NAME, "" + pkg + " distribute done.");
        _src = 'resources/app';
        if (platform.indexOf('darwin') >= 0) {
          _src = "" + pkgName + ".app/Contents/Resources/app/";
        }
        wrench.mkdirSyncRecursive(path.join(releasePath, _src));
        wrench.copyDirSyncRecursive(options.srcPath, path.join(releasePath, _src), {
          forceDelete: true,
          excludeHiddenUnix: false,
          inflateSymlinks: false
        });
        return next(null, platform.indexOf('darwin') < 0 && releasePath || path.join(releasePath, "" + pkgName + ".app"));
      }
    ], function(error, results) {
      var execution, releaseDir;
      releaseDir = results[results.length - 1];
      execution = (function() {
        switch (false) {
          case !(platform.indexOf('darwin') >= 0):
            return "Contents/MacOS/" + pkgName;
          case !(platform.indexOf('win') >= 0):
            return "" + (pkgName.toLowerCase()) + ".exe";
          default:
            return pkgName.toLowerCase();
        }
      })();
      stream.write(new File({
        base: releaseDir,
        path: path.join(releaseDir, execution)
      }));
      return callback(error);
    });
  }, function(error) {
    if (error) {
      stream.emit('error', error);
    }
    return stream.end();
  });
  return stream;
};

isFile = function() {
  var filepath;
  filepath = path.join.apply(path, arguments);
  return fs.existsSync(filepath) && fs.statSync(filepath).isFile();
};

getApmPath = function() {
  var apmPath;
  apmPath = path.join('apm', 'node_modules', 'atom-package-manager', 'bin', 'apm');
  if (!isFile(apmPath)) {
    return apmPath = 'apm';
  }
};

spawn = function(options, callback) {
  var error, proc, stderr, stdout;
  stdout = [];
  stderr = [];
  error = null;
  proc = childProcess.spawn(options.cmd, options.args, options.opts);
  proc.stdout.on('data', function(data) {
    stdout.push(data.toString());
    if (process.NODE_ENV === 'test') {
      return util.log(data.toString());
    }
  });
  proc.stderr.on('data', function(data) {
    return stderr.push(data.toString());
  });
  return proc.on('exit', function(code, signal) {
    var results;
    if (code !== 0) {
      error = new Error(signal);
    }
    results = {
      stderr: stderr.join(''),
      stdout: stdout.join(''),
      code: code
    };
    if (code !== 0) {
      throw new util.PluginError(PLUGIN_NAME, results.stderr || 'unknow error , maybe you can try delete the zip packages.');
    }
    return callback(error, results);
  });
};
<commit_msg>Improve error message<commit_after>var File, PLUGIN_NAME, ProgressBar, async, atom, childProcess, fs, getApmPath, grs, isFile, path, semver, spawn, through2, util, wrench;

fs = require('fs');

grs = require('grs');

path = require('path');

async = require('async');

wrench = require('wrench');

util = require('gulp-util');

through2 = require('through2');

childProcess = require('child_process');

ProgressBar = require('progress');

File = require('vinyl');

semver = require('semver');

PLUGIN_NAME = 'gulp-atom-shell';

module.exports = atom = function(options) {
  var isElectron, pkgName, platforms, stream;
  options = options || {};
  if (!options.releasePath || !options.version || !options.srcPath || !options.cachePath) {
    throw new util.PluginError('Miss version or release path.');
  }
  if (options.platforms == null) {
    options.platforms = ['darwin'];
  }
  if (options.apm == null) {
    options.apm = getApmPath();
  }
  if (options.symbols == null) {
    options.symbols = false;
  }
  if (options.rebuild == null) {
    options.rebuild = false;
  }
  if (options.ext == null) {
    options.ext = 'zip';
  }
  if (typeof options.platforms === 'string') {
    options.platforms = [options.platforms];
  }
  isElectron = semver.gte(options.version.replace('v', ''), '0.24.0');
  pkgName = isElectron ? "Electron" : "Atom";
  stream = through2.obj();
  platforms = ['darwin', 'win32', 'linux', 'darwin-x64', 'linux-ia32', 'linux-x64', 'win32-ia32', 'win32-x64'];
  async.eachSeries(options.platforms, function(platform, callback) {
    var cacheFile, cachePath, pkg, releasePath, repo;
    if (platform === 'osx') {
      platform = 'darwin';
    }
    if (platform === 'win') {
      platform = 'win32';
    }
    if (platforms.indexOf(platform) < 0) {
      stream.emit('error', "Not support platform " + platform);
      return callback();
    }
    if (options.version == null) {
      options.version = "v0.24.0";
    }
    repo = isElectron ? 'electron' : 'atom-shell';
    pkg = "" + repo + "-" + options.version + "-" + platform;
    if (options.symbols) {
      pkg += '-symbols';
    }
    pkg += "." + options.ext;
    cachePath = path.resolve(options.cachePath, options.version);
    cacheFile = path.resolve(cachePath, pkg);
    releasePath = path.resolve(options.releasePath, options.version, platform);
    return async.series([
      function(next) {
        var bar;
        if (!isFile(cacheFile)) {
          wrench.mkdirSyncRecursive(cachePath);
          bar = null;
          return grs({
            repo: "atom/electron",
            tag: options.version,
            name: pkg
          }).on('error', function(error) {
            return stream.emit('error', error);
          }).on('size', function(size) {
            return bar = new ProgressBar("" + pkg + " [:bar] :percent :etas", {
              complete: '>',
              incomplete: ' ',
              width: 20,
              total: size
            });
          }).pipe(through2(function(chunk, enc, cb) {
            bar.tick(chunk.length);
            this.push(chunk);
            return cb();
          })).pipe(fs.createWriteStream(cacheFile)).on('close', function() {
            return next();
          }).on('error', next);
        } else {
          return next();
        }
      }, function(next) {
        if (!isFile(path.resolve(releasePath, 'version'))) {
          wrench.mkdirSyncRecursive(releasePath);
          util.log(PLUGIN_NAME, "unzip " + platform + " " + options.version + " atom-shell.");
          return spawn({
            cmd: 'unzip',
            args: ['-o', cacheFile, '-d', releasePath]
          }, next);
        } else {
          return next();
        }
      }, function(next) {
        if (options.rebuild) {
          util.log(PLUGIN_NAME, "Rebuilding modules");
          return spawn({
            cmd: options.apm,
            args: ['rebuild']
          }, next);
        } else {
          return next();
        }
      }, function(next) {
        var _src;
        util.log(PLUGIN_NAME, "" + pkg + " distribute done.");
        _src = 'resources/app';
        if (platform.indexOf('darwin') >= 0) {
          _src = "" + pkgName + ".app/Contents/Resources/app/";
        }
        wrench.mkdirSyncRecursive(path.join(releasePath, _src));
        wrench.copyDirSyncRecursive(options.srcPath, path.join(releasePath, _src), {
          forceDelete: true,
          excludeHiddenUnix: false,
          inflateSymlinks: false
        });
        return next(null, platform.indexOf('darwin') < 0 && releasePath || path.join(releasePath, "" + pkgName + ".app"));
      }
    ], function(error, results) {
      var execution, releaseDir;
      releaseDir = results[results.length - 1];
      execution = (function() {
        switch (false) {
          case !(platform.indexOf('darwin') >= 0):
            return "Contents/MacOS/" + pkgName;
          case !(platform.indexOf('win') >= 0):
            return "" + (pkgName.toLowerCase()) + ".exe";
          default:
            return pkgName.toLowerCase();
        }
      })();
      stream.write(new File({
        base: releaseDir,
        path: path.join(releaseDir, execution)
      }));
      return callback(error);
    });
  }, function(error) {
    if (error) {
      stream.emit('error', error);
    }
    return stream.end();
  });
  return stream;
};

isFile = function() {
  var filepath;
  filepath = path.join.apply(path, arguments);
  return fs.existsSync(filepath) && fs.statSync(filepath).isFile();
};

getApmPath = function() {
  var apmPath;
  apmPath = path.join('apm', 'node_modules', 'atom-package-manager', 'bin', 'apm');
  if (!isFile(apmPath)) {
    return apmPath = 'apm';
  }
};

spawn = function(options, callback) {
  var error, proc, stderr, stdout;
  stdout = [];
  stderr = [];
  error = null;
  proc = childProcess.spawn(options.cmd, options.args, options.opts);
  proc.stdout.on('data', function(data) {
    stdout.push(data.toString());
    if (process.NODE_ENV === 'test') {
      return util.log(data.toString());
    }
  });
  proc.stderr.on('data', function(data) {
    return stderr.push(data.toString());
  });
  return proc.on('exit', function(code, signal) {
    var results;
    if (code !== 0) {
      error = new Error(signal);
    }
    results = {
      stderr: stderr.join(''),
      stdout: stdout.join(''),
      code: code
    };
    if (code !== 0) {
      throw new util.PluginError(PLUGIN_NAME, results.stderr || 'unknown error... try deleting the zip packages.');
    }
    return callback(error, results);
  });
};
<|endoftext|>


<commit_before>/**
 * route.js
 *
 * Defines the Route class, which provides wrapper methods around Express
 * routes.
 */

var Handler = require('./handler');

/**
 * Constructor. Takes in a RestAPI instance and a path for the route.
 */
module.exports = function Route(restApi, path) {
	this.restApi = restApi;
	this.path = path;

	this.expressRoute = restApi.expressApp.route(path);
}

Route.prototype._addHandler(method) {
	// all arguments after 'method' should be a function handler
	var funcs = Array.prototype.slice.call(arguments, 1);

	this.expressRoute[method](new Handler(funcs));
}

/**
 * Define GET handlers for the route.
 */
Route.prototype.get = function() {
	var callWith = ['get'].concat(Array.prototype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}

/**
 * Define PUT handlers for the route.
 */
Route.protoype.put = function() {
	var callWith = ['put'].concat(Array.protoype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}

/**
 * Define POST handlers for the route.
 */
Route.prototype.post = function() {
	var callWith = ['post'].concat(Array.protoype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}

/**
 * Define DELETE handlers for the route.
 */
Route.prototype.delete = function() {
	var callWith = ['delete'].concat(Array.protoype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}
<commit_msg>Fix typo.<commit_after>/**
 * route.js
 *
 * Defines the Route class, which provides wrapper methods around Express
 * routes.
 */

var Handler = require('./handler');

/**
 * Constructor. Takes in a RestAPI instance and a path for the route.
 */
module.exports = function Route(restApi, path) {
	this.restApi = restApi;
	this.path = path;

	this.expressRoute = restApi.expressApp.route(path);
}

Route.prototype._addHandler = function(method) {
	// all arguments after 'method' should be a function handler
	var funcs = Array.prototype.slice.call(arguments, 1);

	this.expressRoute[method](new Handler(funcs));
}

/**
 * Define GET handlers for the route.
 */
Route.prototype.get = function() {
	var callWith = ['get'].concat(Array.prototype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}

/**
 * Define PUT handlers for the route.
 */
Route.protoype.put = function() {
	var callWith = ['put'].concat(Array.protoype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}

/**
 * Define POST handlers for the route.
 */
Route.prototype.post = function() {
	var callWith = ['post'].concat(Array.protoype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}

/**
 * Define DELETE handlers for the route.
 */
Route.prototype.delete = function() {
	var callWith = ['delete'].concat(Array.protoype.slice.call(arguments));

	this._addHandler.apply(this, callWith);
}
<|endoftext|>


<commit_before>//// the director
//Runtime.director = null;
//
//// the game
//Runtime.game = null;

//Runtime.sceneNode = null;

Runtime.init = function () {
    //this.sceneNode = new cc.Scene();
    //this.game = Engine._renderContext.game;
    //this.director = this.game.director;
    // @ifdef EDITOR
    //this.director.runScene(Runtime.sceneNode);
    // @endif
};

Runtime.animate = function () {
    // update cocos logic to tick cocos animations
    var dt = Time.deltaTime;
    var game = Engine._renderContext.game;
    game.setEnvironment();
    game.director._scheduler.update(dt);
    // @ifdef EDITOR
    game = Engine._renderContext.sceneView.game;
    game.setEnvironment();
    game.director._scheduler.update(dt);
    // @endif
};
<commit_msg>add runtime implementation of tickInEditMode<commit_after>//// the director
//Runtime.director = null;
//
//// the game
//Runtime.game = null;

//Runtime.sceneNode = null;

Runtime.init = function () {
    //this.sceneNode = new cc.Scene();
    //this.game = Engine._renderContext.game;
    //this.director = this.game.director;
    // @ifdef EDITOR
    //this.director.runScene(Runtime.sceneNode);
    // @endif
};

Runtime.animate = function () {
    // update cocos logic to tick cocos animations
    var dt = Time.deltaTime;
    var game = Engine._renderContext.game;
    game.setEnvironment();
    game.director._scheduler.update(dt);
    // @ifdef EDITOR
    game = Engine._renderContext.sceneView.game;
    game.setEnvironment();
    game.director._scheduler.update(dt);
    // @endif
};

//Runtime.render = function (renderContext) {
//    Engine._scene.render(renderContext || Engine._renderContext);
//};

// @ifdef EDITOR
var animateAfterRender = false;
Runtime.animateAfterRender = function () {
    animateAfterRender = true;
};

var animateInNextTick = false;
Runtime.animateInNextTick = function () {
    animateInNextTick = true;
};

Runtime.tickInEditMode = function (renderContext) {
    if (! Engine._isPlaying) {
        if (renderContext && renderContext.isSceneView) {
            var now = Fire._Ticker.now();
            Fire.Time._update(now, false, 1 / 30);
            if (Engine._editorAnimating || animateInNextTick) {
                //animateInNextTick = Engine._editorAnimating;
                animateInNextTick = false;
                this.animate();
            }
        }
    }
    else {
        animateInNextTick = false;
    }

    this.render(renderContext);

    if (animateAfterRender) {
        this.animateInNextTick();
        animateAfterRender = false;
    }
};
// @endif
<|endoftext|>


<commit_before>/*!
 * Module dependencies.
 */

var _ = require('underscore'),
	keystone = require('../../'),
	querystring = require('querystring'),
	https = require('https'),
	util = require('util'),
	utils = require('keystone-utils'),
	super_ = require('../field');

var RADIUS_KM = 6371,
	RADIUS_MILES = 3959;

/**
 * Location FieldType Constructor
 * @extends Field
 * @api public
 */

function location(list, path, options) {

	this._underscoreMethods = ['format', 'googleLookup', 'kmFrom', 'milesFrom'];

	this.enableMapsAPI = keystone.get('google api key') ? true : false;

	if (!options.defaults) {
		options.defaults = {};
	}

	if (options.required) {
		if (Array.isArray(options.required)) {
			this.requiredPaths = options.required;
		} else if ('string' == typeof options.required) {
			this.requiredPaths = options.required.replace(/,/g, ' ').split(/\s+/);
		} else {
			this.requiredPaths = ['street1', 'suburb'];
		}
		options.required = true;
	} else {
		this.requiredPaths = [];
	}

	location.super_.call(this, list, path, options);

};

/*!
 * Inherit from Field
 */

util.inherits(location, super_);

/**
 * Registers the field on the List's Mongoose Schema.
 *
 * @api public
 */

location.prototype.addToSchema = function() {

	var field = this,
		schema = this.list.schema,
		options = this.options;

	var paths = this.paths = {
		number: this._path.append('.number'),
		name: this._path.append('.name'),
		street1: this._path.append('.street1'),
		street2: this._path.append('.street2'),
		suburb: this._path.append('.suburb'),
		state: this._path.append('.state'),
		postcode: this._path.append('.postcode'),
		country: this._path.append('.country'),
		geo: this._path.append('.geo'),
		geo_lat: this._path.append('.geo_lat'),
		geo_lng: this._path.append('.geo_lng'),
		serialised: this._path.append('.serialised'),
		improve: this._path.append('_improve'),
		overwrite: this._path.append('_improve_overwrite')
	};

	var getFieldDef = function(type, key) {
		var def = { type: type };
		if (options.defaults[key]) {
			def.default = options.defaults[key];
		}
		return def;
	}

	schema.nested[this.path] = true;
	schema.add({
		number: getFieldDef(String, 'number'),
		name: getFieldDef(String, 'name'),
		street1: getFieldDef(String, 'street1'),
		street2: getFieldDef(String, 'street2'),
		street3: getFieldDef(String, 'street3'),
		suburb: getFieldDef(String, 'suburb'),
		state: getFieldDef(String, 'state'),
		postcode: getFieldDef(String, 'postcode'),
		country: getFieldDef(String, 'country'),
		geo: { type: [Number], index: '2dsphere' }
	}, this.path + '.');

	schema.virtual(paths.serialised).get(function() {
		return _.compact([
			this.get(paths.number),
			this.get(paths.name),
			this.get(paths.street1),
			this.get(paths.street2),
			this.get(paths.suburb),
			this.get(paths.state),
			this.get(paths.postcode),
			this.get(paths.country)
		]).join(', ');
	});

	// pre-save hook to fix blank geo fields
	// see http://stackoverflow.com/questions/16388836/does-applying-a-2dsphere-index-on-a-mongoose-schema-force-the-location-field-to
	schema.pre('save', function(next) {
		var obj = field._path.get(this);
		if (Array.isArray(obj.geo) && 0 === obj.geo.length) {
			obj.geo = undefined;
		}
		next();
	});

	this.bindUnderscoreMethods();

}

/**
 * Formats a list of the values stored by the field. Only paths that
 * have values will be included.
 *
 * Optionally provide a space-separated list of values to include.
 *
 * Delimiter defaults to `', '`.
 *
 * @api public
 */

location.prototype.format = function(item, values, delimiter) {

	if (!values) {
		return item.get(this.paths.serialised);
	}

	var paths = this.paths;

	values = values.split(' ').map(function(i) {
		return item.get(paths[i]);
	});

	return _.compact(values).join(delimiter || ', ');

}

/**
 * Detects whether the field has been modified
 *
 * @api public
 */

location.prototype.isModified = function(item) {
	return item.isModified(this.paths.number)
		|| item.isModified(this.paths.name)
		|| item.isModified(this.paths.street1)
		|| item.isModified(this.paths.street2)
		|| item.isModified(this.paths.suburb)
		|| item.isModified(this.paths.state)
		|| item.isModified(this.paths.postcode)
		|| item.isModified(this.paths.country)
		|| item.isModified(this.paths.geo);
}

/**
 * Validates that a value for this field has been provided in a data object
 *
 * options.required specifies an array or space-delimited list of paths that
 * are required (defaults to street1, suburb)
 *
 * @api public
 */

location.prototype.validateInput = function(data, required, item) {

	if (required) {

		var paths = this.paths,
			valid = true;

		this.requiredPaths.forEach(function(path) {

			if (!(paths[path] in data) && item && item.get(paths[path])) {
				return;
			}

			if (!data[paths[path]]) {
				valid = false;
			}

		});

		return valid;

	} else {

		return true;

	}
}

/**
 * Updates the value for this field in the item from a data object
 *
 * @api public
 */

location.prototype.updateItem = function(item, data) {

	var paths = this.paths;

	var setValue = function(key) {
		if (paths[key] in data && data[paths[key]] != item.get(paths[key])) {
			item.set(paths[key], data[paths[key]] || null);
		}
	}

	_.each(['number', 'name', 'street1', 'street2', 'suburb', 'state', 'postcode', 'country'], setValue);

	if (paths.geo in data) {

		var oldGeo = item.get(paths.geo) || [],
			newGeo = data[paths.geo];

		if (!Array.isArray(newGeo) || newGeo.length != 2) {
			newGeo = [];
		}

		if (newGeo[0] != oldGeo[0] || newGeo[1] != oldGeo[1]) {
			item.set(paths.geo, newGeo);
		}

	} else if (paths.geo_lat in data && paths.geo_lng in data) {

		var lat = utils.number(data[paths.geo_lat]),
			lng = utils.number(data[paths.geo_lng]);

		if (lat && lng) {
			item.set(paths.geo, [lng, lat]);
		}

	}

}

/**
 * Returns a callback that handles a standard form submission for the field
 *
 * Handles:
 * - `field.paths.improve` in `req.body` - improves data via `.googleLookup()`
 * - `field.paths.overwrite` in `req.body` - in conjunction with `improve`, overwrites existing data
 *
 * @api public
 */

location.prototype.getRequestHandler = function(item, req, paths, callback) {

	var field = this;

	if (utils.isFunction(paths)) {
		callback = paths;
		paths = field.paths;
	} else if (!paths) {
		paths = field.paths;
	}

	callback = callback || function() {};

	return function() {

		var update = req.body[paths.overwrite] ? 'overwrite' : true;

		if (req.body && req.body[paths.improve]) {
			field.googleLookup(item, false, update, function() {
				callback();
			});
		} else {
			callback();
		}

	}

}

/**
 * Immediately handles a standard form submission for the field (see `getRequestHandler()`)
 *
 * @api public
 */

location.prototype.handleRequest = function(item, req, paths, callback) {
	this.getRequestHandler(item, req, paths, callback)();
}

/**
 * Internal Google geocode request method
 *
 * @api private
 */

function doGoogleGeocodeRequest(address, region, callback) {

	// https://developers.google.com/maps/documentation/geocoding/
	// Use of the Google Geocoding API is subject to a query limit of 2,500 geolocation requests per day, except with an enterprise license.
	// Note: the Geocoding API may only be used in conjunction with a Google map; geocoding results without displaying them on a map is prohibited.
	// Please make sure your Keystone app complies with the Google Maps API License.

	var options = {
		sensor: false,
		language: 'en',
		address: address
	};

	if (arguments.length == 2 && 'function' == typeof region) {
		callback = region;
		region = null;
	}

	if (region) {
		options.region = region;
	}

	var endpoint = 'https://maps.googleapis.com/maps/api/geocode/json?' + querystring.stringify(options);

	https.get(endpoint, function(res) {
		var data = [];
		res.on('data', function(chunk) {
				data.push(chunk);
			})
			.on('end', function() {
				var dataBuff = data.join('').trim();
				var result;
				try {
					result = JSON.parse(dataBuff);
				}
				catch (exp) {
					result = {'status_code': 500, 'status_text': 'JSON Parse Failed', 'status': 'UNKNOWN_ERROR'};
				}
				callback(null, result);
			});
	})
	.on('error', function(err) {
		callback(err);
	});
};

/**
 * Autodetect the full address and lat, lng from the stored value.
 *
 * Uses Google's Maps API and may only be used in conjunction with a Google map.
 * Geocoding results without displaying them on a map is prohibited.
 * Please make sure your Keystone app complies with the Google Maps API License.
 *
 * Internal status codes mimic the Google API status codes.
 *
 * @api private
 */

location.prototype.googleLookup = function(item, region, update, callback) {

	if ('function' == typeof update) {
		callback = update;
		update = false;
	}

	var field = this,
		stored = item.get(this.path),
		address = item.get(this.paths.serialised);

	if (address.length == 0) {
		return callback({'status_code': 500, 'status_text': 'No address to geocode', 'status': 'NO_ADDRESS'});
	}

	doGoogleGeocodeRequest(address, region || keystone.get('default region'), function(err, geocode){

		if (err || geocode.status != 'OK') {
			return callback(err);
		}

		// use the first result
		// if there were no results in the array, status would be ZERO_RESULTS
		var result = geocode.results[0];

		// parse the address components into a location object

		var location = {};

		_.each(result.address_components, function(val,key){
			if ( _.indexOf(val.types,'street_number') >= 0 ) {
				location.street1 = location.street1 || [];
				location.street1.push(val.long_name);
			}
			if ( _.indexOf(val.types,'route') >= 0 ) {
				location.street1 = location.street1 || [];
				location.street1.push(val.short_name);
			}
			// in some cases, you get suburb, city as locality - so only use the first
			if ( _.indexOf(val.types,'locality') >= 0 && !location.suburb) {
				location.suburb = val.long_name;
			}
			if ( _.indexOf(val.types,'administrative_area_level_1') >= 0 ) {
				location.state = val.short_name;
			}
			if ( _.indexOf(val.types,'country') >= 0 ) {
				location.country = val.long_name;
			}
			if ( _.indexOf(val.types,'postal_code') >= 0 ) {
				location.postcode = val.short_name;
			}
		});

		if (Array.isArray(location.street1))
			location.street1 = location.street1.join(' ');

		location.geo = [
			result.geometry.location.lng,
			result.geometry.location.lat
		];

		//console.log('------ Google Geocode Results ------');
		//console.log(address);
		//console.log(result);
		//console.log(location);

		if (update == 'overwrite') {
			item.set(field.path, location);
		} else if (update) {
			_.each(location, function(value, key) {
				if (key == 'geo') {
					return;
				}
				if (!stored[key]) {
					item.set(field.paths[key], value);
				}
			});
			if (!Array.isArray(stored.geo) || !stored.geo[0] || !stored.geo[1]) {
				item.set(field.paths.geo, location.geo);
			}
		}

		callback(null, location, result);

	});
};

/**
 * Internal Distance calculation function
 *
 * See http://en.wikipedia.org/wiki/Haversine_formula
 *
 * @api private
 */

function calculateDistance(point1, point2) {

	var dLng = (point2[0] - point1[0]) * Math.PI / 180;
	var dLat = (point2[1] - point1[1]) * Math.PI / 180;
	var lat1 = (point1[1]) * Math.PI / 180;
	var lat2 = (point2[1]) * Math.PI / 180;

	var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLng/2) * Math.sin(dLng/2) * Math.cos(lat1) * Math.cos(lat2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

	return c;

}

/**
 * Returns the distance from a [lat,lng] point in kilometres
 *
 * @api public
 */

location.prototype.kmFrom = function(item, point) {
	return calculateDistance(this.get(this.paths.geo), point) * RADIUS_KM;
}

/**
 * Returns the distance from a [lat,lng] point in miles
 *
 * @api public
 */

location.prototype.milesFrom = function(item, point) {
	return calculateDistance(this.get(this.paths.geo), point) * RADIUS_MILES;
}

/*!
 * Export class
 */

exports = module.exports = location;
<commit_msg>Improvement to invalid geo handling in Location fields, fixes #344<commit_after>/*!
 * Module dependencies.
 */

var _ = require('underscore'),
	keystone = require('../../'),
	querystring = require('querystring'),
	https = require('https'),
	util = require('util'),
	utils = require('keystone-utils'),
	super_ = require('../field');

var RADIUS_KM = 6371,
	RADIUS_MILES = 3959;

/**
 * Location FieldType Constructor
 * @extends Field
 * @api public
 */

function location(list, path, options) {

	this._underscoreMethods = ['format', 'googleLookup', 'kmFrom', 'milesFrom'];

	this.enableMapsAPI = keystone.get('google api key') ? true : false;

	if (!options.defaults) {
		options.defaults = {};
	}

	if (options.required) {
		if (Array.isArray(options.required)) {
			this.requiredPaths = options.required;
		} else if ('string' == typeof options.required) {
			this.requiredPaths = options.required.replace(/,/g, ' ').split(/\s+/);
		} else {
			this.requiredPaths = ['street1', 'suburb'];
		}
		options.required = true;
	} else {
		this.requiredPaths = [];
	}

	location.super_.call(this, list, path, options);

};

/*!
 * Inherit from Field
 */

util.inherits(location, super_);

/**
 * Registers the field on the List's Mongoose Schema.
 *
 * @api public
 */

location.prototype.addToSchema = function() {

	var field = this,
		schema = this.list.schema,
		options = this.options;

	var paths = this.paths = {
		number: this._path.append('.number'),
		name: this._path.append('.name'),
		street1: this._path.append('.street1'),
		street2: this._path.append('.street2'),
		suburb: this._path.append('.suburb'),
		state: this._path.append('.state'),
		postcode: this._path.append('.postcode'),
		country: this._path.append('.country'),
		geo: this._path.append('.geo'),
		geo_lat: this._path.append('.geo_lat'),
		geo_lng: this._path.append('.geo_lng'),
		serialised: this._path.append('.serialised'),
		improve: this._path.append('_improve'),
		overwrite: this._path.append('_improve_overwrite')
	};

	var getFieldDef = function(type, key) {
		var def = { type: type };
		if (options.defaults[key]) {
			def.default = options.defaults[key];
		}
		return def;
	}

	schema.nested[this.path] = true;
	schema.add({
		number: getFieldDef(String, 'number'),
		name: getFieldDef(String, 'name'),
		street1: getFieldDef(String, 'street1'),
		street2: getFieldDef(String, 'street2'),
		street3: getFieldDef(String, 'street3'),
		suburb: getFieldDef(String, 'suburb'),
		state: getFieldDef(String, 'state'),
		postcode: getFieldDef(String, 'postcode'),
		country: getFieldDef(String, 'country'),
		geo: { type: [Number], index: '2dsphere' }
	}, this.path + '.');

	schema.virtual(paths.serialised).get(function() {
		return _.compact([
			this.get(paths.number),
			this.get(paths.name),
			this.get(paths.street1),
			this.get(paths.street2),
			this.get(paths.suburb),
			this.get(paths.state),
			this.get(paths.postcode),
			this.get(paths.country)
		]).join(', ');
	});

	// pre-save hook to fix blank geo fields
	// see http://stackoverflow.com/questions/16388836/does-applying-a-2dsphere-index-on-a-mongoose-schema-force-the-location-field-to
	schema.pre('save', function(next) {
		var obj = field._path.get(this);
		if (Array.isArray(obj.geo) && (obj.geo.length !== 2 || (obj.geo[0] === null && obj.geo[1] === null))) {
			obj.geo = undefined;
		}
		next();
	});

	this.bindUnderscoreMethods();

}

/**
 * Formats a list of the values stored by the field. Only paths that
 * have values will be included.
 *
 * Optionally provide a space-separated list of values to include.
 *
 * Delimiter defaults to `', '`.
 *
 * @api public
 */

location.prototype.format = function(item, values, delimiter) {

	if (!values) {
		return item.get(this.paths.serialised);
	}

	var paths = this.paths;

	values = values.split(' ').map(function(i) {
		return item.get(paths[i]);
	});

	return _.compact(values).join(delimiter || ', ');

}

/**
 * Detects whether the field has been modified
 *
 * @api public
 */

location.prototype.isModified = function(item) {
	return item.isModified(this.paths.number)
		|| item.isModified(this.paths.name)
		|| item.isModified(this.paths.street1)
		|| item.isModified(this.paths.street2)
		|| item.isModified(this.paths.suburb)
		|| item.isModified(this.paths.state)
		|| item.isModified(this.paths.postcode)
		|| item.isModified(this.paths.country)
		|| item.isModified(this.paths.geo);
}

/**
 * Validates that a value for this field has been provided in a data object
 *
 * options.required specifies an array or space-delimited list of paths that
 * are required (defaults to street1, suburb)
 *
 * @api public
 */

location.prototype.validateInput = function(data, required, item) {

	if (required) {

		var paths = this.paths,
			valid = true;

		this.requiredPaths.forEach(function(path) {

			if (!(paths[path] in data) && item && item.get(paths[path])) {
				return;
			}

			if (!data[paths[path]]) {
				valid = false;
			}

		});

		return valid;

	} else {

		return true;

	}
}

/**
 * Updates the value for this field in the item from a data object
 *
 * @api public
 */

location.prototype.updateItem = function(item, data) {

	var paths = this.paths;

	var setValue = function(key) {
		if (paths[key] in data && data[paths[key]] != item.get(paths[key])) {
			item.set(paths[key], data[paths[key]] || null);
		}
	}

	_.each(['number', 'name', 'street1', 'street2', 'suburb', 'state', 'postcode', 'country'], setValue);

	if (paths.geo in data) {

		var oldGeo = item.get(paths.geo) || [],
			newGeo = data[paths.geo];

		if (!Array.isArray(newGeo) || newGeo.length != 2) {
			newGeo = [];
		}

		if (newGeo[0] != oldGeo[0] || newGeo[1] != oldGeo[1]) {
			item.set(paths.geo, newGeo);
		}

	} else if (paths.geo_lat in data && paths.geo_lng in data) {

		var lat = utils.number(data[paths.geo_lat]),
			lng = utils.number(data[paths.geo_lng]);

		if (lat && lng) {
			item.set(paths.geo, [lng, lat]);
		}

	}

}

/**
 * Returns a callback that handles a standard form submission for the field
 *
 * Handles:
 * - `field.paths.improve` in `req.body` - improves data via `.googleLookup()`
 * - `field.paths.overwrite` in `req.body` - in conjunction with `improve`, overwrites existing data
 *
 * @api public
 */

location.prototype.getRequestHandler = function(item, req, paths, callback) {

	var field = this;

	if (utils.isFunction(paths)) {
		callback = paths;
		paths = field.paths;
	} else if (!paths) {
		paths = field.paths;
	}

	callback = callback || function() {};

	return function() {

		var update = req.body[paths.overwrite] ? 'overwrite' : true;

		if (req.body && req.body[paths.improve]) {
			field.googleLookup(item, false, update, function() {
				callback();
			});
		} else {
			callback();
		}

	}

}

/**
 * Immediately handles a standard form submission for the field (see `getRequestHandler()`)
 *
 * @api public
 */

location.prototype.handleRequest = function(item, req, paths, callback) {
	this.getRequestHandler(item, req, paths, callback)();
}

/**
 * Internal Google geocode request method
 *
 * @api private
 */

function doGoogleGeocodeRequest(address, region, callback) {

	// https://developers.google.com/maps/documentation/geocoding/
	// Use of the Google Geocoding API is subject to a query limit of 2,500 geolocation requests per day, except with an enterprise license.
	// Note: the Geocoding API may only be used in conjunction with a Google map; geocoding results without displaying them on a map is prohibited.
	// Please make sure your Keystone app complies with the Google Maps API License.

	var options = {
		sensor: false,
		language: 'en',
		address: address
	};

	if (arguments.length == 2 && 'function' == typeof region) {
		callback = region;
		region = null;
	}

	if (region) {
		options.region = region;
	}

	var endpoint = 'https://maps.googleapis.com/maps/api/geocode/json?' + querystring.stringify(options);

	https.get(endpoint, function(res) {
		var data = [];
		res.on('data', function(chunk) {
				data.push(chunk);
			})
			.on('end', function() {
				var dataBuff = data.join('').trim();
				var result;
				try {
					result = JSON.parse(dataBuff);
				}
				catch (exp) {
					result = {'status_code': 500, 'status_text': 'JSON Parse Failed', 'status': 'UNKNOWN_ERROR'};
				}
				callback(null, result);
			});
	})
	.on('error', function(err) {
		callback(err);
	});
};

/**
 * Autodetect the full address and lat, lng from the stored value.
 *
 * Uses Google's Maps API and may only be used in conjunction with a Google map.
 * Geocoding results without displaying them on a map is prohibited.
 * Please make sure your Keystone app complies with the Google Maps API License.
 *
 * Internal status codes mimic the Google API status codes.
 *
 * @api private
 */

location.prototype.googleLookup = function(item, region, update, callback) {

	if ('function' == typeof update) {
		callback = update;
		update = false;
	}

	var field = this,
		stored = item.get(this.path),
		address = item.get(this.paths.serialised);

	if (address.length == 0) {
		return callback({'status_code': 500, 'status_text': 'No address to geocode', 'status': 'NO_ADDRESS'});
	}

	doGoogleGeocodeRequest(address, region || keystone.get('default region'), function(err, geocode){

		if (err || geocode.status != 'OK') {
			return callback(err);
		}

		// use the first result
		// if there were no results in the array, status would be ZERO_RESULTS
		var result = geocode.results[0];

		// parse the address components into a location object

		var location = {};

		_.each(result.address_components, function(val,key){
			if ( _.indexOf(val.types,'street_number') >= 0 ) {
				location.street1 = location.street1 || [];
				location.street1.push(val.long_name);
			}
			if ( _.indexOf(val.types,'route') >= 0 ) {
				location.street1 = location.street1 || [];
				location.street1.push(val.short_name);
			}
			// in some cases, you get suburb, city as locality - so only use the first
			if ( _.indexOf(val.types,'locality') >= 0 && !location.suburb) {
				location.suburb = val.long_name;
			}
			if ( _.indexOf(val.types,'administrative_area_level_1') >= 0 ) {
				location.state = val.short_name;
			}
			if ( _.indexOf(val.types,'country') >= 0 ) {
				location.country = val.long_name;
			}
			if ( _.indexOf(val.types,'postal_code') >= 0 ) {
				location.postcode = val.short_name;
			}
		});

		if (Array.isArray(location.street1))
			location.street1 = location.street1.join(' ');

		location.geo = [
			result.geometry.location.lng,
			result.geometry.location.lat
		];

		//console.log('------ Google Geocode Results ------');
		//console.log(address);
		//console.log(result);
		//console.log(location);

		if (update == 'overwrite') {
			item.set(field.path, location);
		} else if (update) {
			_.each(location, function(value, key) {
				if (key == 'geo') {
					return;
				}
				if (!stored[key]) {
					item.set(field.paths[key], value);
				}
			});
			if (!Array.isArray(stored.geo) || !stored.geo[0] || !stored.geo[1]) {
				item.set(field.paths.geo, location.geo);
			}
		}

		callback(null, location, result);

	});
};

/**
 * Internal Distance calculation function
 *
 * See http://en.wikipedia.org/wiki/Haversine_formula
 *
 * @api private
 */

function calculateDistance(point1, point2) {

	var dLng = (point2[0] - point1[0]) * Math.PI / 180;
	var dLat = (point2[1] - point1[1]) * Math.PI / 180;
	var lat1 = (point1[1]) * Math.PI / 180;
	var lat2 = (point2[1]) * Math.PI / 180;

	var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLng/2) * Math.sin(dLng/2) * Math.cos(lat1) * Math.cos(lat2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

	return c;

}

/**
 * Returns the distance from a [lat,lng] point in kilometres
 *
 * @api public
 */

location.prototype.kmFrom = function(item, point) {
	return calculateDistance(this.get(this.paths.geo), point) * RADIUS_KM;
}

/**
 * Returns the distance from a [lat,lng] point in miles
 *
 * @api public
 */

location.prototype.milesFrom = function(item, point) {
	return calculateDistance(this.get(this.paths.geo), point) * RADIUS_MILES;
}

/*!
 * Export class
 */

exports = module.exports = location;
<|endoftext|>


<commit_before>// Library of contracts and functors.
// TODO: cache typing judgements on functions in a WeakMap.
define(() => {
  let call = Function.prototype.call;
  let slice = call.bind([].slice);
  let getClassName = call.bind({}.toString);
  let create = Object.create.bind(Object);

  // A contract that allows anything
  let any = (x) => x;

  // Contracts for special values
  let undef = (x) => {
    if (x !== void 0) { throw new TypeError('Expected undefined.'); }
    return x;
  };
  let nul = (x) => {
    if (x !== null) { throw new TypeError('Expected null.'); }
    return x;
  };
  let nan = (x) => {
    if (x === x) { throw new TypeError('Expected NaN.'); }
    return x;
  };

  // Creates a contract that tests the [[Class]]
  // internal property of the object.
  let classOf = (s) => (v) => {
    if (getClassName(v) !== '[object ' + s + ']') {
      throw new TypeError('Expected ' + s);
    }
    return v;
  };

  let array = classOf('Array');
  let date = classOf('Date');
  let regexp = classOf('RegExp');
  let re = r => {
      regexp(r);
      return x => {
          if (!string(x).match(r)) {
              throw new TypeError('Expected a matching string.');
          }
          return x;
      };
  };

  // Creates a contract for a value of type s
  let typeOf = (s) => (v) => {
    if (typeof v !== s) {
      throw new TypeError('Expected a' +
          (s === 'object' ? 'n ' : ' ') + s + '.');
    }
    return v;
  };

  let func = typeOf('function');
  let string = typeOf('string');
  let object = typeOf('object');
  let boolean = typeOf('boolean');
  let number = typeOf('number');

  // Creates a contract for an object inheriting from ctor
  let instanceOf = (ctor) => (inst) => {
    if (!(inst instanceof ctor)) {
      throw new TypeError('Expected an instance of ' + ctor);
    }
    return inst;
  };

  // Asserts n is a signed 32-bit number
  let int32 = (n) => {
    if ((n | 0) !== n) {
      throw new TypeError('Expected a 32-bit integer.');
    }
    return n;
  };

  // Asserts int32 and nonnegative
  let nat32 = (n) => {
    if ((n | 0) !== n || n < 0) {
      throw new TypeError('Expected a 32-bit natural.');
    }
    return n;
  };

  // Creates a contract for an array whose
  // elements all satisfy the contract c
  let arrayOf = (c) => {
    func(c);
    // The function passed to map here
    // restricts c to one argument.
    return (a) => array(a).map(x => c(x));
  };

  // Creates a contract for an object whose
  // enumerable properties all satisfy the contract c
  let objectOf = (c) => {
    func(c);
    return (o) => {
      object(o);
      let result = create(o);
      for (i in o) {
        result[i] = c(o[i]);
      }
      return result;
    };
  };

  // Given an array of contracts, creates a contract for
  // an array whose elements satisfy the respective contracts:
  // the product of the given contracts, indexed by numbers
  let prodn = (cs) => {
    arrayOf(func)(cs);
    let len = cs.length;
    return (args) => {
      array(args);
      if (args.length !== len) {
        throw new TypeError('Expected ' + len + ' elements');
      }
      for (let i = 0; i < len; ++i) {
        // Apply each contract to the
        // corresponding argument.
        args[i] = cs[i](args[i]);
      }
      return args;
    };
  };

  // Given an object whose enumerable properties are contracts,
  // creates a contract for an object whose enumerable properties
  // satisfy the respective contracts: the product of the given
  // contracts, indexed by strings.
  let prods = (cs) => {
    object(cs);
    for (let i in cs) {
      func(cs[i]);
    }
    return (x) => {
      object(x);
      for (let i in cs) {
        x[i] = cs[i](x[i]);
      }
      return x;
    };
  };

  // Given an array of contracts, creates a contract for a
  // 2-element array where item 0 is an index and item 1
  // is a value satisfying the contract at that index
  // in the array: the coproduct of the given contracts,
  // tagged by numbers.
  let coprodn = (cs) => {
    arrayOf(func)(cs);
    return (choice) => {
      array(choice);
      nat32(choice[0]);
      if (choice.length !== 2) {
        throw new TypeError('Expected [nat32, any].');
      }
      if (choice[0] >= cs.length) {
        throw new TypeError('Tag out of range.')
      }
      choice[1] = cs[choice[0]](choice[1]);
      return choice;
    };
  };

  // Given an object of contracts, creates a contract for a
  // 2-element array where item 0 is a property name and item 1
  // is a value satisfying the contract at that property name
  // in the object: the coproduct of the given contracts,
  // tagged by strings.
  let coprods = (cs) => {
    objectOf(func)(cs);
    return (choice) => {
      array(choice);
      string(choice[0]);
      if (choice.length !== 2) {
        throw new TypeError('Expected [string, any].');
      }
      if (!cs.hasOwnProperty(choice[0])) {
        throw new TypeError('Unknown tag.')
      }
      choice[1] = cs[choice[0]](choice[1]);
      return choice;
    };
  };

  // Given an array of contracts, apply all of them.
  // This is the product in the category of sets and inclusions.
  let intersect = (cs) => {
    arrayOf(func)(cs);
    let len = cs.length;
    return (x) => {
      let result = x;
      for (let i = 0; i < len; ++i) {
        result = cs[i](result);
      }
      return result;
    };
  };

  // Given an array of contracts, succeed if any succeeds.
  // This is the coproduct in the category of sets and inclusions.
  let union = (cs) => {
    arrayOf(func)(cs);
    let len = cs.length;
    return (x) => {
      for (let i = 0; i < len; ++i) {
        try {
          return cs[i](x);
        } catch (e) { }
      }
      throw new TypeError('No match among unioned types.')
    };
  };

  // Given an array of functions, returns a contract
  // for those arrays where the elements all map to the
  // same value under the given functions, e.g. given
  // [f, g], we get a contract for those [x, y] for which
  // f(x) === g(y): the pullback of the functions f and g.
  let pbn = (fs) => {
    let c = prodn(fs);
    let len = fs.length;
    return (args) => {
      array(args);
      let result = c(args);
      for (let i = 1; i < len; ++i) {
        if (result[i] !== result[0]) {
          throw new TypeError(
              'Failed to match pullback constraint in position ' + i);
        }
      }
      return args;
    };
  };

  // TODO: pushouts

  // Helper for the hom functor below.
  // hom(a,b).self(contractForThis)(function method(){...})(args...)
  let self = (c) => {
    func(c);
    let homab = this;
    return (method) => {
      // homab(method) checks the pre/post conditions on method
      method = homab(method);
      let result = function (letArgs) {
        // c(this) checks that it is being invoked
        // on the right kind of object
        return method.apply(c(this), arguments);
      };
      result.toString = () => method.toString();
      return result;
    };
  };

  // Creates a contract for a function whose inputs and output
  // satisfy the given contracts.
  let hom = function(/* input1, ..., inputn, output */) {
    let precond = prodn(arrayOf(func)(
        slice(arguments, 0, arguments.length - 1)));
    let postcond = func(arguments[arguments.length - 1]);
    let result = (middle) => {
      func(middle);
      let result = function (letArgs) {
        return postcond(
               middle.apply(this,
               precond(slice(arguments))));
      };
      result.toString =
          ((str) => () => str + '/* guarded */')('' + middle);
      return result;
    };
    result.self = self.bind(result);
    return result;
  };

  // Using prods and hom.self to define an interface:
  // let Fooable = prods({
  //   foo: hom(int32, string).self(Fooable);
  // });

  // Returns a memoized version of c.
  let memo = (c) => {
    c = hom(any, any)(c);
    let memo = new Map();
    return (key) => {
      if (memo.has(key)) {
        return memo.get(key);
      }
      memo.set(key, c(key));
      return key;
    };
  };

  let promOf = (c) => (x) => {
    return x.then(c);
  };

  return {
    allOf: intersect,
    any,
    anyOf: union,
    array,
    arrayOf,
    boolean,
    coprodn,
    coprods,
    date,
    func,
    hom,
    id: any,
    instanceOf,
    int32,
    intersect,
    memo,
    nan,
    nat32,
    nul,
    number,
    object,
    objectOf,
    pbn,
    prodn,
    prods,
    promOf,
    re,
    regexp,
    string,
    undef,
    union
  };
});
<commit_msg>Add promOf, switch back to creating object for prods, prodn because mapping shouldn't alter original<commit_after>// Library of contracts and functors.
// TODO: cache typing judgements on functions in a WeakMap.
define(() => {
  let call = Function.prototype.call;
  let slice = call.bind([].slice);
  let getClassName = call.bind({}.toString);
  let create = Object.create.bind(Object);

  // A contract that allows anything
  let any = (x) => x;

  // Contracts for special values
  let undef = (x) => {
    if (x !== void 0) { throw new TypeError('Expected undefined.'); }
    return x;
  };
  let nul = (x) => {
    if (x !== null) { throw new TypeError('Expected null.'); }
    return x;
  };
  let nan = (x) => {
    if (x === x) { throw new TypeError('Expected NaN.'); }
    return x;
  };

  // Creates a contract that tests the [[Class]]
  // internal property of the object.
  let classOf = (s) => (v) => {
    if (getClassName(v) !== '[object ' + s + ']') {
      throw new TypeError('Expected ' + s);
    }
    return v;
  };

  let array = classOf('Array');
  let date = classOf('Date');
  let regexp = classOf('RegExp');
  let promise = classOf('Promise');

  let re = r => {
      regexp(r);
      return x => {
          if (!string(x).match(r)) {
              throw new TypeError('Expected a matching string.');
          }
          return x;
      };
  };

  let promOf = (c) => (x) => {
    return x.then(c);
  };

  // Creates a contract for a value of type s
  let typeOf = (s) => (v) => {
    if (typeof v !== s) {
      throw new TypeError('Expected a' +
          (s === 'object' ? 'n ' : ' ') + s + '.');
    }
    return v;
  };

  let func = typeOf('function');
  let string = typeOf('string');
  let object = typeOf('object');
  let boolean = typeOf('boolean');
  let number = typeOf('number');

  // Creates a contract for an object inheriting from ctor
  let instanceOf = (ctor) => (inst) => {
    if (!(inst instanceof ctor)) {
      throw new TypeError('Expected an instance of ' + ctor);
    }
    return inst;
  };

  // Asserts n is a signed 32-bit number
  let int32 = (n) => {
    if ((n | 0) !== n) {
      throw new TypeError('Expected a 32-bit integer.');
    }
    return n;
  };

  // Asserts int32 and nonnegative
  let nat32 = (n) => {
    if ((n | 0) !== n || n < 0) {
      throw new TypeError('Expected a 32-bit natural.');
    }
    return n;
  };

  // Creates a contract for an array whose
  // elements all satisfy the contract c
  let arrayOf = (c) => {
    func(c);
    // The function passed to map here
    // restricts c to one argument.
    return (a) => array(a).map(x => c(x));
  };

  // Creates a contract for an object whose
  // enumerable properties all satisfy the contract c
  let objectOf = (c) => {
    func(c);
    return (o) => {
      object(o);
      let result = create(o);
      for (i in o) {
        result[i] = c(o[i]);
      }
      return result;
    };
  };

  // Given an array of contracts, creates a contract for
  // an array whose elements satisfy the respective contracts:
  // the product of the given contracts, indexed by numbers
  let prodn = (cs) => {
    arrayOf(func)(cs);
    let len = cs.length;
    return (args) => {
      array(args);
      if (args.length !== len) {
        throw new TypeError('Expected ' + len + ' elements');
      }
      let result = [];
      for (let i = 0; i < len; ++i) {
        // Apply each contract to the
        // corresponding argument.
        result[i] = cs[i](args[i]);
      }
      return result;
    };
  };

  // Given an object whose enumerable properties are contracts,
  // creates a contract for an object whose enumerable properties
  // satisfy the respective contracts: the product of the given
  // contracts, indexed by strings.
  let prods = (cs) => {
    object(cs);
    for (let i in cs) {
      func(cs[i]);
    }
    return (x) => {
      let y = Object.create(object(x));
      for (let i in cs) {
        y[i] = cs[i](x[i]);
      }
      return y;
    };
  };

  // Given an array of contracts, creates a contract for a
  // 2-element array where item 0 is an index and item 1
  // is a value satisfying the contract at that index
  // in the array: the coproduct of the given contracts,
  // tagged by numbers.
  let coprodn = (cs) => {
    arrayOf(func)(cs);
    return (choice) => {
      array(choice);
      nat32(choice[0]);
      if (choice.length !== 2) {
        throw new TypeError('Expected [nat32, any].');
      }
      if (choice[0] >= cs.length) {
        throw new TypeError('Tag out of range.')
      }
      choice[1] = cs[choice[0]](choice[1]);
      return choice;
    };
  };

  // Given an object of contracts, creates a contract for a
  // 2-element array where item 0 is a property name and item 1
  // is a value satisfying the contract at that property name
  // in the object: the coproduct of the given contracts,
  // tagged by strings.
  let coprods = (cs) => {
    objectOf(func)(cs);
    return (choice) => {
      array(choice);
      string(choice[0]);
      if (choice.length !== 2) {
        throw new TypeError('Expected [string, any].');
      }
      if (!cs.hasOwnProperty(choice[0])) {
        throw new TypeError('Unknown tag.')
      }
      choice[1] = cs[choice[0]](choice[1]);
      return choice;
    };
  };

  // Given an array of contracts, apply all of them.
  // This is the product in the category of sets and inclusions.
  let intersect = (cs) => {
    arrayOf(func)(cs);
    let len = cs.length;
    return (x) => {
      let result = x;
      for (let i = 0; i < len; ++i) {
        result = cs[i](result);
      }
      return result;
    };
  };

  // Given an array of contracts, succeed if any succeeds.
  // This is the coproduct in the category of sets and inclusions.
  let union = (cs) => {
    arrayOf(func)(cs);
    let len = cs.length;
    return (x) => {
      for (let i = 0; i < len; ++i) {
        try {
          return cs[i](x);
        } catch (e) { }
      }
      throw new TypeError('No match among unioned types.')
    };
  };

  // Given an array of functions, returns a contract
  // for those arrays where the elements all map to the
  // same value under the given functions, e.g. given
  // [f, g], we get a contract for those [x, y] for which
  // f(x) === g(y): the pullback of the functions f and g.
  let pbn = (fs) => {
    let c = prodn(fs);
    let len = fs.length;
    return (args) => {
      array(args);
      let result = c(args);
      for (let i = 1; i < len; ++i) {
        if (result[i] !== result[0]) {
          throw new TypeError(
              'Failed to match pullback constraint in position ' + i);
        }
      }
      return args;
    };
  };

  // TODO: pushouts

  // Helper for the hom functor below.
  // hom(a,b).self(contractForThis)(function method(){...})(args...)
  let self = (c) => {
    func(c);
    let homab = this;
    return (method) => {
      // homab(method) checks the pre/post conditions on method
      method = homab(method);
      let result = function (letArgs) {
        // c(this) checks that it is being invoked
        // on the right kind of object
        return method.apply(c(this), arguments);
      };
      result.toString = () => method.toString();
      return result;
    };
  };

  // Creates a contract for a function whose inputs and output
  // satisfy the given contracts.
  let hom = function(/* input1, ..., inputn, output */) {
    let precond = prodn(arrayOf(func)(
        slice(arguments, 0, arguments.length - 1)));
    let postcond = func(arguments[arguments.length - 1]);
    let result = (middle) => {
      func(middle);
      let result = function (letArgs) {
        return postcond(
               middle.apply(this,
               precond(slice(arguments))));
      };
      result.toString =
          ((str) => () => str + '/* guarded */')('' + middle);
      return result;
    };
    result.self = self.bind(result);
    return result;
  };

  // Using prods and hom.self to define an interface:
  // let Fooable = prods({
  //   foo: hom(int32, string).self(Fooable);
  // });

  // Returns a memoized version of c.
  let memo = (c) => {
    c = hom(any, any)(c);
    let memo = new Map();
    return (key) => {
      if (memo.has(key)) {
        return memo.get(key);
      }
      memo.set(key, c(key));
      return key;
    };
  };

  return {
    allOf: intersect,
    any,
    anyOf: union,
    array,
    arrayOf,
    boolean,
    coprodn,
    coprods,
    date,
    func,
    hom,
    id: any,
    instanceOf,
    int32,
    intersect,
    memo,
    nan,
    nat32,
    nul,
    number,
    object,
    objectOf,
    pbn,
    prodn,
    prods,
    promOf,
    promise,
    re,
    regexp,
    string,
    undef,
    union
  };
});
<|endoftext|>


<commit_before>var zmq = require('..')
  , should = require('should')
  , semver = require('semver');

describe('socket.xpub-xsub', function () {
    var pub, sub, xpub, xsub;

    beforeEach(function () {
        pub = zmq.socket('pub');
        sub = zmq.socket('sub');
		xpub = zmq.socket('xpub');
		xsub = zmq.socket('xsub');
    });

    it('should support pub-sub tracing and filtering', function (done) {
        var n = 0;

		pub.bindSync('tcp://*:5556');
		xsub.connect('tcp://127.0.0.1:5556');
		xpub.bindSync('tcp://*:5555');
        sub.connect('tcp://127.0.0.1:5555'); // connect to the xpub

        sub.on('message', function (msg) {
            msg.should.be.an.instanceof(Buffer);

            switch (n++) {
                case 0:
                    console.log('first message');
                    msg.toString().should.equal('js is cool');
                    break;
                case 1:
                    console.log('second message');
                    msg.toString().should.equal('luna is cool too');
                    break;
            }
        });

        sub.subscribe('js');
        sub.subscribe('luna');

        XSubXPubProxy(xsub, xpub, done);

        setTimeout(function () {
            pub.send('js is cool');
            pub.send('ruby is meh');
            pub.send('py is pretty cool');
            pub.send('luna is cool too');
        }, 100.0);

        setTimeout(function () {
            sub.unsubscribe('luna');
        }, 500);
    });

    XSubXPubProxy = function (xsub, xpub, done) {
        var n = 0;

        xsub.on('message', function (msg) {
            xpub.send(msg); // Just re-send message out on the xpub, so subscribers can receive it
        });

        xpub.on('message', function (msg) {
            msg.should.be.an.instanceof(Buffer);

            var type = msg[0] === 0 ? 'unsubscribe' : 'subscribe';
            var channel = msg.slice(1).toString();

            switch (type) {
                case 'subscribe':
                    switch (n++) {
                        case 0:
                            console.log('subscribe js');
                            channel.should.equal('js');
                            break;
                        case 1:
                            console.log('subscribe luna');
                            channel.should.equal('luna');
                            break;
                    }
                    break;
                case 'unsubscribe':
                    switch (n++) {
                        case 2:
                            console.log('unsubscribe luna');
                            channel.should.equal('luna');
                            sub.close();
                            pub.close();
                            xsub.close();
                            xpub.close();
                            done();
                            break;
                    }
                    break;
            }

            xsub.send(msg); // Just re-send message out on the xsub so the publisher knows it has a subscriber
        });
    }

});
<commit_msg>Clean up code in xpub-xsub test<commit_after>var zmq = require('..')
  , should = require('should')
  , semver = require('semver');

describe('socket.xpub-xsub', function () {
    var pub, sub, xpub, xsub;

    beforeEach(function () {
        pub = zmq.socket('pub');
        sub = zmq.socket('sub');
		xpub = zmq.socket('xpub');
		xsub = zmq.socket('xsub');
    });

    it('should support pub-sub tracing and filtering', function (done) {
        var n = 0;

		pub.bindSync('tcp://*:5556');
		xsub.connect('tcp://127.0.0.1:5556');
		xpub.bindSync('tcp://*:5555');
        sub.connect('tcp://127.0.0.1:5555');

        sub.on('message', function (msg) {
            msg.should.be.an.instanceof(Buffer);
            switch (n++) {
                case 0:
                    msg.toString().should.equal('js is cool');
                    break;
                case 1:
                    msg.toString().should.equal('luna is cool too');
                    break;
            }
        });

        sub.subscribe('js');
        sub.subscribe('luna');

        XSubXPubProxy(xsub, xpub, done);

        setTimeout(function () {
            pub.send('js is cool');
            pub.send('ruby is meh');
            pub.send('py is pretty cool');
            pub.send('luna is cool too');
        }, 100.0);

        setTimeout(function () {
            sub.unsubscribe('luna');
        }, 300);
    });

    XSubXPubProxy = function (xsub, xpub, done) {
        var n = 0;

        xsub.on('message', function (msg) {
            xpub.send(msg); // Forward message using the xpub so subscribers can receive it
        });

        xpub.on('message', function (msg) {
            msg.should.be.an.instanceof(Buffer);

            var type = msg[0] === 0 ? 'unsubscribe' : 'subscribe';
            var channel = msg.slice(1).toString();

            switch (type) {
                case 'subscribe':
                    switch (n++) {
                        case 0:
                            channel.should.equal('js');
                            break;
                        case 1:
                            channel.should.equal('luna');
                            break;
                    }
                    break;
                case 'unsubscribe':
                    switch (n++) {
                        case 2:
                            channel.should.equal('luna');
                            sub.close();
                            pub.close();
                            xsub.close();
                            xpub.close();
                            done();
                            break;
                    }
                    break;
            }

            xsub.send(msg); // Forward message using the xsub so the publisher knows it has a subscriber
        });
    }
});
<|endoftext|>


<commit_before>/**
 * Copyright 2014 SURFnet bv
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function ($) {
    'use strict';

    $(document).ready(function() {
        $('#revocationModal').on('show.bs.modal', function (event) {
            var button = $(event.relatedTarget),
                data = button.data(),
                sf = {
                    id: data.sfid,
                    identifier: data.sfidentifier,
                    type: data.sftype,
                    identityId: data.sfidentityid,
                    name: data.sfname,
                    email: data.sfemail
                },
                modal = $(this);

            modal.find('.modal-body td.identifier').text(sf.identifier);
            modal.find('.modal-body td.type').text(sf.type);
            modal.find('.modal-body td.name').text(sf.name);
            modal.find('.modal-body td.email').text(sf.email);

            modal.on('click', 'button.revoke', function (event) {
                var form = $('form[name="ra_revoke_second_factor"]'),
                    secondFactorIdInput = $('#ra_revoke_second_factor_secondFactorId'),
                    identityIdInput = $('#ra_revoke_second_factor_identityId');

                modal.find('button').prop('disabled', true);
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                });

                secondFactorIdInput.val(sf.id);
                identityIdInput.val(sf.identityId);

                form.submit();
            });
        });

        $('#removalModal').on('show.bs.modal', function (event) {
            var button = $(event.relatedTarget),
                data = button.data(),
                sf = {
                    id: data.locationid,
                    institution: data.locationinstitution,
                    name: data.locationname,
                    location: data.locationlocation,
                    contactInformation: data.locationcontactinformation
                },
                modal = $(this);

            modal.find('.modal-body td.name').text(sf.name);
            modal.find('.modal-body td.location').text(sf.location);
            modal.find('.modal-body td.contactInformation').text(sf.contactInformation);

            modal.on('click', 'button.remove', function (event) {
                var form = $('form[name="ra_remove_ra_location"]'),
                    locationIdInput = $('#ra_remove_ra_location_locationId'),
                    intitutionInput = $('#ra_remove_ra_location_institution');

                modal.find('button').prop('disabled', true);
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                });

                locationIdInput.val(sf.id);
                intitutionInput.val(sf.institution);

                form.submit();
            });
        });

        $(document).on('click', 'form[name="ra_management_create_ra"] button.create-ra', function (event) {
            var form = $('form[name="ra_management_create_ra"]'),
                modal = $('#create_ra_confirmation_modal');

            if (typeof form[0].checkValidity === 'function' && !form[0].checkValidity()) {
                // Allow native validation behaviour.
                return;
            }

            event.preventDefault();

            modal
                .find('.modal-body td.location')
                .text($('textarea#ra_management_create_ra_location').val());
            modal
                .find('.modal-body td.contact-information')
                .text($('textarea#ra_management_create_ra_contactInformation').val());
            modal
                .find('.modal-body td.role')
                .text($('select#ra_management_create_ra_role option:selected').text());

            modal.modal();

            modal.on('click', 'button.confirm', function (event) {
                var confirmationButton = modal.find('button.confirm');
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                });

                event.preventDefault();

                modal.find('button').prop('disabled', true);
                confirmationButton.html('');

                form.submit();
            })
        });

        $(document).on('click', 'form[name="ra_management_change_ra_role"] button.change-ra-role', function (event) {
            var form = $('form[name="ra_management_change_ra_role"]'),
                modal = $('#change_ra_role_confirmation_modal');

            if (typeof form[0].checkValidity === 'function' && !form[0].checkValidity()) {
                // Allow native validation behaviour.
                return;
            }

            event.preventDefault();

            modal
                .find('.modal-body td.role')
                .text($('select#ra_management_change_ra_role_role option:selected').text());

            modal.modal();

            modal.on('click', 'button.confirm', function (event) {
                var confirmationButton = modal.find('button.confirm');
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                });

                event.preventDefault();

                modal.find('button').prop('disabled', true);
                confirmationButton.html('');

                form.submit();
            })
        });

        $(document).on('click', '.not-yet-implemented', function (event) {
            event.preventDefault();

            alert('Sorry, this functionality has not yet been implemented...');
        });

        // Format all <time> elements to local timezone.
        $("time[datetime]").each(function () {
            $(this).text(
                moment($(this).attr("datetime")).format('Y-MM-DD HH:mm')
            );
        });

        // Prevent form elements from being disabled when the export button is clicked.
        $(document).on('submit', function () {
            var $clickedButton = $(document.activeElement),
                $form = $(this);

            if ($clickedButton.attr('id') === 'ra_search_ra_second_factors_export') {
                setTimeout(function () {
                    $form.find('button, input, textarea, select').prop('disabled', false);
                }, 0);
            }
        });

        // Hide the export button when no search results found on the second factor screen
        if (!$('.search-second-factors table.table-striped').length) {
            $('button#ra_search_ra_second_factors_export').hide();
        }

    });
})(jQuery);
<commit_msg>Update the create ra(a) confirmation modal<commit_after>/**
 * Copyright 2014 SURFnet bv
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function ($) {
    'use strict';

    $(document).ready(function() {
        $('#revocationModal').on('show.bs.modal', function (event) {
            var button = $(event.relatedTarget),
                data = button.data(),
                sf = {
                    id: data.sfid,
                    identifier: data.sfidentifier,
                    type: data.sftype,
                    identityId: data.sfidentityid,
                    name: data.sfname,
                    email: data.sfemail
                },
                modal = $(this);

            modal.find('.modal-body td.identifier').text(sf.identifier);
            modal.find('.modal-body td.type').text(sf.type);
            modal.find('.modal-body td.name').text(sf.name);
            modal.find('.modal-body td.email').text(sf.email);

            modal.on('click', 'button.revoke', function (event) {
                var form = $('form[name="ra_revoke_second_factor"]'),
                    secondFactorIdInput = $('#ra_revoke_second_factor_secondFactorId'),
                    identityIdInput = $('#ra_revoke_second_factor_identityId');

                modal.find('button').prop('disabled', true);
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                });

                secondFactorIdInput.val(sf.id);
                identityIdInput.val(sf.identityId);

                form.submit();
            });
        });

        $('#removalModal').on('show.bs.modal', function (event) {
            var button = $(event.relatedTarget),
                data = button.data(),
                sf = {
                    id: data.locationid,
                    institution: data.locationinstitution,
                    name: data.locationname,
                    location: data.locationlocation,
                    contactInformation: data.locationcontactinformation
                },
                modal = $(this);

            modal.find('.modal-body td.name').text(sf.name);
            modal.find('.modal-body td.location').text(sf.location);
            modal.find('.modal-body td.contactInformation').text(sf.contactInformation);

            modal.on('click', 'button.remove', function (event) {
                var form = $('form[name="ra_remove_ra_location"]'),
                    locationIdInput = $('#ra_remove_ra_location_locationId'),
                    intitutionInput = $('#ra_remove_ra_location_institution');

                modal.find('button').prop('disabled', true);
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                });

                locationIdInput.val(sf.id);
                intitutionInput.val(sf.institution);

                form.submit();
            });
        });

        $(document).on('click', 'form[name="ra_management_create_ra"] button.create-ra', function (event) {
            var form = $('form[name="ra_management_create_ra"]'),
                modal = $('#create_ra_confirmation_modal');

            if (typeof form[0].checkValidity === 'function' && !form[0].checkValidity()) {
                // Allow native validation behaviour.
                return;
            }

            event.preventDefault();

            modal
                .find('.modal-body td.location')
                .text($('textarea#ra_management_create_ra_location').val());
            modal
                .find('.modal-body td.contact-information')
                .text($('textarea#ra_management_create_ra_contactInformation').val());
            modal
                .find('.modal-body td.role')
                .text($('select#ra_management_create_ra_role option:selected').text() + " @ " + $('select#ra_management_create_ra_raInstitution option:selected').text());

            modal.modal();

            modal.on('click', 'button.confirm', function (event) {
                var confirmationButton = modal.find('button.confirm');
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                });

                event.preventDefault();

                modal.find('button').prop('disabled', true);
                confirmationButton.html('');

                form.submit();
            })
        });

        $(document).on('click', 'form[name="ra_management_change_ra_role"] button.change-ra-role', function (event) {
            var form = $('form[name="ra_management_change_ra_role"]'),
                modal = $('#change_ra_role_confirmation_modal');

            if (typeof form[0].checkValidity === 'function' && !form[0].checkValidity()) {
                // Allow native validation behaviour.
                return;
            }

            event.preventDefault();

            modal
                .find('.modal-body td.role')
                .text($('select#ra_management_change_ra_role_role option:selected').text());

            modal.modal();

            modal.on('click', 'button.confirm', function (event) {
                var confirmationButton = modal.find('button.confirm');
                modal.on('hide.bs.modal', function (event) {
                    event.preventDefault();
                });

                event.preventDefault();

                modal.find('button').prop('disabled', true);
                confirmationButton.html('');

                form.submit();
            })
        });

        $(document).on('click', '.not-yet-implemented', function (event) {
            event.preventDefault();

            alert('Sorry, this functionality has not yet been implemented...');
        });

        // Format all <time> elements to local timezone.
        $("time[datetime]").each(function () {
            $(this).text(
                moment($(this).attr("datetime")).format('Y-MM-DD HH:mm')
            );
        });

        // Prevent form elements from being disabled when the export button is clicked.
        $(document).on('submit', function () {
            var $clickedButton = $(document.activeElement),
                $form = $(this);

            if ($clickedButton.attr('id') === 'ra_search_ra_second_factors_export') {
                setTimeout(function () {
                    $form.find('button, input, textarea, select').prop('disabled', false);
                }, 0);
            }
        });

        // Hide the export button when no search results found on the second factor screen
        if (!$('.search-second-factors table.table-striped').length) {
            $('button#ra_search_ra_second_factors_export').hide();
        }

    });
})(jQuery);
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var ShortId = require('./shortid');

var defaultSave = mongoose.Model.prototype.save;
mongoose.Model.prototype.save = function(cb) {
  for (fieldName in this.schema.tree) {
    if (this.isNew && this[fieldName] === undefined) {
        var idType = this.schema.tree[fieldName];

        if (idType === ShortId || idType.type === ShortId) {
            var idInfo = this.schema.path(fieldName);
            var retries = idInfo.retries;
            var self = this;
            function attemptSave() {
                idInfo.generator(idInfo.generatorOptions, function(err, id) {
                    if (err) {
                        cb(err);
                        return;
                    }
                    self[fieldName] = id;
                    defaultSave.call(self, function(err, obj) {
                        if (err &&
                            err.code == 11000 &&
                            err.err.indexOf(fieldName) !== -1 &&
                            retries > 0
                        ) {
                            --retries;
                            attemptSave();
                        } else {
                            // TODO check these args
                            cb(err, obj);
                        }
                    });
                });
            }
            attemptSave();
            return;
        }
    }
  }
  defaultSave.call(this, cb);
};

module.exports = exports = ShortId;
<commit_msg>Create a variable in scope to avoid being override<commit_after>var mongoose = require('mongoose');
var ShortId = require('./shortid');

var defaultSave = mongoose.Model.prototype.save;
mongoose.Model.prototype.save = function(cb) {
  for (key in this.schema.tree) {
    var fieldName = key
    if (this.isNew && this[fieldName] === undefined) {
        var idType = this.schema.tree[fieldName];

        if (idType === ShortId || idType.type === ShortId) {
            var idInfo = this.schema.path(fieldName);
            var retries = idInfo.retries;
            var self = this;
            function attemptSave() {
                idInfo.generator(idInfo.generatorOptions, function(err, id) {
                    if (err) {
                        cb(err);
                        return;
                    }
                    self[fieldName] = id;
                    defaultSave.call(self, function(err, obj) {
                        if (err &&
                            err.code == 11000 &&
                            err.err.indexOf(fieldName) !== -1 &&
                            retries > 0
                        ) {
                            --retries;
                            attemptSave();
                        } else {
                            // TODO check these args
                            cb(err, obj);
                        }
                    });
                });
            }
            attemptSave();
            return;
        }
    }
  }
  defaultSave.call(this, cb);
};

module.exports = exports = ShortId;
<|endoftext|>