<commit_before>var AdmZip = require('adm-zip'),
	async = require('async'),
	constants = require('./constants'),
	exec = require('child_process').exec,
	fs = require('fs'),
	path = require('path'),
	request = require('request'),
	tiappXml = require('tiapp.xml'),
	U = require('./utils');

module.exports = function sdk(opts, callback) {

	// validate input
	callback = U.maybeCallback(arguments[arguments.length-1]);
	if (!opts || U.isFunction(opts)) {
		opts = {};
	}

	// validate command type
	var type = opts.type || 'get';
	if (type !== 'get' && type !== 'set' && type !== 'install' && type !== 'update') {
		return callback('Invalid type "' + type + '"');
	}

	try {
		var tiapp;

		if (type === 'get') {

			tiapp = tiappXml.load(opts.tiapp);

			// get the tiapp property holding the SDK name
			var mwSdk = tiapp.getProperty('mw-sdk-name');
			if (!mwSdk) {
				return callback(null, null);
			}

			// search for the installed module
			var modules = tiapp.getModules();
			for (var i = 0; i < modules.length; i++) {
				if (modules[i].id === mwSdk) {

					// return module object if found
					return callback(null, modules[i]);
				}
			}
		} else if (type === 'set') {

			if (!opts.name) {
				return callback('No sdk name specified for sdk() with type "set"');
			}

			tiapp = tiappXml.load(opts.tiapp);

			// write sdk name as tiapp property
			tiapp.setProperty('mw-sdk-name', opts.name, 'string');

			// set the native commonjs module
			tiapp.setModule(opts.name, {
				version: opts.version,
				platform: 'commonjs'
			});

			// write the tiapp.xml
			tiapp.write();

		} else if (type === 'install' || type === 'update') {

			// pass in opts, prompt for creds, authenticate, then get updates
			return async.waterfall([
				function(cb) { return cb(null, opts); },
				U.authenticate, updateRequest
			], callback);

		}
	} catch (e) {
		return callback(e);
	}

	return callback(null, null);
};

function updateRequest(opts, callback) {
	return U.doRequest(
		constants.UPDATE_API,
		{
			method: 'GET',
			cookie: opts.cookie,
			host: opts.host,
			port: opts.port,
			success: function(res, data) {
				try {
					var ti = path.join(__dirname,'..','node_modules','.bin','titanium'),
						cmd = ti + ' sdk -o json';

					exec(cmd, function(err, stdout, stderr) {
						if (err) { throw err; }
						var tiPath = JSON.parse(stdout).defaultInstallLocation,
							updates = JSON.parse(data).result.modules;

						updates = updates.filter(function(i) {
							return (!opts.name || i.name === opts.name) &&
								(!opts.version || i.version === opts.version) ;
						});

						async.each(updates, function(i, cb) {
							var moduleName = path.basename(i.url),
								modulePath = path.join(tiPath, moduleName);

							var req = request(i.url);
							req.pipe(fs.createWriteStream(modulePath));
							req.on('end', function() {
								console.log('unzipping ' + modulePath + ' to ' + tiPath);
								var zip = new AdmZip(modulePath);
								zip.extractAllTo(tiPath, true);
								fs.unlinkSync(modulePath);
								cb();
							}, callback);
						});
					});
				} catch (e) {
					return callback(e);
				}
			}
		},
		callback
	);
}
<commit_msg>linting<commit_after>var AdmZip = require('adm-zip'),
	async = require('async'),
	constants = require('./constants'),
	exec = require('child_process').exec,
	fs = require('fs'),
	path = require('path'),
	request = require('request'),
	tiappXml = require('tiapp.xml'),
	U = require('./utils');

module.exports = function sdk(opts, callback) {

	// validate input
	callback = U.maybeCallback(arguments[arguments.length-1]);
	if (!opts || U.isFunction(opts)) {
		opts = {};
	}

	// validate command type
	var type = opts.type || 'get';
	if (type !== 'get' && type !== 'set' && type !== 'install' && type !== 'update') {
		return callback('Invalid type "' + type + '"');
	}

	try {
		var tiapp;

		if (type === 'get') {

			tiapp = tiappXml.load(opts.tiapp);

			// get the tiapp property holding the SDK name
			var mwSdk = tiapp.getProperty('mw-sdk-name');
			if (!mwSdk) {
				return callback(null, null);
			}

			// search for the installed module
			var modules = tiapp.getModules();
			for (var i = 0; i < modules.length; i++) {
				if (modules[i].id === mwSdk) {

					// return module object if found
					return callback(null, modules[i]);
				}
			}
		} else if (type === 'set') {

			if (!opts.name) {
				return callback('No sdk name specified for sdk() with type "set"');
			}

			tiapp = tiappXml.load(opts.tiapp);

			// write sdk name as tiapp property
			tiapp.setProperty('mw-sdk-name', opts.name, 'string');

			// set the native commonjs module
			tiapp.setModule(opts.name, {
				version: opts.version,
				platform: 'commonjs'
			});

			// write the tiapp.xml
			tiapp.write();

		} else if (type === 'install' || type === 'update') {

			// pass in opts, prompt for creds, authenticate, then get updates
			return async.waterfall([
				function(cb) { return cb(null, opts); },
				U.authenticate, updateRequest
			], callback);

		}
	} catch (e) {
		return callback(e);
	}

	return callback(null, null);
};

function updateRequest(opts, callback) {
	return U.doRequest(
		constants.UPDATE_API,
		{
			method: 'GET',
			cookie: opts.cookie,
			host: opts.host,
			port: opts.port,
			success: function(res, data) {
				try {
					var ti = path.join(__dirname,'..','node_modules','.bin','titanium'),
						cmd = ti + ' sdk -o json';

					exec(cmd, function(err, stdout) {
						if (err) { throw err; }
						var tiPath = JSON.parse(stdout).defaultInstallLocation,
							updates = JSON.parse(data).result.modules;

						updates = updates.filter(function(i) {
							return (!opts.name || i.name === opts.name) &&
								(!opts.version || i.version === opts.version) ;
						});

						async.each(updates, function(i, cb) {
							var moduleName = path.basename(i.url),
								modulePath = path.join(tiPath, moduleName);

							var req = request(i.url);
							req.pipe(fs.createWriteStream(modulePath));
							req.on('end', function() {
								console.log('unzipping ' + modulePath + ' to ' + tiPath);
								var zip = new AdmZip(modulePath);
								zip.extractAllTo(tiPath, true);
								fs.unlinkSync(modulePath);
								cb();
							}, callback);
						});
					});
				} catch (e) {
					return callback(e);
				}
			}
		},
		callback
	);
}
<|endoftext|>


<commit_before>var fs = require("fs")

var sweet = require("./sweet.js");
var codegen = require("escodegen");

var argv = require("optimist")
            .usage("Usage: sjs [options] path/to/file.js")
            .demand(1)
            .alias('o', 'output')
            .describe('o', 'Output file path')
            .argv;

exports.run = function() {
    var infile = argv._[0];
    var outfile = argv.output;
    var file = fs.readFileSync(infile, "utf8");

    if(outfile) {
        fs.writeFileSync(outfile, codegen.generate(sweet.parse(file)), "utf8");
    } else {
        console.log(codegen.generate(sweet.parse(file)));
    }
};
<commit_msg>add file watch functionality (./bin/sjs --watch ./myfile.sjs --output ./myfile.js)<commit_after>var fs = require("fs");

var sweet = require("./sweet.js");
var codegen = require("escodegen");

var argv = require("optimist")
            .usage("Usage: sjs [options] path/to/file.js")
            .demand(1)
            .alias('o', 'output')
            .describe('o', 'Output file path')
            .alias('watch', 'w')
            .describe('watch', 'watch a file')
            .boolean('watch')
            .argv;

exports.run = function() {
    var infile = argv._[0];
    var outfile = argv.output;
    var watch = argv.watch;
    var file = fs.readFileSync(infile, "utf8");

	if (watch && outfile){
		fs.watch(infile, function(){
			file = fs.readFileSync(infile, "utf8");
			fs.writeFileSync(outfile, codegen.generate(sweet.parse(file)), "utf8");
		});
	} else if(outfile) {
       fs.writeFileSync(outfile, codegen.generate(sweet.parse(file)), "utf8");
    } else {
        console.log(codegen.generate(sweet.parse(file)));
    }
};
<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var srs = require('./_srs');
var _settings = require('./settings');
var exists = require('fs').existsSync || require('path').existsSync;

/*
 This is a custom srs definition for
 spherical mercator that we make
 canonical because no single variant
 of the projection stored by various
 applications is optimal.

 This is basically a modification of gdal's
 understanding of epsg 3857

 Changes:

 * add +over and +wktext to proj4 string
 * remove any double spaces in proj4 string
 * epsg is 3857, the new official epsg for 900913
 * name is pulled from gdal/data/cubwerx_extra.wkt for 900913
   instead of using 'WGS 84 / Pseudo-Mercator' or 'Popular...'

 TODO:
 * +x_0=0.0 vs +x_0=0 (same with +y_0)
 * handle two scaling aliases +k and +k_0
 * meaning of +k=1. vs +k=1.0 ?

*/

var merc_pretty_wkt = 'PROJCS["WGS 84 / Pseudo-Mercator",\n    GEOGCS["WGS 84",\n        DATUM["WGS_1984",\n            SPHEROID["WGS 84",6378137,298.257223563,\n                AUTHORITY["EPSG","7030"]],\n            AUTHORITY["EPSG","6326"]],\n        PRIMEM["Greenwich",0,\n            AUTHORITY["EPSG","8901"]],\n        UNIT["degree",0.0174532925199433,\n            AUTHORITY["EPSG","9122"]],\n        AUTHORITY["EPSG","4326"]],\n    UNIT["metre",1,\n        AUTHORITY["EPSG","9001"]],\n    PROJECTION["Mercator_1SP"],\n    PARAMETER["central_meridian",0],\n    PARAMETER["scale_factor",1],\n    PARAMETER["false_easting",0],\n    PARAMETER["false_northing",0],\n    EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs"],\n    AUTHORITY["EPSG","3857"],\n    AXIS["X",EAST],\n    AXIS["Y",NORTH]]';

exports.canonical = {
  spherical_mercator: {
      proj4: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over',
      srid: 3857, // or 900913
      auth: 'EPSG',
      pretty_wkt: merc_pretty_wkt,
      esri: false,
      name: 'Google Maps Global Mercator', // so many variants here
      valid: true,
      is_geographic: false
  }
};

function oc(a) {
    var o = {};
    for (var i = 0; i < a.length; i++) {
        o[a[i]] = '';
    }
    return o;
}

var merc_names = [
  'Google_Maps_Global_Mercator',
  'Google Maps Global Mercator',
  'WGS 84 / Pseudo-Mercator', // 3857
  'Popular Visualisation CRS / Mercator', // 3785
  'WGS_1984_Web_Mercator', // ESRI
  'WGS_1984_Web_Mercator_Auxiliary_Sphere', // ESRI
  'Popular_Visualisation_CRS_Mercator_deprecated' // wtf
  ];

var merc_srids = [
  900913, // neo-hippy followers of http://crschmidt.net/
  3857, // epsg official, second try
  3785, // epsg deprecated, failed first try
  //3587, // common typo but actually NAD83(NSRS2007) / Michigan Central
  102100, // esri official, second try
  102113, // esri deprecated, failed first try
  41001 //osgeo
  ];

var known_esri_variant_special_cases = [
  ['DATUM["D_OSGB_1936"','DATUM["OSGB_1936"']
];

/*
if we have statically linked libosr then we need
to set the GDAL_DATA directory so that the bundled
.csv and .wkt files are found.
*/
if (_settings.static_osr) {
    process.env.GDAL_DATA = path.join(__dirname, 'srs_data');
}

// push all C++ symbols into js module
for (var k in srs) { exports[k] = srs[k]; }

// make settings available
exports.settings = _settings;

var force_merc = function(result) {
    var new_merc = exports.canonical.spherical_mercator;
    new_merc.input = result.input;
    return new_merc;
};

exports.split_proj = function(literal) {
    var parts = literal.split(' ');
    // remove blank parts due to double spaces (common in proj epsg table)
    var len = parts.length;
    for (i = 0; i < len; i++) {
        if (parts[i] === '') {
            parts.splice(i, 1);
        }
    }
    // break into key=value pairs, discarding +modifiers without values
    var pairs = {};
    parts.sort();
    var new_len = parts.length;
    for (i = 0; i < new_len; i++) {
        var p = parts[i];
        if (p.indexOf('=') != -1) {
            var pair = p.split('=');
            if (pair[1] && pair[1] === '0') {
                // https://github.com/mapbox/tilemill/issues/1866
                pair[1] = '0.0'
            }
            pairs[pair[0]] = pair[1];
        }
    }
    return pairs;
};

var canonical_parts = exports.split_proj(exports.canonical.spherical_mercator.proj4);
var canonical_stringify = JSON.stringify(canonical_parts);

exports.parse = function(arg) {

    if (arg instanceof Buffer) {
        arg = arg.toString();
    }

    if (exists(arg)) {
        var extension = path.extname(arg).toLowerCase();
        var is_json = false;
        if (extension == '.json' || extension == '.geojson') {
            is_json = true;
        }
        var file_data = fs.readFileSync(arg);
        if (!is_json) {
           if (file_data[0] == '{') {
               is_json = true;
           } else {
                 var fstring = file_data.toString();
                 if (
                     ((fstring.search('"type"') > -1) && (fstring.search('"coordinates"') > -1))
                     || (fstring.search('"FeatureCollection"') > -1)
                     || ((fstring.search('"geometryType"') > -1) && (fstring.search('"esriGeometry"') > -1))
                    )
                 {
                   is_json = true;
                 }
           }
        }
        if (is_json) {
            var file = JSON.parse(file_data);
            if (file.crs && file.crs.properties && file.crs.properties.urn) {
                arg = file.crs.properties.urn;
            } else if (file.crs && file.crs.properties && file.crs.properties.name) {
                arg = file.crs.properties.name;
            } else {
                arg = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs';
            }
        }
    }

    for (var hack in known_esri_variant_special_cases) {
        var obj = known_esri_variant_special_cases[hack];
        if (arg.indexOf(obj[0]) > -1) {
            arg = arg.replace(obj[0],obj[1]);
        }
    }
    var result;

    try {
        result = srs._parse(arg);
    } catch (e) {
        if (arg.indexOf('ESRI::') !== 0) {
            result = srs._parse('ESRI::' + arg);
        } else {
            throw e;
        }
    }

    // detect mercator variants and
    // replace with canonical.spherical_mercator
    if (result.name in oc(merc_names)) {
        // this should be a fast track for many .prj files
        return force_merc(result);
    } else if (result.srid in oc(merc_srids)) {
        return force_merc(result);
    } else if (result.proj4 !== undefined && result.proj4.indexOf('+proj=merc') != -1) {
        // catch case of gdal's translation to proj4 being used as input
        if (result.proj4 === '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs') {
           return force_merc(result);
        } else if (result.proj4 === '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +units=m +no_defs') {
           return force_merc(result);
        }
        // break into parts
        // TODO - sort and remove less critical pairs
        var parts = exports.split_proj(result.proj4);
        if (JSON.stringify(parts) === canonical_stringify) {
            return force_merc(result);
        }
    }

    // detect OSGB variant and fix the srid
    // https://github.com/springmeyer/node-srs/issues/25
    if (!result.srid && result.name == 'OSGB 1936 / British National Grid') {
        result.srid = 27700;
        result.auth = 27700;
    }

    return result;
};
<commit_msg>add wgs_84 entry and fix the proj4 for merc to declare +over in the pretty wkt<commit_after>var path = require('path');
var fs = require('fs');
var srs = require('./_srs');
var _settings = require('./settings');
var exists = require('fs').existsSync || require('path').existsSync;

/*
 This is a custom srs definition for
 spherical mercator that we make
 canonical because no single variant
 of the projection stored by various
 applications is optimal.

 This is basically a modification of gdal's
 understanding of epsg 3857

 Changes:

 * add +over and +wktext to proj4 string
 * remove any double spaces in proj4 string
 * epsg is 3857, the new official epsg for 900913
 * name is pulled from gdal/data/cubwerx_extra.wkt for 900913
   instead of using 'WGS 84 / Pseudo-Mercator' or 'Popular...'

 TODO:
 * +x_0=0.0 vs +x_0=0 (same with +y_0)
 * handle two scaling aliases +k and +k_0
 * meaning of +k=1. vs +k=1.0 ?

*/

var merc_pretty_wkt = 'PROJCS["WGS 84 / Pseudo-Mercator",\n    GEOGCS["WGS 84",\n        DATUM["WGS_1984",\n            SPHEROID["WGS 84",6378137,298.257223563,\n                AUTHORITY["EPSG","7030"]],\n            AUTHORITY["EPSG","6326"]],\n        PRIMEM["Greenwich",0,\n            AUTHORITY["EPSG","8901"]],\n        UNIT["degree",0.0174532925199433,\n            AUTHORITY["EPSG","9122"]],\n        AUTHORITY["EPSG","4326"]],\n    UNIT["metre",1,\n        AUTHORITY["EPSG","9001"]],\n    PROJECTION["Mercator_1SP"],\n    PARAMETER["central_meridian",0],\n    PARAMETER["scale_factor",1],\n    PARAMETER["false_easting",0],\n    PARAMETER["false_northing",0],\n    EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"],\n    AUTHORITY["EPSG","3857"],\n    AXIS["X",EAST],\n    AXIS["Y",NORTH]]';

var lon_lat_pretty_wkt = 'GEOGCS["WGS 84",\n    DATUM["WGS_1984",\n        SPHEROID["WGS 84",6378137,298.257223563,\n            AUTHORITY["EPSG","7030"]],\n        TOWGS84[0,0,0,0,0,0,0],\n        AUTHORITY["EPSG","6326"]],\n    PRIMEM["Greenwich",0,\n        AUTHORITY["EPSG","8901"]],\n    UNIT["degree",0.0174532925199433,\n        AUTHORITY["EPSG","9108"]],\n    AUTHORITY["EPSG","4326"]]';

exports.canonical = {
  spherical_mercator: {
      proj4: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over',
      srid: 3857, // or 900913
      auth: 'EPSG',
      pretty_wkt: merc_pretty_wkt,
      esri: false,
      name: 'Google Maps Global Mercator', // so many variants here
      valid: true,
      is_geographic: false
  },
  wgs_84: {
      proj4: '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs',
      srid: 4326,
      auth: 'EPSG',
      pretty_wkt: lon_lat_pretty_wkt,
      esri: false,
      name: 'WGS 84',
      valid: true,
      is_geographic: true
  }
};

function oc(a) {
    var o = {};
    for (var i = 0; i < a.length; i++) {
        o[a[i]] = '';
    }
    return o;
}

var merc_names = [
  'Google_Maps_Global_Mercator',
  'Google Maps Global Mercator',
  'WGS 84 / Pseudo-Mercator', // 3857
  'Popular Visualisation CRS / Mercator', // 3785
  'WGS_1984_Web_Mercator', // ESRI
  'WGS_1984_Web_Mercator_Auxiliary_Sphere', // ESRI
  'Popular_Visualisation_CRS_Mercator_deprecated' // wtf
  ];

var merc_srids = [
  900913, // neo-hippy followers of http://crschmidt.net/
  3857, // epsg official, second try
  3785, // epsg deprecated, failed first try
  //3587, // common typo but actually NAD83(NSRS2007) / Michigan Central
  102100, // esri official, second try
  102113, // esri deprecated, failed first try
  41001 //osgeo
  ];

var known_esri_variant_special_cases = [
  ['DATUM["D_OSGB_1936"','DATUM["OSGB_1936"']
];

/*
if we have statically linked libosr then we need
to set the GDAL_DATA directory so that the bundled
.csv and .wkt files are found.
*/
if (_settings.static_osr) {
    process.env.GDAL_DATA = path.join(__dirname, 'srs_data');
}

// push all C++ symbols into js module
for (var k in srs) { exports[k] = srs[k]; }

// make settings available
exports.settings = _settings;

var force_merc = function(result) {
    var new_merc = exports.canonical.spherical_mercator;
    new_merc.input = result.input;
    return new_merc;
};

exports.split_proj = function(literal) {
    var parts = literal.split(' ');
    // remove blank parts due to double spaces (common in proj epsg table)
    var len = parts.length;
    for (i = 0; i < len; i++) {
        if (parts[i] === '') {
            parts.splice(i, 1);
        }
    }
    // break into key=value pairs, discarding +modifiers without values
    var pairs = {};
    parts.sort();
    var new_len = parts.length;
    for (i = 0; i < new_len; i++) {
        var p = parts[i];
        if (p.indexOf('=') != -1) {
            var pair = p.split('=');
            if (pair[1] && pair[1] === '0') {
                // https://github.com/mapbox/tilemill/issues/1866
                pair[1] = '0.0'
            }
            pairs[pair[0]] = pair[1];
        }
    }
    return pairs;
};

var canonical_parts = exports.split_proj(exports.canonical.spherical_mercator.proj4);
var canonical_stringify = JSON.stringify(canonical_parts);

exports.parse = function(arg) {

    if (arg instanceof Buffer) {
        arg = arg.toString();
    }

    if (exists(arg)) {
        var extension = path.extname(arg).toLowerCase();
        var is_json = false;
        if (extension == '.json' || extension == '.geojson') {
            is_json = true;
        }
        var file_data = fs.readFileSync(arg);
        if (!is_json) {
           if (file_data[0] == '{') {
               is_json = true;
           } else {
                 var fstring = file_data.toString();
                 if (
                     ((fstring.search('"type"') > -1) && (fstring.search('"coordinates"') > -1))
                     || (fstring.search('"FeatureCollection"') > -1)
                     || ((fstring.search('"geometryType"') > -1) && (fstring.search('"esriGeometry"') > -1))
                    )
                 {
                   is_json = true;
                 }
           }
        }
        if (is_json) {
            var file = JSON.parse(file_data);
            if (file.crs && file.crs.properties && file.crs.properties.urn) {
                arg = file.crs.properties.urn;
            } else if (file.crs && file.crs.properties && file.crs.properties.name) {
                arg = file.crs.properties.name;
            } else {
                arg = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs';
            }
        }
    }

    for (var hack in known_esri_variant_special_cases) {
        var obj = known_esri_variant_special_cases[hack];
        if (arg.indexOf(obj[0]) > -1) {
            arg = arg.replace(obj[0],obj[1]);
        }
    }
    var result;

    try {
        result = srs._parse(arg);
    } catch (e) {
        if (arg.indexOf('ESRI::') !== 0) {
            result = srs._parse('ESRI::' + arg);
        } else {
            throw e;
        }
    }

    // detect mercator variants and
    // replace with canonical.spherical_mercator
    if (result.name in oc(merc_names)) {
        // this should be a fast track for many .prj files
        return force_merc(result);
    } else if (result.srid in oc(merc_srids)) {
        return force_merc(result);
    } else if (result.proj4 !== undefined && result.proj4.indexOf('+proj=merc') != -1) {
        // catch case of gdal's translation to proj4 being used as input
        if (result.proj4 === '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs') {
           return force_merc(result);
        } else if (result.proj4 === '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +units=m +no_defs') {
           return force_merc(result);
        }
        // break into parts
        // TODO - sort and remove less critical pairs
        var parts = exports.split_proj(result.proj4);
        if (JSON.stringify(parts) === canonical_stringify) {
            return force_merc(result);
        }
    }

    // detect OSGB variant and fix the srid
    // https://github.com/springmeyer/node-srs/issues/25
    if (!result.srid && result.name == 'OSGB 1936 / British National Grid') {
        result.srid = 27700;
        result.auth = 27700;
    }

    return result;
};
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "ui", "tabManager"
    ];
    main.provides = ["terminal.monitor.message_view"];
    return main;

    function main(options, imports, register) {
        var ui = imports.ui;
        var Plugin = imports.Plugin;
        var tabManager = imports.tabManager;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var css = require("text!./message_view.css");

        tabManager.on("tabDestroy", function() {
            hide();
        });

        tabManager.on("tabBeforeReparent", function() {
            hide();
        });

        var containerNode, contentNode;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Load CSS
            ui.insertCss(css, plugin);
            draw();
        }

        function draw(){
            // Create HTML elements
            var html = require("text!./message_view.html");
            containerNode = ui.insertHtml(null, html, plugin)[0];
            contentNode = containerNode.querySelector(".message");

            containerNode.addEventListener("blur", hide);
            contentNode.addEventListener("click", handleClick);
        }

        function handleClick(e) {
            switch (e.target.getAttribute("data-type")) {
                case "preview":
                    handlePreview(e);
                default:
                    hide();
            }
        }

        function handlePreview(e) {
            e.preventDefault();
            tabManager.open({
                editorType : "preview",
                active     : true,
                document   : {
                    preview : {
                        path: e.target.innerText
                    }
                }
            }, function(err, tab) {});
        }

        function show(message, referenceNode) {
            if (!containerNode)
                return;

            var referenceBoundingRect = referenceNode.getBoundingClientRect();
            var offset = { top: 8, left: 8, right: 8 };
            var top = referenceBoundingRect.top + offset.top;
            var left = referenceBoundingRect.left + offset.left;
            var width = referenceBoundingRect.width - offset.right - offset.left;

            contentNode.innerHTML = message;
            containerNode.style.display = 'block';
            containerNode.style.top = top + 'px';
            containerNode.style.left = left + 'px';
            containerNode.style.width = width + 'px';

            setTimeout(function() {
                containerNode.style.opacity = 1;
            });
            containerNode.focus();
        }

        function hide() {
            if (!containerNode)
                return;

            containerNode.style.display = 'none';
            containerNode.style.opacity = 0;
            contentNode.innerHTML = '';
        }

        plugin.on("load", function(){
            load();
        });

        plugin.freezePublicAPI({
            show: show,
            hide: hide
        });

        register(null, {
            "terminal.monitor.message_view": plugin
        });
    }
});
<commit_msg>Always close on document click<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "ui", "tabManager"
    ];
    main.provides = ["terminal.monitor.message_view"];
    return main;

    function main(options, imports, register) {
        var ui = imports.ui;
        var Plugin = imports.Plugin;
        var tabManager = imports.tabManager;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var css = require("text!./message_view.css");

        tabManager.on("tabDestroy", function() {
            hide();
        });

        tabManager.on("tabBeforeReparent", function() {
            hide();
        });

        var containerNode, contentNode, isVisible = false;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Load CSS
            ui.insertCss(css, plugin);
            draw();
        }

        function draw(){
            // Create HTML elements
            var html = require("text!./message_view.html");
            containerNode = ui.insertHtml(null, html, plugin)[0];
            contentNode = containerNode.querySelector(".message");

            containerNode.addEventListener("blur", hide);
            contentNode.addEventListener("click", handleClick);
            document.addEventListener("click", hide);
        }

        function handleClick(e) {
            switch (e.target.getAttribute("data-type")) {
                case "preview":
                    handlePreview(e);
                default:
                    hide();
            }
        }

        function handlePreview(e) {
            e.preventDefault();
            tabManager.open({
                editorType : "preview",
                active     : true,
                document   : {
                    preview : {
                        path: e.target.innerText
                    }
                }
            }, function(err, tab) {});
        }

        function show(message, referenceNode) {
            if (!containerNode)
                return;

            var referenceBoundingRect = referenceNode.getBoundingClientRect();
            var offset = { top: 8, left: 8, right: 8 };
            var top = referenceBoundingRect.top + offset.top;
            var left = referenceBoundingRect.left + offset.left;
            var width = referenceBoundingRect.width - offset.right - offset.left;

            contentNode.innerHTML = message;
            containerNode.style.display = 'block';
            containerNode.style.top = top + 'px';
            containerNode.style.left = left + 'px';
            containerNode.style.width = width + 'px';

            setTimeout(function() {
                containerNode.style.opacity = 1;
            });
            containerNode.focus();
            isVisible = true;
        }

        function hide() {
            if (!containerNode || !isVisible)
                return;

            containerNode.style.display = 'none';
            containerNode.style.opacity = 0;
            contentNode.innerHTML = '';
            isVisible = false;
        }

        plugin.on("load", function(){
            load();
        });

        plugin.freezePublicAPI({
            show: show,
            hide: hide
        });

        register(null, {
            "terminal.monitor.message_view": plugin
        });
    }
});
<|endoftext|>


<commit_before>'use strict';

function repo_init(){
    core_repo_init({
      'storage': {
        'base-keycode': 0,
        'key': 'H',
        'keycode': 72,
        'keycode-range': 1000,
      },
      'title': 'KeyInfo.htm',
    });

    core_storage_update();

    document.getElementById('fetch-keyinfo-key').onclick = fetch_keyinfo_key;
    document.getElementById('fetch-keyinfo-keycode').onclick = fetch_keyinfo_keycode;
    document.getElementById('generate').onclick = generate_list;

    document.getElementById('text').oninput = function(){
        // Fetch lowercase value.
        var value = this.value.toLowerCase();

        // Display length of inputted text.
        document.getElementById('length').innerHTML = value.length;

        // Reset characters.
        var element = document.getElementById('characters');
        element.innerHTML = '';
        var characters = '0123456789abcdefghijklmnopqrstuvwxyz !@#$%^&*()_-+={}|:;"\'<,>.?/'.split('');
        var output = '';

        // Count how many times each character appears in inputted text.
        for(var character in characters){
            var character_count = value.replace(
              new RegExp(
                '[^' + characters[character] + ']',
                'g'// Global
              ),
              ''
            ).length;

            // Only display characters that appear in inputted text.
            if(character_count <= 0){
                continue;
            }

            output +=
              '
'
              + characters[character]
              + '	'
              + character_count
              + '	'
              + ((character_count / value.length) * 100).toFixed(7)
              + '%
';
        }

        element.innerHTML = output;
    };
}
<commit_msg>added info-events usage<commit_after>'use strict';

function repo_init(){
    core_repo_init({
      'info-events': {
        'fetch-keyinfo-key': {
          'todo': fetch_keyinfo_key,
        },
        'fetch-keyinfo-keycode': {
          'todo': fetch_keyinfo_keycode,
        },
        'generate': {
          'todo': generate_list,
        },
      },
      'storage': {
        'base-keycode': 0,
        'key': 'H',
        'keycode': 72,
        'keycode-range': 1000,
      },
      'title': 'KeyInfo.htm',
    });

    document.getElementById('text').oninput = function(){
        // Fetch lowercase value.
        var value = this.value.toLowerCase();

        // Display length of inputted text.
        document.getElementById('length').innerHTML = value.length;

        // Reset characters.
        var element = document.getElementById('characters');
        element.innerHTML = '';
        var characters = '0123456789abcdefghijklmnopqrstuvwxyz !@#$%^&*()_-+={}|:;"\'<,>.?/'.split('');
        var output = '';

        // Count how many times each character appears in inputted text.
        for(var character in characters){
            var character_count = value.replace(
              new RegExp(
                '[^' + characters[character] + ']',
                'g'// Global
              ),
              ''
            ).length;

            // Only display characters that appear in inputted text.
            if(character_count <= 0){
                continue;
            }

            output +=
              '
'
              + characters[character]
              + '	'
              + character_count
              + '	'
              + ((character_count / value.length) * 100).toFixed(7)
              + '%
';
        }

        element.innerHTML = output;
    };
}
<|endoftext|>


<commit_before>(function(globals){
// Don't worry if that seems a little funky...

  /**
   * Internal representation of the game board in its current state.
   *
   * @see game.board
   * @see game.tracer
   * @see initial
   * @var {Array} of {Array} of {String|null}
   */
  var board = initial(); // initialize the `board`

  /**
   * List of moves for the "Catalan Opening: Closed Variation" suitable for use
   * as arguments to `applyMove` below.
   *
   * @see applyMove
   * @var {Array} of...?
   */
  var moves = [
    // TODO: Fill me in!
    /* possible structure [from{ , }, to{ , }]
    */
  ]; // END moves

  // var current; TODO: do we need this?

  // You don't need to understand `globals` yet...
  var game = globals.game = {
    /**
     * Provide a _copy_ of the game board in order to update the View from it
     *
     * @return {Array} of {Array} of {String|null}
     */
    board: function(){
      return board.map(function(row){
        return row.slice();
      });
    },
    /**
     * Reset the internal game board to it's initial state.
     *
     * @return {Object} the game object for Method Chaining
     */
    reset: function(){
      board = initial();

      return this;
    },
    /**
     * Advance the internal game board to the next move.
     *
     * @return {Object} the game object for Method Chaining
     * @todo Make this work!
     */
    next: function(){
//based on the current move/counter call the applyMove function with the arguments
// from and to for the next move in the moves array
// if the game is at the last move, dont attempt advance the game any further
// increase the game counter by one

      return this;
    },
    /**
     * Advance the internal game board to the previous move.
     *
     * @return {Object} the game object for Method Chaining
     * @todo Make this work!
     */
    prev: function(){
//based on the current move/counter call the applyMove function with the arguments
// from and to for the previous move in the moves array
// if the game is at the start (game counter = 0), dont step back any further
// decrease the game counter by one
      return this;
    },
    /**
     * Advance the internal game board to the last move.
     *
     * @return {Object} the game object for Method Chaining
     * @todo Make this work!
     */
    end: function(){
//move from the current move/counter to the end of the game
//loop through the next function until the game counter has reached the
//last move (moves.length)

      return this;
    },
    /**
     * Provide a printable representation of the game board for use as a tracer
     *
     * @return {String} representation of `board`
     * @todo Refactor to use Array methods?
     */
    tracer: function(){
      var bullet = '';

      for ( var rank = 0; rank < board.length; rank++ ){
        bullet += '|';
        for ( var file = 0; file < board[rank].length; file++ ){
          bullet += board[rank][file] || ' |';
        }
        bullet += '\n';
      }

      return bullet;
    },
    /**
     * Apply a move to the game board, given a `from` and `to` position that both
     * contain values for `rank` and `file`.
     *
     * @param {Object} from with `rank` and `file`
     * @param {Object} to with `rank` and `file`
     * @return undefined
     *
     * @todo Fill me in! ...and remove this comment.
     */
    applyMove: function(from, to){
//take the from and to arguments and apply them to the board
//remove the piece in "from" spot and add it to the "to" spot

    } // END applyMove
  }; // END game

  /**
   * Provide the initial state of the game board, useful for any game.
   *
   * @return {Array} of {Array} of {String|null}
   */
  function initial(){
    return [
      [ 'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R' ],
      [ 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P' ],
      Array(8).fill(null),
      Array(8).fill(null),
      Array(8).fill(null),
      Array(8).fill(null),
      [ 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p' ],
      [ 'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r' ],
    ];
  } // END initial

// You are not expected to understand anything below this line...
})(window || module && module.exports || this);
<commit_msg>fixed the game.tracer to make it more prettier<commit_after>(function(globals){
// Don't worry if that seems a little funky...

  /**
   * Internal representation of the game board in its current state.
   *
   * @see game.board
   * @see game.tracer
   * @see initial
   * @var {Array} of {Array} of {String|null}
   */
  var board = initial(); // initialize the `board`

  /**
   * List of moves for the "Catalan Opening: Closed Variation" suitable for use
   * as arguments to `applyMove` below.
   *
   * @see applyMove
   * @var {Array} of...?
   */
  var moves = [
    // TODO: Fill me in!
    /* possible structure [from{ , }, to{ , }]
    */
  ]; // END moves

  // var current; TODO: do we need this?

  // You don't need to understand `globals` yet...
  var game = globals.game = {
    /**
     * Provide a _copy_ of the game board in order to update the View from it
     *
     * @return {Array} of {Array} of {String|null}
     */
    board: function(){
      return board.map(function(row){
        return row.slice();
      });
    },
    /**
     * Reset the internal game board to it's initial state.
     *
     * @return {Object} the game object for Method Chaining
     */
    reset: function(){
      board = initial();

      return this;
    },
    /**
     * Advance the internal game board to the next move.
     *
     * @return {Object} the game object for Method Chaining
     * @todo Make this work!
     */
    next: function(){
//based on the current move/counter call the applyMove function with the arguments
// from and to for the next move in the moves array
// if the game is at the last move, dont attempt advance the game any further
// increase the game counter by one

      return this;
    },
    /**
     * Advance the internal game board to the previous move.
     *
     * @return {Object} the game object for Method Chaining
     * @todo Make this work!
     */
    prev: function(){
//based on the current move/counter call the applyMove function with the arguments
// from and to for the previous move in the moves array
// if the game is at the start (game counter = 0), dont step back any further
// decrease the game counter by one
      return this;
    },
    /**
     * Advance the internal game board to the last move.
     *
     * @return {Object} the game object for Method Chaining
     * @todo Make this work!
     */
    end: function(){
//move from the current move/counter to the end of the game
//loop through the next function until the game counter has reached the
//last move (moves.length)

      return this;
    },
    /**
     * Provide a printable representation of the game board for use as a tracer
     *
     * @return {String} representation of `board`
     * @todo Refactor to use Array methods?
     */
    tracer: function(){
      var bullet = '';

      for ( rank = 0; rank < board.length; rank++ ){
        bullet += '|';
        for ( var file = 0; file < board[rank].length; file++ ){
          bullet += (board[rank][file] || ' ') + '|';
        }
        bullet += '\n';
      }      return bullet;
  },
    /**
     * Apply a move to the game board, given a `from` and `to` position that both
     * contain values for `rank` and `file`.
     *
     * @param {Object} from with `rank` and `file`
     * @param {Object} to with `rank` and `file`
     * @return undefined
     *
     * @todo Fill me in! ...and remove this comment.
     */
    applyMove: function(from, to){
//take the from and to arguments and apply them to the board
//remove the piece in "from" spot and add it to the "to" spot

    } // END applyMove
  }; // END game

  /**
   * Provide the initial state of the game board, useful for any game.
   *
   * @return {Array} of {Array} of {String|null}
   */
  function initial(){
    return [
      [ 'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R' ],
      [ 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P' ],
      Array(8).fill(null),
      Array(8).fill(null),
      Array(8).fill(null),
      Array(8).fill(null),
      [ 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p' ],
      [ 'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r' ],
    ];
  } // END initial

// You are not expected to understand anything below this line...
})(window || module && module.exports || this);
<|endoftext|>


<commit_before>// Copyright 2014, Josh Puckett

$(function() {

// Set up vars
var defaults = {
	phoneColor: "white",		// "white" or "black"
	hand: true,
	zoom: false,
	isRetina: (window.devicePixelRatio > 1),
	device: "iphone",				// "iphone" or "android"
	background: 0,
	url: "https://s3-us-west-2.amazonaws.com/tweakapp.co/Framewebview/lightbox/index.html"
};

var backgrounds = [
	"",
	"https://s3-us-west-2.amazonaws.com/tweakapp.co/Framewebview/_bgs/bg1.png",
	"https://s3-us-west-2.amazonaws.com/tweakapp.co/Framewebview/_bgs/bg2.png",
];

// Copy defaults to an options object
var options = {};
$.map(defaults, function(value, key){
	options[key] = value;
});

// Fetch GET parameters, apply over options object
var params = window.location.search.substring(1).split("&");
$.map(params, function(param){
	var key_value_pair = param.split('=');

	// Ensure URLs and booleans are properly formatted
	var value = decodeURIComponent(key_value_pair[1]);
	value = (value === "true") ? true : value;
	value = (value === "false") ? false : value;

	options[key_value_pair[0]] = value;
});

// Compares current settings to defaults, updates address bar to reflect delta
var updateAddressBar = function(){
	var paramString = "?";
	$.map(defaults, function(value, key){
		if (options[key] != value){
			paramString += key + "=" + options[key] + "&";
		}
	});
	window.history.pushState({}, "Frameview", window.location.pathname + paramString.slice(0, -1));
}

function prototypeViewer() {

	setBackground();
	setPhoneColor();
	setHand();
	setURL();

	//Set up some object vars based on if zoom has been toggled
	//and if device is retina or not
	if (!options.zoom) {
		viewerHeight = ($(window).height() * .8);
		viewerWidth = viewerHeight * .48588;
		viewerScale = viewerHeight/1630;
	} else {
	 	viewerHeight = options.isRetina ? 1630/2 : 1630;
		viewerWidth = options.isRetina ? 792/2 : 792;
		viewerScale = options.isRetina ? 0.5 : 1;
	}

	//Private object vars
	var isiPhone = (options.device == "iphone");
	var positionLeft = isiPhone ? 75 : 35;
	var positionTop = isiPhone ? 247 : 164;
	var deviceMultiple = isiPhone ? 1.3 : 1.375;
	var deviceLeftMultiple = isiPhone ? 1.352 : 1.433;
	var deviceTopMultiple = isiPhone ? 1.27 : 1.33;

	//Set up viewer
	$('#viewer').css({
		"height": viewerHeight,
		"width": viewerWidth,
		"position": 'absolute',
		"left": ($(window).width() - viewerWidth)/2,
    "top": ($(window).height() - viewerHeight)/2,
	});

	//Set up viewer iframe
	$('#frame').css({
		'webkitTransform': 'scale(' + viewerScale + ', ' + viewerScale + ')',
		'webkitTransformOrigin': '0% 0%',
		'position': 'absolute',
		'left': positionLeft * viewerScale,
		'top': positionTop * viewerScale,
	});

	//Set up hand
	$('#hand').css({
		'height': ((1833 * deviceMultiple) * viewerScale) * 0.7793,
		'width': (1833 * deviceMultiple) * viewerScale,
		'position': 'absolute',
		'left': ($(window).width() - ((1833 * deviceLeftMultiple) * viewerScale))/2,
    'top': $(window).height() - (((1833 * deviceTopMultiple) * viewerScale) * 0.7793),
	});
}

function setBackground(background) {
	options.background = (background != undefined) ? background : options.background;
	if (options.background > backgrounds.length-1){
		options.background = 0;
	}
	if (options.background == 0) {
		$('html').css({
	  	"background": "none"
		});
	} else {
		$('html').css({
			  "background": "url('" + backgrounds[options.background] + "') no-repeat center center fixed",
			  "-webkit-background-size": "cover",
		  	"-moz-background-size": "cover",
		  	"-o-background-size": "cover",
		  	"background-size": "cover"
		});
	}
}

var setPhoneColor = function(phoneColor){
	options.phoneColor = (phoneColor != undefined) ? phoneColor : options.phoneColor;

	var phoneColors = {
		"white": "url('img/iphone_white.png')",
		"black": "url('img/iphone_black.png')"
	};

	if (options.device == "iphone"){
		$('#viewer').css({
			"background-image": phoneColors[options.phoneColor] || phoneColors["white"]
		});
	}

};

var setHand = function(hand){
	options.hand = (hand != undefined) ? hand : options.hand;
	$('#hand').css({
		"background-image": !options.hand ? "none" : "url('img/hand.png')"
	});
};

var setURL = function(url){
	options.url = (url != undefined) ? url : options.url;
	$('.prototypeinput').val(options.url);
	$("#frame").attr("src", options.url);
}

var setDevice = function(device){
	options.device = (device != undefined) ? device : options.device;

	if (options.device == "iphone"){
		$('#iphone').addClass("iphoneactive").removeClass("iphone");
		setPhoneColor();
		$('iframe').css({ "width": "640px", "height": "1136px" });
	}else{
		$('#iphone').addClass("iphone").removeClass("iphoneactive");
	}

	if (options.device == "android"){
		$('#android').addClass("androidactive").removeClass("android");
		$('#viewer').css({
			"background-image": "url('img/nexus.png')"
		});
		$('iframe').css({ "width": "720px", "height": "1280px" });
	}else{
		$('#android').addClass("android").removeClass("androidactive");
	}

	prototypeViewer();
}

// Keypress listeners.
$(window).keypress(function(e) {
	switch (e.which) {
		// Hitting the P key toggles between black and white iPhone
		case 112:
			setPhoneColor((options.phoneColor == "white") ? "black" : "white" );
			updateAddressBar();
			break;
		// Hitting the H key toggles the hand on and off
		case 104:
			setHand(!options.hand);
			updateAddressBar();
			break;
		// Hitting the B key cycles through various backgrounds
		case 98:
			setBackground(options.background + 1);
			updateAddressBar();
			break;
		// Hitting the Z key zooms the viewer to 100% scale
		case 122:
			options.zoom = !options.zoom;
			updateAddressBar();
			prototypeViewer();
			break;
	}
});

// Kick things off and update on resize
$(document).ready(prototypeViewer);
$(window).resize(prototypeViewer);

function search(ele) {
  if(event.keyCode == 13) {
		$("#frame").attr("src", ele.value);
		$('.prototypeinput').blur();
		updateAddressBar();
  }
}

// Needs to be called once on initialize
setDevice();

$("#iphone, #android").click(function(){
	if (options.device == "iphone"){
		setDevice("android");
	}else{
		setDevice("iphone");
	}
});

$("#controls").mouseenter(function(){
	$("#controls").animate({opacity:'1'}, 'fast');
});
$("#controls").mouseleave(function(){
  $("#controls").animate({opacity:'0.1'}, 'slow');
});

});
<commit_msg>Update address bar on Android / iOS toggle change<commit_after>// Copyright 2014, Josh Puckett

$(function() {

// Set up vars
var defaults = {
	phoneColor: "white",		// "white" or "black"
	hand: true,
	zoom: false,
	isRetina: (window.devicePixelRatio > 1),
	device: "iphone",				// "iphone" or "android"
	background: 0,
	url: "https://s3-us-west-2.amazonaws.com/tweakapp.co/Framewebview/lightbox/index.html"
};

var backgrounds = [
	"",
	"https://s3-us-west-2.amazonaws.com/tweakapp.co/Framewebview/_bgs/bg1.png",
	"https://s3-us-west-2.amazonaws.com/tweakapp.co/Framewebview/_bgs/bg2.png",
];

// Copy defaults to an options object
var options = {};
$.map(defaults, function(value, key){
	options[key] = value;
});

// Fetch GET parameters, apply over options object
var params = window.location.search.substring(1).split("&");
$.map(params, function(param){
	var key_value_pair = param.split('=');

	// Ensure URLs and booleans are properly formatted
	var value = decodeURIComponent(key_value_pair[1]);
	value = (value === "true") ? true : value;
	value = (value === "false") ? false : value;

	options[key_value_pair[0]] = value;
});

// Compares current settings to defaults, updates address bar to reflect delta
var updateAddressBar = function(){
	var paramString = "?";
	$.map(defaults, function(value, key){
		if (options[key] != value){
			paramString += key + "=" + options[key] + "&";
		}
	});
	window.history.pushState({}, "Frameview", window.location.pathname + paramString.slice(0, -1));
}

function prototypeViewer() {

	setBackground();
	setPhoneColor();
	setHand();
	setURL();

	//Set up some object vars based on if zoom has been toggled
	//and if device is retina or not
	if (!options.zoom) {
		viewerHeight = ($(window).height() * .8);
		viewerWidth = viewerHeight * .48588;
		viewerScale = viewerHeight/1630;
	} else {
	 	viewerHeight = options.isRetina ? 1630/2 : 1630;
		viewerWidth = options.isRetina ? 792/2 : 792;
		viewerScale = options.isRetina ? 0.5 : 1;
	}

	//Private object vars
	var isiPhone = (options.device == "iphone");
	var positionLeft = isiPhone ? 75 : 35;
	var positionTop = isiPhone ? 247 : 164;
	var deviceMultiple = isiPhone ? 1.3 : 1.375;
	var deviceLeftMultiple = isiPhone ? 1.352 : 1.433;
	var deviceTopMultiple = isiPhone ? 1.27 : 1.33;

	//Set up viewer
	$('#viewer').css({
		"height": viewerHeight,
		"width": viewerWidth,
		"position": 'absolute',
		"left": ($(window).width() - viewerWidth)/2,
    "top": ($(window).height() - viewerHeight)/2,
	});

	//Set up viewer iframe
	$('#frame').css({
		'webkitTransform': 'scale(' + viewerScale + ', ' + viewerScale + ')',
		'webkitTransformOrigin': '0% 0%',
		'position': 'absolute',
		'left': positionLeft * viewerScale,
		'top': positionTop * viewerScale,
	});

	//Set up hand
	$('#hand').css({
		'height': ((1833 * deviceMultiple) * viewerScale) * 0.7793,
		'width': (1833 * deviceMultiple) * viewerScale,
		'position': 'absolute',
		'left': ($(window).width() - ((1833 * deviceLeftMultiple) * viewerScale))/2,
    'top': $(window).height() - (((1833 * deviceTopMultiple) * viewerScale) * 0.7793),
	});
}

function setBackground(background) {
	options.background = (background != undefined) ? background : options.background;
	if (options.background > backgrounds.length-1){
		options.background = 0;
	}
	if (options.background == 0) {
		$('html').css({
	  	"background": "none"
		});
	} else {
		$('html').css({
			  "background": "url('" + backgrounds[options.background] + "') no-repeat center center fixed",
			  "-webkit-background-size": "cover",
		  	"-moz-background-size": "cover",
		  	"-o-background-size": "cover",
		  	"background-size": "cover"
		});
	}
}

var setPhoneColor = function(phoneColor){
	options.phoneColor = (phoneColor != undefined) ? phoneColor : options.phoneColor;

	var phoneColors = {
		"white": "url('img/iphone_white.png')",
		"black": "url('img/iphone_black.png')"
	};

	if (options.device == "iphone"){
		$('#viewer').css({
			"background-image": phoneColors[options.phoneColor] || phoneColors["white"]
		});
	}

};

var setHand = function(hand){
	options.hand = (hand != undefined) ? hand : options.hand;
	$('#hand').css({
		"background-image": !options.hand ? "none" : "url('img/hand.png')"
	});
};

var setURL = function(url){
	options.url = (url != undefined) ? url : options.url;
	$('.prototypeinput').val(options.url);
	$("#frame").attr("src", options.url);
}

var setDevice = function(device){
	options.device = (device != undefined) ? device : options.device;

	if (options.device == "iphone"){
		$('#iphone').addClass("iphoneactive").removeClass("iphone");
		setPhoneColor();
		$('iframe').css({ "width": "640px", "height": "1136px" });
	}else{
		$('#iphone').addClass("iphone").removeClass("iphoneactive");
	}

	if (options.device == "android"){
		$('#android').addClass("androidactive").removeClass("android");
		$('#viewer').css({
			"background-image": "url('img/nexus.png')"
		});
		$('iframe').css({ "width": "720px", "height": "1280px" });
	}else{
		$('#android').addClass("android").removeClass("androidactive");
	}

	prototypeViewer();
}

// Keypress listeners.
$(window).keypress(function(e) {
	switch (e.which) {
		// Hitting the P key toggles between black and white iPhone
		case 112:
			setPhoneColor((options.phoneColor == "white") ? "black" : "white" );
			updateAddressBar();
			break;
		// Hitting the H key toggles the hand on and off
		case 104:
			setHand(!options.hand);
			updateAddressBar();
			break;
		// Hitting the B key cycles through various backgrounds
		case 98:
			setBackground(options.background + 1);
			updateAddressBar();
			break;
		// Hitting the Z key zooms the viewer to 100% scale
		case 122:
			options.zoom = !options.zoom;
			updateAddressBar();
			prototypeViewer();
			break;
	}
});

// Kick things off and update on resize
$(document).ready(prototypeViewer);
$(window).resize(prototypeViewer);

function search(ele) {
  if(event.keyCode == 13) {
		$("#frame").attr("src", ele.value);
		$('.prototypeinput').blur();
		updateAddressBar();
  }
}

// Needs to be called once on initialize
setDevice();

$("#iphone, #android").click(function(){
	if (options.device == "iphone"){
		setDevice("android");
	}else{
		setDevice("iphone");
	}
	updateAddressBar();
});

$("#controls").mouseenter(function(){
	$("#controls").animate({opacity:'1'}, 'fast');
});
$("#controls").mouseleave(function(){
  $("#controls").animate({opacity:'0.1'}, 'slow');
});

});
<|endoftext|>


<commit_before>var Directory = require('./directory')
  , Subset = require('./subset')

var TTFFont = module.exports = function(buffer) {
  var self = this
  this.buffer = buffer instanceof TTFFont
                ? buffer.buffer
                : buffer = buffer instanceof ArrayBuffer ? buffer : toArrayBuffer(buffer)

  if (buffer instanceof TTFFont) {
    this.directory = buffer.directory.clone()
  } else {
    this.directory = new Directory()
    this.directory.unpack(new DataView(buffer))
  }

  var scalerType = this.directory.scalerType.toString(16)
  if (scalerType !== '74727565' && scalerType !== '10000') {
    throw new Error('Not a TrueType font')
  }

  this.tables = {}
  function unpackTable(table, args) {
    var name = table.replace(/[^a-z0-9]/ig, '').toLowerCase()
      , entry = self.directory.entries[table]
    if (!entry) return
    if (buffer instanceof TTFFont) {
      self.tables[name] = self.tables[table] = buffer.tables[table].clone()
      return
    }
    var Table = require('./table/' + name)
      , view  = new DataView(buffer, entry.offset, entry.length)
    if (args) Table = Table.apply(undefined, args)
    self.tables[name] = self.tables[table] = (typeof Table === 'function' ? new Table : Table).unpack(view)
  }

  // workaround for browserify
  if (false) {
    require('./table/cmap')
    require('./table/head')
    require('./table/hhea')
    require('./table/maxp')
    require('./table/hmtx')
    require('./table/loca')
    require('./table/glyf')
    require('./table/name')
    require('./table/post')
    require('./table/os2')
  }

  unpackTable('cmap')
  for (var i = 0, len = this.tables.cmap.subtables.length; i < len; ++i) {
    var subtable = this.tables.cmap.subtables[i]
    if (subtable.isUnicode) {
      self.codeMap = subtable.table.codeMap
      break
    }
  }
  if (!this.codeMap) throw new Error('Font does not contain a Unicode Cmap.')

  unpackTable('head')
  unpackTable('hhea')
  unpackTable('maxp')
  unpackTable('hmtx', [this.tables.hhea.numOfLongHorMetrics, this.tables.maxp.numGlyphs])
  unpackTable('loca', [this.tables.head.indexToLocFormat, this.tables.maxp.numGlyphs])
  unpackTable('glyf', [this.tables.loca])
  unpackTable('name')
  unpackTable('post')
  // I don't want to bother with post's versions, therefore skip glyhp names
  // by setting version to 3.0, TODO: bother with it ...
  this.tables.post.version = 196608
  unpackTable('OS/2')

  this.baseFont = this.tables.name.records.filter(function(record) {
    return record.nameID === 6
  })[0].string
  this.fontName = 'MARKUS+' + this.baseFont

  this.scaleFactor = 1000.0 / this.tables.head.unitsPerEm

  this.italicAngle = parseFloat(this.tables.post.italicAngleHi + '.' + this.tables.post.italicAngleLow)
  var os2 = this.tables.os2 || {}
  this.ascent      = Math.round((os2.sTypoAscender  || this.tables.hhea.ascent) * this.scaleFactor)
  this.descent     = Math.round((os2.sTypoDescender || this.tables.hhea.descent) * this.scaleFactor)
  this.lineGap     = Math.round((os2.sTypoLineGap   || this.tables.hhea.lineGap) * this.scaleFactor)
  this.capHeight   = os2.sCapHeight || this.ascent
  this.stemV       = 0
  this.bbox        = [this.tables.head.xMin, this.tables.head.yMin, this.tables.head.xMax, this.tables.head.yMax].map(function(val) {
    return Math.round(val * self.scaleFactor)
  })

  var flags = 0, familyClass = (os2.sFamilyClass || 0) >> 8
    , isSerif = !!~[1, 2, 3, 4, 5, 6, 7].indexOf(familyClass)
  if (this.tables.post.isFixedPitch) flags |= 1 << 0
  if (isSerif)                       flags |= 1 << 1
  if (familyClass === 10)            flags |= 1 << 3
  if (this.italicAngle !== 0)        flags |= 1 << 6
  /* assume not being symbolic */    flags |= 1 << 5
  this.flags = flags

  this.widths = []
  for (var code in this.codeMap) {
    if (code < 32) continue
    var gid = this.codeMap[code]
    this.widths.push(Math.round(this.tables.hmtx.metrics[gid] * this.scaleFactor))
  }
}

TTFFont.prototype.stringWidth = function(string, size) {
  var width = 0, scale = size / 1000
  for (var i = 0, len = string.length; i < len; ++i) {
    var code = string.charCodeAt(i) - 32 // - 32 because of non AFM font
    width += this.widths[code] || 0
  }
  return width * scale
}

TTFFont.prototype.lineHeight = function(size, includeGap) {
  if (includeGap == null) includeGap = false
  var gap = includeGap ? this.lineGap : 0
  return (this.ascent + gap - this.descent) / 1000 * size
}

TTFFont.prototype.subset = function() {
  return new Subset(this)
}

TTFFont.TABLES = ['cmap', 'glyf', 'loca', 'hmtx', 'hhea', 'maxp', 'post', 'name', 'head', 'OS/2']

TTFFont.prototype.clone = function() {
  var clone = new TTFFont(this)
  clone.tables.glyf.view = this.tables.glyf.view
  return clone
}

TTFFont.prototype.save = function() {
  var self = this, tables = TTFFont.TABLES
  for (var name in this.directory.entries) {
    if (!!!~tables.indexOf(name)) delete this.directory.entries[name]
  }

  // calculate total size
  var size = offset = this.directory.lengthFor(this.directory, true) * this.directory.sizeFor(this.directory, true)

  tables.forEach(function(name) {
    if (!(name in self.directory.entries)) return
    var table = self.tables[name]
    var length = table ? table.lengthFor(table, true) * table.sizeFor(table, true)
                       : self.directory.entries[name].length
    size += length + length % 4
  })

  // prepare head
  this.tables.head.checkSumAdjustment = 0

  var view = new DataView(new ArrayBuffer(size))

  tables.forEach(function(name) {
    if (!(name in self.directory.entries)) return
    var table = self.tables[name], entry = self.directory.entries[name]
    if (!table) {
      var from = new DataView(self.buffer, entry.offset, entry.length)
      for (var i = 0; i < entry.length; ++i) view.setUint8(offset + i, from.getUint8(i))
      entry.offset = offset
    } else {
      table.pack(view, offset)
      entry.offset = offset
      entry.length = table.lengthFor(table, true) * table.sizeFor(table, true)
    }

    // pad up to a length completely divisible by 4
    var padding = entry.length % 4, length = entry.length + padding
    for (var i = entry.offset + entry.length, to = i + padding; i < to; ++i)
      view.setInt8(i, 0)

    // checksum
    var sum = 0
    for (var i = 0; i < length; i += 4)
      sum += view.getInt32(offset + i)
    entry.checkSum = sum

    // update offset for the next table
    offset += length
  })

  this.directory.pack(view, 0)

  // file checksum
  var sum = 0
  for (var i = 0; i < size; i += 4)
    sum += view.getInt32(i)
  this.tables.head.checkSumAdjustment = 0xB1B0AFBA - sum
  this.tables.head.pack(view, this.directory.entries.head.offset)

  return view.buffer
}

TTFFont.Subset = Subset

function toArrayBuffer(buffer) {
  var ab = new ArrayBuffer(buffer.length);
  var view = new Uint8Array(ab);
  for (var i = 0; i < buffer.length; ++i) {
      view[i] = buffer[i];
  }
  return ab;
}<commit_msg>fix width calculation<commit_after>var Directory = require('./directory')
  , Subset = require('./subset')

var TTFFont = module.exports = function(buffer) {
  var self = this
  this.buffer = buffer instanceof TTFFont
                ? buffer.buffer
                : buffer = buffer instanceof ArrayBuffer ? buffer : toArrayBuffer(buffer)

  if (buffer instanceof TTFFont) {
    this.directory = buffer.directory.clone()
  } else {
    this.directory = new Directory()
    this.directory.unpack(new DataView(buffer))
  }

  var scalerType = this.directory.scalerType.toString(16)
  if (scalerType !== '74727565' && scalerType !== '10000') {
    throw new Error('Not a TrueType font')
  }

  this.tables = {}
  function unpackTable(table, args) {
    var name = table.replace(/[^a-z0-9]/ig, '').toLowerCase()
      , entry = self.directory.entries[table]
    if (!entry) return
    if (buffer instanceof TTFFont) {
      self.tables[name] = self.tables[table] = buffer.tables[table].clone()
      return
    }
    var Table = require('./table/' + name)
      , view  = new DataView(buffer, entry.offset, entry.length)
    if (args) Table = Table.apply(undefined, args)
    self.tables[name] = self.tables[table] = (typeof Table === 'function' ? new Table : Table).unpack(view)
  }

  // workaround for browserify
  if (false) {
    require('./table/cmap')
    require('./table/head')
    require('./table/hhea')
    require('./table/maxp')
    require('./table/hmtx')
    require('./table/loca')
    require('./table/glyf')
    require('./table/name')
    require('./table/post')
    require('./table/os2')
  }

  unpackTable('cmap')
  for (var i = 0, len = this.tables.cmap.subtables.length; i < len; ++i) {
    var subtable = this.tables.cmap.subtables[i]
    if (subtable.isUnicode) {
      self.codeMap = subtable.table.codeMap
      break
    }
  }
  if (!this.codeMap) throw new Error('Font does not contain a Unicode Cmap.')

  unpackTable('head')
  unpackTable('hhea')
  unpackTable('maxp')
  unpackTable('hmtx', [this.tables.hhea.numOfLongHorMetrics, this.tables.maxp.numGlyphs])
  unpackTable('loca', [this.tables.head.indexToLocFormat, this.tables.maxp.numGlyphs])
  unpackTable('glyf', [this.tables.loca])
  unpackTable('name')
  unpackTable('post')
  // I don't want to bother with post's versions, therefore skip glyhp names
  // by setting version to 3.0, TODO: bother with it ...
  this.tables.post.version = 196608
  unpackTable('OS/2')

  this.baseFont = this.tables.name.records.filter(function(record) {
    return record.nameID === 6
  })[0].string
  this.fontName = 'MARKUS+' + this.baseFont

  this.scaleFactor = 1000.0 / this.tables.head.unitsPerEm

  this.italicAngle = parseFloat(this.tables.post.italicAngleHi + '.' + this.tables.post.italicAngleLow)
  var os2 = this.tables.os2 || {}
  this.ascent      = Math.round((os2.sTypoAscender  || this.tables.hhea.ascent) * this.scaleFactor)
  this.descent     = Math.round((os2.sTypoDescender || this.tables.hhea.descent) * this.scaleFactor)
  this.lineGap     = Math.round((os2.sTypoLineGap   || this.tables.hhea.lineGap) * this.scaleFactor)
  this.capHeight   = os2.sCapHeight || this.ascent
  this.stemV       = 0
  this.bbox        = [this.tables.head.xMin, this.tables.head.yMin, this.tables.head.xMax, this.tables.head.yMax].map(function(val) {
    return Math.round(val * self.scaleFactor)
  })

  var flags = 0, familyClass = (os2.sFamilyClass || 0) >> 8
    , isSerif = !!~[1, 2, 3, 4, 5, 6, 7].indexOf(familyClass)
  if (this.tables.post.isFixedPitch) flags |= 1 << 0
  if (isSerif)                       flags |= 1 << 1
  if (familyClass === 10)            flags |= 1 << 3
  if (this.italicAngle !== 0)        flags |= 1 << 6
  /* assume not being symbolic */    flags |= 1 << 5
  this.flags = flags

  this.widths = []
  for (var code in this.codeMap) {
    if (code < 32) continue
    var gid = this.codeMap[code]
    this.widths.push(Math.round(this.tables.hmtx.metrics[gid] * this.scaleFactor))
  }
  this.avgCharWidth = this.tables.os2 && (this.tables.os2.xAvgCharWidth * this.scaleFactor) || 0
}

TTFFont.prototype.stringWidth = function(string, size) {
  var width = 0, scale = size / 1000
  for (var i = 0, len = string.length; i < len; ++i) {
    var code = string.charCodeAt(i) - 32 // - 32 because of non AFM font
    width += this.widths[code] || this.avgCharWidth
  }
  return width * scale
}

TTFFont.prototype.lineHeight = function(size, includeGap) {
  if (includeGap == null) includeGap = false
  var gap = includeGap ? this.lineGap : 0
  return (this.ascent + gap - this.descent) / 1000 * size
}

TTFFont.prototype.subset = function() {
  return new Subset(this)
}

TTFFont.TABLES = ['cmap', 'glyf', 'loca', 'hmtx', 'hhea', 'maxp', 'post', 'name', 'head', 'OS/2']

TTFFont.prototype.clone = function() {
  var clone = new TTFFont(this)
  clone.tables.glyf.view = this.tables.glyf.view
  return clone
}

TTFFont.prototype.save = function() {
  var self = this, tables = TTFFont.TABLES
  for (var name in this.directory.entries) {
    if (!!!~tables.indexOf(name)) delete this.directory.entries[name]
  }

  // calculate total size
  var size = offset = this.directory.lengthFor(this.directory, true) * this.directory.sizeFor(this.directory, true)

  tables.forEach(function(name) {
    if (!(name in self.directory.entries)) return
    var table = self.tables[name]
    var length = table ? table.lengthFor(table, true) * table.sizeFor(table, true)
                       : self.directory.entries[name].length
    size += length + length % 4
  })

  // prepare head
  this.tables.head.checkSumAdjustment = 0

  var view = new DataView(new ArrayBuffer(size))

  tables.forEach(function(name) {
    if (!(name in self.directory.entries)) return
    var table = self.tables[name], entry = self.directory.entries[name]
    if (!table) {
      var from = new DataView(self.buffer, entry.offset, entry.length)
      for (var i = 0; i < entry.length; ++i) view.setUint8(offset + i, from.getUint8(i))
      entry.offset = offset
    } else {
      table.pack(view, offset)
      entry.offset = offset
      entry.length = table.lengthFor(table, true) * table.sizeFor(table, true)
    }

    // pad up to a length completely divisible by 4
    var padding = entry.length % 4, length = entry.length + padding
    for (var i = entry.offset + entry.length, to = i + padding; i < to; ++i)
      view.setInt8(i, 0)

    // checksum
    var sum = 0
    for (var i = 0; i < length; i += 4)
      sum += view.getInt32(offset + i)
    entry.checkSum = sum

    // update offset for the next table
    offset += length
  })

  this.directory.pack(view, 0)

  // file checksum
  var sum = 0
  for (var i = 0; i < size; i += 4)
    sum += view.getInt32(i)
  this.tables.head.checkSumAdjustment = 0xB1B0AFBA - sum
  this.tables.head.pack(view, this.directory.entries.head.offset)

  return view.buffer
}

TTFFont.Subset = Subset

function toArrayBuffer(buffer) {
  var ab = new ArrayBuffer(buffer.length);
  var view = new Uint8Array(ab);
  for (var i = 0; i < buffer.length; ++i) {
      view[i] = buffer[i];
  }
  return ab;
}<|endoftext|>


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

/*jslint evil:true*/
/*global app */
(function () {
  'use strict';

  // Supported CSS properties that accept shape values.
  // NOTE: unprefixed clip-path applies only to SVG; use -webkit- prefix for SVG & HTML.
  var CSS_PROPERTIES = ['shape-outside', 'shape-inside', '-webkit-clip-path'];

  // DOM equivalent of CSS properties used to query getComputedStyle() result.
  var DOM_PROPERTIES = CSS_PROPERTIES.map(window.toDOMProperty);

  // extension instance
  var ext;

  // messaging port to background page (background.js)
  var port = chrome.runtime.connect({name: "devtools"});

  function Extension(root) {
    var self = this;

    if (!root){
      throw new Error('Missing root window for View');
    }

    self.getSelectedElementStyles().then(function(data){
      self.view = new app.View(root);
      self.model = new app.Model(data);
      self.controller = new app.Controller(self.model, self.view);
      self.controller.on('editorStateChange', function(editor){
        self.onEditorStateChange.call(self, editor);
      });
      self.controller.setView();
    });

    // store a reference to the 'this'-bound event handler so we can
    // release it with removeListener() in Extension.teardown()
    // oh, JavaScript!
    self.boundSelectedElementChange = function(scope){
      return function(){
        scope.onSelectedElementChange.call(scope);
      };
    }(self);

    chrome.devtools.panels.elements.onSelectionChanged.addListener(self.boundSelectedElementChange);
  }

  Extension.prototype.teardown = function(){
    if (this.activeEditor){
      this.removeEditor(this.activeEditor);
    }

    this.view.teardown();
    this.view = null;
    this.model = null;
    this.controller.off('editorStateChange');
    this.controller = null;

    chrome.devtools.panels.elements.onSelectionChanged.removeListener(this.boundSelectedElementChange);
  };

  Extension.prototype.onSelectedElementChange = function(){
    var self = this;

    if (this.activeEditor){
      this.removeEditor(this.activeEditor);
    }

    self.getSelectedElementStyles().then(function(data){
      self.controller.setModel(new app.Model(data));
      self.controller.setView();
    });
  };

  Extension.prototype.onEditorStateChange = function(editor){
    if (editor.enabled){
      this.setupEditor(editor);
    } else {
      this.removeEditor(editor);
    }
  };

  Extension.prototype.setupEditor = function(editor){
    chrome.devtools.inspectedWindow.eval('setup($0, "'+ editor.property.toString() +'", "'+ editor.value.toString() +'")', { useContentScriptContext: true });
    this.activeEditor = editor;
  };

  Extension.prototype.removeEditor = function(editor){
    chrome.devtools.inspectedWindow.eval('remove("'+ editor.property.toString() +'")', { useContentScriptContext: true });
    this.activeEditor = null;
  };

  /*
    Returns a Promise that resolves with the CSS Shapes properties
    from the computed style of the currently selected element($0).

    @see CSS_PROPETIES
    @return {Promise}
  */
  Extension.prototype.getSelectedElementStyles = function(){
    return new Promise(function(resolve, reject){

      function extractStyles(style){
        var data = {};

        style = JSON.parse(style);

        CSS_PROPERTIES.forEach(function(prop, index){
          var domProp = DOM_PROPERTIES[index];

          if (!style[domProp]){
            return;
          }
          data[prop] = {
            property: prop,
            value: style[domProp]
          };
        });

        resolve(data);
      }

      chrome.devtools.inspectedWindow.eval("JSON.stringify(window.getComputedStyle($0, null))", extractStyles);
    });
  };

  function handleMessage(msg){
    if (!ext){
      console.warn('how did you get here? ext:', ext);
      return;
    }

    switch (msg.type){
      case "update":
        ext.model.update(msg.property, { value: msg.value });
      break;

      case "remove":
        ext.model.update(msg.property, { enabled: false });
      break;
    }
  }

  document.addEventListener('DOMContentLoaded', function(){
    chrome.devtools.panels.elements.createSidebarPane("Shapes",
      function(sidebar) {

        sidebar.setPage('sidebar.html');
        sidebar.setHeight('100vh');

        sidebar.onShown.addListener(function(contentWindow){
          ext = new Extension(contentWindow);
          port.onMessage.addListener(handleMessage);
        });

        sidebar.onHidden.addListener(function(){
          ext.teardown();
          ext = undefined;
          port.onMessage.removeListener(handleMessage);
        });
    });
  });

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

/*jslint evil:true*/
/*global app */
(function () {
  'use strict';

  // Supported CSS properties that accept shape values.
  // NOTE: unprefixed clip-path applies only to SVG; use -webkit- prefix for SVG & HTML.
  var CSS_PROPERTIES = ['shape-outside', 'shape-inside', '-webkit-clip-path'];

  // DOM equivalent of CSS properties used to query getComputedStyle() result.
  var DOM_PROPERTIES = CSS_PROPERTIES.map(window.toDOMProperty);

  // extension instance
  var ext;

  // messaging port to background page (background.js)
  var port = chrome.runtime.connect({name: "devtools"});

  function Extension(root) {
    var self = this;

    if (!root){
      throw new Error('Missing root window for View');
    }

    self.getSelectedElementStyles().then(function(data){
      self.view = new app.View(root);
      self.model = new app.Model(data);
      self.controller = new app.Controller(self.model, self.view);
      self.controller.on('editorStateChange', function(editor){
        self.onEditorStateChange.call(self, editor);
      });
      self.controller.setView();
    });

    // store a reference to the 'this'-bound event handler so we can
    // release it with removeListener() in Extension.teardown()
    // oh, JavaScript!
    self.boundSelectedElementChange = function(scope){
      return function(){
        scope.onSelectedElementChange.call(scope);
      };
    }(self);

    chrome.devtools.panels.elements.onSelectionChanged.addListener(self.boundSelectedElementChange);
  }

  Extension.prototype.teardown = function(){
    if (this.activeEditor){
      this.removeEditor(this.activeEditor);
    }

    this.view.teardown();
    this.view = null;
    this.model = null;
    this.controller.off('editorStateChange');
    this.controller = null;

    chrome.devtools.panels.elements.onSelectionChanged.removeListener(this.boundSelectedElementChange);
  };

  Extension.prototype.onSelectedElementChange = function(){
    var self = this;

    if (this.activeEditor){
      this.removeEditor(this.activeEditor);
    }

    self.getSelectedElementStyles().then(function(data){
      self.controller.setModel(new app.Model(data));
      self.controller.setView();
    });
  };

  Extension.prototype.onEditorStateChange = function(editor){
    if (editor.enabled){
      this.setupEditor(editor);
    } else {
      this.removeEditor(editor);
    }
  };

  Extension.prototype.setupEditor = function(editor){
    chrome.devtools.inspectedWindow.eval('setup($0, "'+ editor.property.toString() +'", "'+ editor.value.toString() +'")', { useContentScriptContext: true });
    this.activeEditor = editor;
  };

  Extension.prototype.removeEditor = function(editor){
    chrome.devtools.inspectedWindow.eval('remove("'+ editor.property.toString() +'")', { useContentScriptContext: true });
    this.activeEditor = null;
  };

  /*
    Returns a Promise that resolves with the CSS Shapes properties
    from the computed style of the currently selected element($0).

    @see CSS_PROPETIES
    @return {Promise}
  */
  Extension.prototype.getSelectedElementStyles = function(){
    return new Promise(function(resolve, reject){

      function extractStyles(style){
        var data = {};

        style = JSON.parse(style);

        CSS_PROPERTIES.forEach(function(prop, index){
          var domProp = DOM_PROPERTIES[index];

          if (!style[domProp]){
            return;
          }
          data[prop] = {
            property: prop,
            value: style[domProp]
          };
        });

        resolve(data);
      }

      chrome.devtools.inspectedWindow.eval("JSON.stringify(window.getComputedStyle($0, null))", extractStyles);
    });
  };

  function handleMessage(msg){
    if (!ext){
      console.warn('how did you get here? ext:', ext);
      return;
    }

    switch (msg.type){
      case "update":
        ext.model.update(msg.property, { value: msg.value });
      break;

      case "remove":
        ext.model.update(msg.property, { enabled: false });
      break;
    }
  }

  document.addEventListener('DOMContentLoaded', function(){
    chrome.devtools.panels.elements.createSidebarPane("Shapes",
      function(sidebar) {

        sidebar.setPage('sidebar.html');

        sidebar.onShown.addListener(function(contentWindow){
          ext = new Extension(contentWindow);
          port.onMessage.addListener(handleMessage);
        });

        sidebar.onHidden.addListener(function(){
          ext.teardown();
          ext = undefined;
          port.onMessage.removeListener(handleMessage);
        });
    });
  });

})();
<|endoftext|>


<commit_before>/**
 * @since 150316 11:09
 * @author vivaxy
 */

/**
 * usage:
 *
 * // parse some link
 * var url = new Url(link);
 *
 * // parse current location link
 * var url = new Url();
 *
 * methods:
 *
 * // get query string by name
 * url.queryString(key);
 *
 * // set query string by name, and update url properties
 * url.queryString(key, value);
 *
 * properties:
 *
 * // href: fill link, like `https://www.test.com:8080/vivaxy/test/url?name=vivaxy&year=2014&month=6#some`
 * url.href
 *
 * // protocol: like `https:`
 * url.protocol
 *
 * // host: hostname + ':' + port, like `www.test.com:8080`
 * url.host
 *
 * // hostname: like `www.test.com`
 * url.hostname
 *
 * // port: like `8080`
 * url.port
 *
 * // pathname: full path from some host, like `/vivaxy/test/url`
 * url.pathname
 *
 * // search: queryString, like `?name=vivaxy&year=2014&month=6`
 * url.search
 *
 * // path: pathname + search, like `/vivaxy/test/url?name=vivaxy&year=2014&month=6`
 * url.path
 *
 * // query: search without `?`, like `name=vivaxy&year=2014&month=6`
 * url.query
 *
 * // hash: like `#some`
 * url.hash
 *
 */
(function (global) {

    /**
     *
     * @param href
     * @constructor
     */
    var Url = function (href) {

        this.href = href || location.href;
        this._queryObject = {};
        this._parse();
        this._parseQuery();
        this._formatQuery();

    }, p = Url.prototype;

    /**
     * parse url string to url object, and save to Url
     * @private
     */
    p._parse = function () {

        var a = document.createElement('a');
        a.href = this.href;

        this.protocol = a.protocol;
        this.host = a.host;
        this.hostname = a.hostname;
        this.port = a.port;
        this.pathname = a.pathname;
        this.search = a.search;
        this.path = this.pathname + this.search;
        this.query = this.search.slice(1);
        this.hash = a.hash;

    };

    /**
     * parse query string to query object, and save to _queryObject
     * @private
     */
    p._parseQuery = function () {

        var qs = this.query.split('&');
        qs = qs.filter(function (item) {
            return item !== '' && item.indexOf('=') > -1;
        });

        var l = qs.length;
        for (var i = 0; i < l; i++) {
            var split = qs[i].split('=');
            this._queryObject[split[0]] = split[1];
        }

    };

    /**
     * format query object to query string, and update the url object
     * @private
     */
    p._formatQuery = function () {
        var query = '', obj = this._queryObject;
        for (var i in obj) {
            if (obj.hasOwnProperty(i)) {
                query += i + '=' + obj[i] + '&';
            }
        }
        query = query.slice(0, -1);
        this.query = query;
        if (query !== '') {
            this.search = '?' + query;
        }
        this.path = this.pathname + this.search;
        this.href = this.protocol + '//' + this.host + this.path + this.hash;
    };

    /**
     * get or set some query object
     * @param key
     * @param value
     * @returns {*}
     */
    p.queryString = function (key, value) {
        if (value === undefined) {
            // get
            return this._queryObject[key];
        } else {
            // set
            this._queryObject[key] = value;
            this._formatQuery();
        }
    };

    global.Url = global.Url || Url;

})(window);
<commit_msg>global<commit_after>/**
 * @since 150316 11:09
 * @author vivaxy
 */

/**
 * usage:
 *
 * // parse some link
 * var url = new Url(link);
 *
 * // parse current location link
 * var url = new Url();
 *
 * methods:
 *
 * // get query string by name
 * url.queryString(key);
 *
 * // set query string by name, and update url properties
 * url.queryString(key, value);
 *
 * properties:
 *
 * // href: fill link, like `https://www.test.com:8080/vivaxy/test/url?name=vivaxy&year=2014&month=6#some`
 * url.href
 *
 * // protocol: like `https:`
 * url.protocol
 *
 * // host: hostname + ':' + port, like `www.test.com:8080`
 * url.host
 *
 * // hostname: like `www.test.com`
 * url.hostname
 *
 * // port: like `8080`
 * url.port
 *
 * // pathname: full path from some host, like `/vivaxy/test/url`
 * url.pathname
 *
 * // search: queryString, like `?name=vivaxy&year=2014&month=6`
 * url.search
 *
 * // path: pathname + search, like `/vivaxy/test/url?name=vivaxy&year=2014&month=6`
 * url.path
 *
 * // query: search without `?`, like `name=vivaxy&year=2014&month=6`
 * url.query
 *
 * // hash: like `#some`
 * url.hash
 *
 */
(function (global) {

    /**
     *
     * @param href
     * @constructor
     */
    var Url = function (href) {

        this.href = href || global.location.href;
        this._queryObject = {};
        this._parse();
        this._parseQuery();
        this._formatQuery();

    }, p = Url.prototype;

    /**
     * parse url string to url object, and save to Url
     * @private
     */
    p._parse = function () {

        var a = global.document.createElement('a');
        a.href = this.href;

        this.protocol = a.protocol;
        this.host = a.host;
        this.hostname = a.hostname;
        this.port = a.port;
        this.pathname = a.pathname;
        this.search = a.search;
        this.path = this.pathname + this.search;
        this.query = this.search.slice(1);
        this.hash = a.hash;

    };

    /**
     * parse query string to query object, and save to _queryObject
     * @private
     */
    p._parseQuery = function () {

        var qs = this.query.split('&');
        qs = qs.filter(function (item) {
            return item !== '' && item.indexOf('=') > -1;
        });

        var l = qs.length;
        for (var i = 0; i < l; i++) {
            var split = qs[i].split('=');
            this._queryObject[split[0]] = split[1];
        }

    };

    /**
     * format query object to query string, and update the url object
     * @private
     */
    p._formatQuery = function () {
        var query = '', obj = this._queryObject;
        for (var i in obj) {
            if (obj.hasOwnProperty(i)) {
                query += i + '=' + obj[i] + '&';
            }
        }
        query = query.slice(0, -1);
        this.query = query;
        if (query !== '') {
            this.search = '?' + query;
        }
        this.path = this.pathname + this.search;
        this.href = this.protocol + '//' + this.host + this.path + this.hash;
    };

    /**
     * get or set some query object
     * @param key
     * @param value
     * @returns {*}
     */
    p.queryString = function (key, value) {
        if (value === undefined) {
            // get
            return this._queryObject[key];
        } else {
            // set
            this._queryObject[key] = value;
            this._formatQuery();
        }
    };

    global.Url = global.Url || Url;

})(window);
<|endoftext|>


<commit_before>'use strict';

function repo_init(){
    core_repo_init({
      'title': 'Clock.htm',
    });

    second();

    // Setup hands.
    let hands = [
      'hours-hand',
      'minutes-hand',
      'seconds-hand',
    ];
    for(let hand in hands){
        let hand_element = document.getElementById(hands[hand]);
        hand_element.style.background = '#' + core_random_hex();
        hand_element.style.height = '10px';
        hand_element.style.left = '50%';
        hand_element.style.position = 'fixed';
        hand_element.style.top = '50%';
        hand_element.style.transformOrigin = 'left';
        hand_element.style.width = (hand * 100 + 100) + 'px';
    }

    core_interval_modify({
      'id': 'clock',
      'interval': 1000,
      'todo': second,
    });
}
<commit_msg>added interval sync usage<commit_after>'use strict';

function repo_init(){
    core_repo_init({
      'title': 'Clock.htm',
    });

    second();

    // Setup hands.
    let hands = [
      'hours-hand',
      'minutes-hand',
      'seconds-hand',
    ];
    for(let hand in hands){
        let hand_element = document.getElementById(hands[hand]);
        hand_element.style.background = '#' + core_random_hex();
        hand_element.style.height = '10px';
        hand_element.style.left = '50%';
        hand_element.style.position = 'fixed';
        hand_element.style.top = '50%';
        hand_element.style.transformOrigin = 'left';
        hand_element.style.width = (hand * 100 + 100) + 'px';
    }

    core_interval_modify({
      'id': 'clock',
      'interval': 1000,
      'sync': true,
      'todo': second,
    });
}
<|endoftext|>


<commit_before>'use strict'

/**
 * Module dependencies
 */
const config = require('./config')

module.exports = function (version) {
  config.set('current', version)
  console.log(`You're using v${version} now!`.green)
}
<commit_msg>check before use a new version<commit_after>'use strict'

/**
 * Module dependencies
 */
const path = require('path')
const home = require('user-home')
const exists = require('path-exists')
const config = require('./config')

module.exports = function (version) {
  config.set('current', version)
  const cached = path.join(home, '.nwjs', version)
  if (!exists.sync(cached)) {
    return console.log(`Run ${`nw install ${version}`.red} first`)
  }
  console.log(`You're using v${version} now!`.green)
}
<|endoftext|>


<commit_before>var canvas = document.getElementById('screen');
var ctx = canvas.getContext('2d');

var blueprints = {
    house: House().materials
}

var entities = {
    organisms: [],
    resources: [],
    structures: []
};

var townHall = new TownHall();

entities.structures.push(townHall);

for (var i = 0; i < 10; i++) {
    entities.organisms.push(new Organism());
    entities.resources.push(new Tree());
    entities.resources.push(new Rock());
}

console.log(entities)

var game = setInterval(onTick, 33);

function onTick() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (i in entities.organisms) {
        entities.organisms[i].step();
    }

    for (i in entities) {
        for (j in entities[i]) {
            entities[i][j].render();
        }
    }
}

function guid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}<commit_msg>Regrow trees over time.<commit_after>var canvas = document.getElementById('screen');
var ctx = canvas.getContext('2d');

var blueprints = {
    house: House().materials
}

var entities = {
    organisms: [],
    resources: [],
    structures: []
};

var townHall = new TownHall();

entities.structures.push(townHall);

for (var i = 0; i < 10; i++) {
    entities.organisms.push(new Organism());
    entities.resources.push(new Tree());
    entities.resources.push(new Rock());
}

console.log(entities)

var game = setInterval(onTick, 33);

function onTick() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (i in entities.organisms) {
        entities.organisms[i].step();
    }

    for (i in entities) {
        for (j in entities[i]) {
            entities[i][j].render();
        }
    }

    if (Math.random() < 0.02) {
        entities.resources.push(new Tree());
    }
}

function guid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}<|endoftext|>


<commit_before>(function () {
    'use strict';

    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function getRandomArbitrary(min, max) {
        var newVar = Math.random() * (max - min) + min;
        if (newVar == 0) {
            newVar = min;
        }
        return  newVar;
    }

    $(document).ready(function () {
        var ctx = $("canvas").get(0).getContext('2d');
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;

        var stage = new Stage(ctx);
        var generatorInterval = null;
        var updateInterval = null;

        function stopStage() {
            stage.stop();
        }

        function startStage() {
            stage.begin();//开始渲染
        }

        function restart() {
            stopStage();
            if (generatorInterval) {
                clearInterval(generatorInterval);
            }
            if(updateInterval){
                clearInterval(updateInterval);
            }
            startStage();

        }

        $("#waitingBtn").on("click", function () {
            console.log("start waiting...");
            restart();
            updateInterval = setInterval(function () {
                for (var i in stage.sprites) {
                    if (stage.sprites[i]) {
                        stage.sprites[i].move()
                    }
                }
            }, 50);

            function createCircle() {
                var x = getRandomInt(0, w);
                var y = getRandomInt(h/2, h);
                var radius = getRandomInt(2, 20);
                var a = radius / 20.0;
                var circle = new Circle(ctx, x, y, radius, {strokeStyle: "rgba(255,255,255," + a + ")"});
                var speedX = 0; // 水平方向速度不变
                var speedY = -1 * a;
                circle.speed = {x: speedX, y: speedY};
                var count = getRandomInt(20, 30)
                if (stage.sprites.length < count) {
                    stage.addSprite(circle);
                } else {
                    stage.deleteSprite();
                }
            }

            generatorInterval = setInterval(createCircle, 100);
        });

        $("#monitorBtn").on("click", function () {
            console.log("start mornitoring...");
            restart();

            function createRectangle() {
                var d = 20;
                var left = (w - d) / 2;
                var top = (h - d) / 2;

                var rect = new Rectangle(ctx, left, top, d, d);
                rect.speed = {x: 0, y: 0};
                stage.addSprite(rect);
            }

            for (var i = 0; i < 15; i++) {
                createRectangle();
            }

            function lineSmallRectangles() {
                var sprites = stage.sprites;
                var len = sprites.length;
                var d = 10;
                var span = 15;
                var left = (w - (span * len)) / 2;
                var top = (h - d) / 2;

                for(var i=0; i<len; i++){
                    var spr = sprites[i];
                    spr.moveTo(left+(i*span), top);
                    spr.setWidth(d);
                    spr.setHeight(d/2);
                }

                updateInterval = setInterval(function () {
                    for (var i in stage.sprites) {
                        var spr = stage.sprites[i];
                        if (spr) {
                            var oldH = spr.h;
                            var h = getRandomInt(0, 30);
                            spr.setHeight(h);
                            var dh = h - oldH;
                            spr.y = top - (dh/2);
                        }
                    }
                }, 100);//这里是50帧每秒

            }

            setTimeout(lineSmallRectangles, 1000);
        });

        $("#thinkBtn").on("click", function () {
            console.log("start thinking...");
        });
    });

}());
<commit_msg>speed up updating<commit_after>(function () {
    'use strict';

    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function getRandomArbitrary(min, max) {
        var newVar = Math.random() * (max - min) + min;
        if (newVar == 0) {
            newVar = min;
        }
        return  newVar;
    }

    $(document).ready(function () {
        var ctx = $("canvas").get(0).getContext('2d');
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;

        var stage = new Stage(ctx);
        var generatorInterval = null;
        var updateInterval = null;

        function stopStage() {
            stage.stop();
        }

        function startStage() {
            stage.begin();//开始渲染
        }

        function restart() {
            stopStage();
            if (generatorInterval) {
                clearInterval(generatorInterval);
            }
            if(updateInterval){
                clearInterval(updateInterval);
            }
            startStage();

        }

        $("#waitingBtn").on("click", function () {
            console.log("start waiting...");
            restart();
            updateInterval = setInterval(function () {
                for (var i in stage.sprites) {
                    if (stage.sprites[i]) {
                        stage.sprites[i].move()
                    }
                }
            }, 20);

            function createCircle() {
                var x = getRandomInt(0, w);
                var y = getRandomInt(h/2, h);
                var radius = getRandomInt(2, 20);
                var a = radius / 20.0;
                var circle = new Circle(ctx, x, y, radius, {strokeStyle: "rgba(255,255,255," + a + ")"});
                var speedX = 0; // 水平方向速度不变
                var speedY = -1 * a;
                circle.speed = {x: speedX, y: speedY};
                var count = getRandomInt(20, 30)
                if (stage.sprites.length < count) {
                    stage.addSprite(circle);
                } else {
                    stage.deleteSprite();
                }
            }

            generatorInterval = setInterval(createCircle, 50);
        });

        $("#monitorBtn").on("click", function () {
            console.log("start mornitoring...");
            restart();

            function createRectangle() {
                var d = 20;
                var left = (w - d) / 2;
                var top = (h - d) / 2;

                var rect = new Rectangle(ctx, left, top, d, d);
                rect.speed = {x: 0, y: 0};
                stage.addSprite(rect);
            }

            for (var i = 0; i < 15; i++) {
                createRectangle();
            }

            function lineSmallRectangles() {
                var sprites = stage.sprites;
                var len = sprites.length;
                var d = 10;
                var span = 15;
                var left = (w - (span * len)) / 2;
                var top = (h - d) / 2;

                for(var i=0; i<len; i++){
                    var spr = sprites[i];
                    spr.moveTo(left+(i*span), top);
                    spr.setWidth(d);
                    spr.setHeight(d/2);
                }

                updateInterval = setInterval(function () {
                    for (var i in stage.sprites) {
                        var spr = stage.sprites[i];
                        if (spr) {
                            var oldH = spr.h;
                            var h = getRandomInt(0, 30);
                            spr.setHeight(h);
                            var dh = h - oldH;
                            spr.y = top - (dh/2);
                        }
                    }
                }, 20);//这里是50帧每秒

            }

            setTimeout(lineSmallRectangles, 1000);
        });

        $("#thinkBtn").on("click", function () {
            console.log("start thinking...");
        });
    });

}());
<|endoftext|>