<commit_before>#!/usr/bin/env node

// 1) validate a zip file argument was supplied
// 2) unzip the zip file using node_appc
// 3) copy the "mobileweb" directory to "tizen"
// 4) remove tizen/templates/app/default/resources/mobileweb directory
// 4) copy tizen files (cli, templates, titanium) on top of "tizen" directory
// 5) copy titanium-sdk/lib/tiappxml.js on top of node_modules/titanium-sdk/lib
// 6) read manifest.json, parse json, add "tizen" to platforms, stringify json, write manifest
// 7) run dependencies.json builder using titanium_mobile/support/mobileweb/dependencyAnalyzer
// 8) re-zip distribution file with "VERSION-tizen.zip"

//input parameters:
// path to zip
// output file name
// working directory unzip original sdk

console.log("cli args: " + process.argv);

var fs = require('fs'),
	path = require('path'),
	async = require('async'),
	appc = require('node-appc'),
	xmldom = require('xmldom'),
	wrench = require('wrench'),
	tmpFileUtil = require ("file-utils").File,
	scriptArgs = process.argv.slice(2),
	workingDir = void 0,//scriptArgs[1],
	titaniumTizenDir = __dirname,
	sdkRoot,
	resultPath,
	buildLinuxSdk = false;

console.log('[DEBUG] scriptArgs(zip, working directory): ' + scriptArgs);

async.series([
	function(next){
		//Validation
		if(validateArgs(scriptArgs)){
			var archiveName = path.basename(scriptArgs[0]);
			//build name for output zip with SDK
			archiveName = archiveName.replace('.zip', '-tizen.zip');
			resultPath = path.join(path.dirname(scriptArgs[0]), archiveName);
			if(resultPath.indexOf('linux') != -1){
				//initialize everything for linux sdk
				buildLinuxSdk = true;
			}
			console.log('[DEBUG] created output file name: ' + resultPath);
			if(process.platform === 'win32'){
				//create temporary dir to unzip and modify sdk content. The dir is removed when the process finishes
				var settings = {
						directory: scriptArgs[1]
				};
				tmpFileUtil.createTempFolder (settings, function (error, folder){
					if(folder == null){
						next("Cannot create temporary directory", 'failed');
					}
					console.log ('[DEBUG] created temporary directory:' + folder.toString());
					workingDir = folder.toString();
					next(null, 'ok');
				});
			}else{
				workingDir = scriptArgs[1];
				next(null, 'ok');
			}
		}
	}
	, function(next){
		console.log('[DEBUG] Start unzip');
		//Unzip callback
		var resultCb = function(errorMsg){
			if(errorMsg){
				console.log('[DEBUG] unzip finished with error: ' + errorMsg);
				next(null, 'ok');
			}else{
				next(null, 'ok');
			}
		};
		if(process.platform === 'win32'){
			unzip7za(scriptArgs[0], workingDir, resultCb);
		}else{
			appc.zip.unzip(scriptArgs[0], workingDir, resultCb);
		}
	}
	, function(next){
		console.log('[DEBUG] Create tizen platform, initially copy it from mobileweb');
 		copymobilWebToTizen(function(){
 			console.log('[DEBUG] copymobilWebToTizen calling next()');
 			next(null, 'ok');
 		});
	}
	, function(next){
		console.log('[DEBUG] fixing manifest.json');
		fixManifest();
		next(null, 'ok');
	}, function(next){
		executeDependenciesAnalyzer(function(){
			next(null, 'ok');
		});
	}, function(next){
		if(process.platform === 'win32'){
			console.log('Start packaging on win32');
			packagingSDK7z(function(){
				next(null, 'ok');
			});
		} else {
			packagingSDKLinux(function(){
				next(null, 'Packaging on linux ok');
			});
		}
	}
	], function(err){
		if(err)
			console.log(err)
		console.log('Finished.')

});

//validating input parameters
function validateArgs(params){
	var workOk = true;
	if(!fs.existsSync(params[0])){
		console.log('Error: param 1 should point existng zip archive. Current value: ' + params[0]);
		workOk = false;
	}
	var stats = fs.statSync(params[1]);
	if(!stats.isDirectory() ){
		console.log('Error: param 3 should point existing directory. Current value: ' + params[1]);
		workOk = false;
	}
	return workOk;
}

function copymobilWebToTizen(finish){
	var basePath;
	if(buildLinuxSdk){
		basePath = path.join(workingDir, 'mobilesdk', 'linux');
	}else{
		basePath = path.join(workingDir, 'mobilesdk', 'win32');
	}
	console.log('[DEBUG] Looking for sdk in  folder:' + basePath);
	appc.fs.visitDirs(basePath,
		function(name, dpath){
			sdkRoot = dpath;
			console.log('[DEBUG] Full path to SDK folder:' + sdkRoot);
		},
		function(){
			//visitDirs finished, sdk root detected, create initiali version of tizen directory that really is copy of mobileweb
			console.log('[DEBUG] wrench.copyDirSyncRecursive from ' + path.join(sdkRoot, 'mobileweb') + " to "+ path.join(sdkRoot, 'tizen'));
			wrench.copyDirSyncRecursive(path.join(sdkRoot, 'mobileweb'), path.join(sdkRoot, 'tizen'));

			console.log('[DEBUG] copyDirSyncRecursiveEx from ' +path.join(titaniumTizenDir, 'titanium', 'Ti') + " to "+ path.join(sdkRoot, 'tizen', 'titanium', 'Ti'));
			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'titanium', 'Ti'), path.join(sdkRoot, 'tizen', 'titanium', 'Ti'));

			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'cli', 'commands'), path.join(sdkRoot, 'tizen', 'cli', 'commands'));

			copyFileSync(path.join(titaniumTizenDir, 'titanium', 'Ti.js'), path.join(sdkRoot, 'tizen', 'titanium', 'Ti.js'));

			//remove tizen/templates/app/default/resources/mobileweb directory
			//console.log('[DEBUG]rmdirSyncRecursive from ' + path.join(sdkRoot, 'tizen', 'templates', 'app', 'default', 'Resources', 'mobileweb'));
			//wrench.rmdirSyncRecursive(path.join(sdkRoot, 'tizen', 'templates', 'app', 'default', 'Resources', 'mobileweb'), false);

			//config.tmpl template for
			copyFileSync(path.join(titaniumTizenDir, 'templates', 'app', 'config.tmpl'), path.join(sdkRoot, 'tizen', 'templates', 'app', 'config.tmpl'));

			wrench.copyDirSyncRecursive(path.join(titaniumTizenDir,'templates', 'app', 'default', 'Resources', 'tizen'), path.join(sdkRoot, 'tizen', 'templates', 'app', 'default', 'Resources', 'tizen'));

			copyFileSync(path.join(titaniumTizenDir, 'src', 'loader.js'), path.join(sdkRoot, 'tizen', 'src', 'loader.js'));

			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'dependencyAnalyzer'), path.join(sdkRoot, 'tizen', 'dependencyAnalyzer'));

			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'themes'), path.join(sdkRoot, 'tizen', 'themes'));

			//signer app for tizen
			fs.mkdirSync(path.join(sdkRoot, 'tizen', 'utils'));
			copyFileSync(path.join(titaniumTizenDir, 'utils', 'signapp.jar'), path.join(sdkRoot, 'tizen', 'utils', 'signapp.jar'));

			finish();
		}
	);
}

function applyPatches(){
	//make temp dir

	//generate patche

	//apply patch

}

function fixManifest(){
	var manifestPath = path.join(sdkRoot, "manifest.json");
	var manifestStr = fs.readFileSync(manifestPath, 'utf8').toString();
	var manifestObject = JSON.parse(manifestStr);
	manifestObject.platforms.push("tizen");
	fs.writeFileSync(manifestPath, JSON.stringify(manifestObject), 'utf8');
}

function executeDependenciesAnalyzer(finished){
	console.log('[DEBUG] executeDependenciesAnalyzer ');
	var runner = require('child_process');
	var scriptpath = path.join(sdkRoot, 'tizen', 'dependencyAnalyzer', 'dependencyAnalyzer.js');
	var analyzerCmd = 'node "' + scriptpath + '"';

	console.log('starting dependency analyzer: ' + analyzerCmd);
	options = { cwd: path.join(sdkRoot, 'tizen', 'dependencyAnalyzer') };
	runner.exec(
		analyzerCmd,
		function (err, stdout, stderr) {
			console.log(stdout);
			if(err != null){
				console.log('[Error] executeDependenciesAnalyzer failed');
				console.log(stderr);
			}else{
				console.log('executeDependenciesAnalyzer ok');
			}
			finished();
		});
}

function copyFileSync(srcFile, destFile) {
	console.log('[DEBUG] copyFileSync from ' + srcFile + " to "+ destFile);
	var bytesRead, fdr, fdw, pos;
	var BUF_LENGTH = 64 * 1024;
	var _buff = new Buffer(BUF_LENGTH);
	fdr = fs.openSync(srcFile, 'r');
	fdw = fs.openSync(destFile, 'w');
	bytesRead = 1;
	pos = 0;
	while (bytesRead > 0) {
		bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos);
		fs.writeSync(fdw, _buff, 0, bytesRead);
		pos += bytesRead;
	}
	fs.closeSync(fdr);
	return fs.closeSync(fdw);
}

function copyDirSyncRecursiveEx(sourceDir, newDirLocation) {
	console.log('[DEBUG] copyDirSyncRecursiveEx src ' + sourceDir + " destination "+ newDirLocation);
    /*  Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
    var checkDir = fs.statSync(sourceDir);
    try {
    	if(!fs.existsSync(newDirLocation)){
        	fs.mkdirSync(newDirLocation, checkDir.mode);
    	}
    } catch (e) {
        //if the directory already exists, that's okay
        if (e.code !== 'EEXIST') throw e;
    }

    var files = fs.readdirSync(sourceDir);
	console.log('[DEBUG] copyDirSyncRecursiveEx created filelist for ' + sourceDir + " it contains "+ files.length);
    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
        if(currFile.isDirectory()) {
            /*  recursion this thing right on back. */
            copyDirSyncRecursiveEx(sourceDir + "/" + files[i], newDirLocation + "/" + files[i]);
        } else if(currFile.isSymbolicLink()) {
        	console.log('[WARRNING] copyDirSyncRecursiveEx symlink instead of file: ' + sourceDir + "/" + files[i]);
            var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]);
            fs.symlinkSync(symlinkFull, newDirLocation + "/" + files[i]);
        } else {
            /*  At this point, we've hit a file actually worth copying... so copy it on over. */
            copyFileSync(sourceDir + "/" + files[i], newDirLocation + "/" + files[i])
        }
    }
}

function find7za(){
	var zippath = path.normalize(path.join(path.dirname(require.resolve('node-appc')), '..','tools','7zip','7za.exe'));
	console.log('7za.exe detected. Path is ' + path.normalize(zippath));

	if(fs.existsSync(zippath)){
		return zippath;
	}else{
		console.log('Not found 7za.exe path is wrong ' + path.normalize(zippath));
	}
}

function packagingSDK7z(finish){
	console.log('Packaging application into zip');
	var packer = require('child_process');
	// Create the tasks to unzip each entry in the zip file
	var child,
	stdout = '',
	stderr = '';

	child = packer.spawn(path.resolve(find7za().toString()), ['a', resultPath, workingDir + '/*', '-tzip']);
	child.stdout.on('data', function (data) {
		stdout += data.toString();
	});
	child.on('exit', function (code, signal) {
		if (finish) {
			if (code) {
				// if we're on windows, the error message is actually in stdout, so scan for it
				if (process.platform === 'win32') {
					var foundError = false,
						err = [];

					stdout.split('\n').forEach(function (line) {
						if (/^Error\:/.test(line)) {
							foundError = true;
						}
						if (foundError) {
							line && err.push(line.trim());
						}
					});
					if (err.length) {
						stderr = err.join('\n') + stderr;
					}
				}
				finish();
			} else {
				finish();
			}
		}
	});
}

function unzip7za(src, dest, callback){
	var packer = require('child_process');
	// Create the tasks to unzip each entry in the zip file
	var child,
	stdout = '',
	stderr = '';

	child = packer.spawn(path.resolve(find7za().toString()), ['x', src, '-o' + dest, '-y', '-bd']);
	child.stdout.on('data', function (data) {
		stdout += data.toString();
	});
	child.on('exit', function (code, signal) {
		if (callback) {
			if (code) {
				// if we're on windows, the error message is actually in stdout, so scan for it
				if (process.platform === 'win32') {
					var foundError = false,
						err = [];

					stdout.split('\n').forEach(function (line) {
						if (/^Error\:/.test(line)) {
							foundError = true;
						}
						if (foundError) {
							line && err.push(line.trim());
						}
					});

					if (err.length) {
						stderr = err.join('\n') + stderr;
					}
				}
				callback(null);
			} else {
				callback(null);
			}
		}
	});
}

function packagingSDKLinux(finish){
	var packer = require('child_process');
	var cmdzip = 'zip -r "' + resultPath + '" *';
	console.log('zip cmd: ' + cmdzip);
	packer.exec(
		cmdzip,
		{
			cwd: workingDir
		},
		function (err, stdout, stderr) {
			console.log(stdout);
			if(err != null){
				console.log(stderr);
			}else{
				console.log('compressing ok');
			}
			finish(null);
		});
}
<commit_msg>removed commented code<commit_after>#!/usr/bin/env node

// 1) validate a zip file argument was supplied
// 2) unzip the zip file using node_appc
// 3) copy the "mobileweb" directory to "tizen"
// 4) remove tizen/templates/app/default/resources/mobileweb directory
// 4) copy tizen files (cli, templates, titanium) on top of "tizen" directory
// 5) copy titanium-sdk/lib/tiappxml.js on top of node_modules/titanium-sdk/lib
// 6) read manifest.json, parse json, add "tizen" to platforms, stringify json, write manifest
// 7) run dependencies.json builder using titanium_mobile/support/mobileweb/dependencyAnalyzer
// 8) re-zip distribution file with "VERSION-tizen.zip"

//input parameters:
// path to zip
// output file name
// working directory unzip original sdk

console.log("cli args: " + process.argv);

var fs = require('fs'),
	path = require('path'),
	async = require('async'),
	appc = require('node-appc'),
	xmldom = require('xmldom'),
	wrench = require('wrench'),
	tmpFileUtil = require ("file-utils").File,
	scriptArgs = process.argv.slice(2),
	workingDir = void 0,//scriptArgs[1],
	titaniumTizenDir = __dirname,
	sdkRoot,
	resultPath,
	buildLinuxSdk = false;

console.log('[DEBUG] scriptArgs(zip, working directory): ' + scriptArgs);

async.series([
	function(next){
		//Validation
		if(validateArgs(scriptArgs)){
			var archiveName = path.basename(scriptArgs[0]);
			//build name for output zip with SDK
			archiveName = archiveName.replace('.zip', '-tizen.zip');
			resultPath = path.join(path.dirname(scriptArgs[0]), archiveName);
			if(resultPath.indexOf('linux') != -1){
				//initialize everything for linux sdk
				buildLinuxSdk = true;
			}
			console.log('[DEBUG] created output file name: ' + resultPath);
			if(process.platform === 'win32'){
				//create temporary dir to unzip and modify sdk content. The dir is removed when the process finishes
				var settings = {
						directory: scriptArgs[1]
				};
				tmpFileUtil.createTempFolder (settings, function (error, folder){
					if(folder == null){
						next("Cannot create temporary directory", 'failed');
					}
					console.log ('[DEBUG] created temporary directory:' + folder.toString());
					workingDir = folder.toString();
					next(null, 'ok');
				});
			}else{
				workingDir = scriptArgs[1];
				next(null, 'ok');
			}
		}
	}
	, function(next){
		console.log('[DEBUG] Start unzip');
		//Unzip callback
		var resultCb = function(errorMsg){
			if(errorMsg){
				console.log('[DEBUG] unzip finished with error: ' + errorMsg);
				next(null, 'ok');
			}else{
				next(null, 'ok');
			}
		};
		if(process.platform === 'win32'){
			unzip7za(scriptArgs[0], workingDir, resultCb);
		}else{
			appc.zip.unzip(scriptArgs[0], workingDir, resultCb);
		}
	}
	, function(next){
		console.log('[DEBUG] Create tizen platform, initially copy it from mobileweb');
 		copymobilWebToTizen(function(){
 			console.log('[DEBUG] copymobilWebToTizen calling next()');
 			next(null, 'ok');
 		});
	}
	, function(next){
		console.log('[DEBUG] fixing manifest.json');
		fixManifest();
		next(null, 'ok');
	}, function(next){
		executeDependenciesAnalyzer(function(){
			next(null, 'ok');
		});
	}, function(next){
		if(process.platform === 'win32'){
			console.log('Start packaging on win32');
			packagingSDK7z(function(){
				next(null, 'ok');
			});
		} else {
			packagingSDKLinux(function(){
				next(null, 'Packaging on linux ok');
			});
		}
	}
	], function(err){
		if(err)
			console.log(err)
		console.log('Finished.')

});

//validating input parameters
function validateArgs(params){
	var workOk = true;
	if(!fs.existsSync(params[0])){
		console.log('Error: param 1 should point existng zip archive. Current value: ' + params[0]);
		workOk = false;
	}
	var stats = fs.statSync(params[1]);
	if(!stats.isDirectory() ){
		console.log('Error: param 3 should point existing directory. Current value: ' + params[1]);
		workOk = false;
	}
	return workOk;
}

function copymobilWebToTizen(finish){
	var basePath;
	if(buildLinuxSdk){
		basePath = path.join(workingDir, 'mobilesdk', 'linux');
	}else{
		basePath = path.join(workingDir, 'mobilesdk', 'win32');
	}
	console.log('[DEBUG] Looking for sdk in  folder:' + basePath);
	appc.fs.visitDirs(basePath,
		function(name, dpath){
			sdkRoot = dpath;
			console.log('[DEBUG] Full path to SDK folder:' + sdkRoot);
		},
		function(){
			//visitDirs finished, sdk root detected, create initiali version of tizen directory that really is copy of mobileweb
			console.log('[DEBUG] wrench.copyDirSyncRecursive from ' + path.join(sdkRoot, 'mobileweb') + " to "+ path.join(sdkRoot, 'tizen'));
			wrench.copyDirSyncRecursive(path.join(sdkRoot, 'mobileweb'), path.join(sdkRoot, 'tizen'));

			console.log('[DEBUG] copyDirSyncRecursiveEx from ' +path.join(titaniumTizenDir, 'titanium', 'Ti') + " to "+ path.join(sdkRoot, 'tizen', 'titanium', 'Ti'));
			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'titanium', 'Ti'), path.join(sdkRoot, 'tizen', 'titanium', 'Ti'));

			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'cli', 'commands'), path.join(sdkRoot, 'tizen', 'cli', 'commands'));

			copyFileSync(path.join(titaniumTizenDir, 'titanium', 'Ti.js'), path.join(sdkRoot, 'tizen', 'titanium', 'Ti.js'));

			//config.tmpl template for
			copyFileSync(path.join(titaniumTizenDir, 'templates', 'app', 'config.tmpl'), path.join(sdkRoot, 'tizen', 'templates', 'app', 'config.tmpl'));

			wrench.copyDirSyncRecursive(path.join(titaniumTizenDir,'templates', 'app', 'default', 'Resources', 'tizen'), path.join(sdkRoot, 'tizen', 'templates', 'app', 'default', 'Resources', 'tizen'));

			copyFileSync(path.join(titaniumTizenDir, 'src', 'loader.js'), path.join(sdkRoot, 'tizen', 'src', 'loader.js'));

			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'dependencyAnalyzer'), path.join(sdkRoot, 'tizen', 'dependencyAnalyzer'));

			copyDirSyncRecursiveEx(path.join(titaniumTizenDir, 'themes'), path.join(sdkRoot, 'tizen', 'themes'));

			//signer app for tizen
			fs.mkdirSync(path.join(sdkRoot, 'tizen', 'utils'));
			copyFileSync(path.join(titaniumTizenDir, 'utils', 'signapp.jar'), path.join(sdkRoot, 'tizen', 'utils', 'signapp.jar'));

			finish();
		}
	);
}

function applyPatches(){
	//make temp dir

	//generate patche

	//apply patch

}

function fixManifest(){
	var manifestPath = path.join(sdkRoot, "manifest.json");
	var manifestStr = fs.readFileSync(manifestPath, 'utf8').toString();
	var manifestObject = JSON.parse(manifestStr);
	manifestObject.platforms.push("tizen");
	fs.writeFileSync(manifestPath, JSON.stringify(manifestObject), 'utf8');
}

function executeDependenciesAnalyzer(finished){
	console.log('[DEBUG] executeDependenciesAnalyzer ');
	var runner = require('child_process');
	var scriptpath = path.join(sdkRoot, 'tizen', 'dependencyAnalyzer', 'dependencyAnalyzer.js');
	var analyzerCmd = 'node "' + scriptpath + '"';

	console.log('starting dependency analyzer: ' + analyzerCmd);
	options = { cwd: path.join(sdkRoot, 'tizen', 'dependencyAnalyzer') };
	runner.exec(
		analyzerCmd,
		function (err, stdout, stderr) {
			console.log(stdout);
			if(err != null){
				console.log('[Error] executeDependenciesAnalyzer failed');
				console.log(stderr);
			}else{
				console.log('executeDependenciesAnalyzer ok');
			}
			finished();
		});
}

function copyFileSync(srcFile, destFile) {
	console.log('[DEBUG] copyFileSync from ' + srcFile + " to "+ destFile);
	var bytesRead, fdr, fdw, pos;
	var BUF_LENGTH = 64 * 1024;
	var _buff = new Buffer(BUF_LENGTH);
	fdr = fs.openSync(srcFile, 'r');
	fdw = fs.openSync(destFile, 'w');
	bytesRead = 1;
	pos = 0;
	while (bytesRead > 0) {
		bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos);
		fs.writeSync(fdw, _buff, 0, bytesRead);
		pos += bytesRead;
	}
	fs.closeSync(fdr);
	return fs.closeSync(fdw);
}

function copyDirSyncRecursiveEx(sourceDir, newDirLocation) {
	console.log('[DEBUG] copyDirSyncRecursiveEx src ' + sourceDir + " destination "+ newDirLocation);
    /*  Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
    var checkDir = fs.statSync(sourceDir);
    try {
    	if(!fs.existsSync(newDirLocation)){
        	fs.mkdirSync(newDirLocation, checkDir.mode);
    	}
    } catch (e) {
        //if the directory already exists, that's okay
        if (e.code !== 'EEXIST') throw e;
    }

    var files = fs.readdirSync(sourceDir);
	console.log('[DEBUG] copyDirSyncRecursiveEx created filelist for ' + sourceDir + " it contains "+ files.length);
    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
        if(currFile.isDirectory()) {
            /*  recursion this thing right on back. */
            copyDirSyncRecursiveEx(sourceDir + "/" + files[i], newDirLocation + "/" + files[i]);
        } else if(currFile.isSymbolicLink()) {
        	console.log('[WARRNING] copyDirSyncRecursiveEx symlink instead of file: ' + sourceDir + "/" + files[i]);
            var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]);
            fs.symlinkSync(symlinkFull, newDirLocation + "/" + files[i]);
        } else {
            /*  At this point, we've hit a file actually worth copying... so copy it on over. */
            copyFileSync(sourceDir + "/" + files[i], newDirLocation + "/" + files[i])
        }
    }
}

function find7za(){
	var zippath = path.normalize(path.join(path.dirname(require.resolve('node-appc')), '..','tools','7zip','7za.exe'));
	console.log('7za.exe detected. Path is ' + path.normalize(zippath));

	if(fs.existsSync(zippath)){
		return zippath;
	}else{
		console.log('Not found 7za.exe path is wrong ' + path.normalize(zippath));
	}
}

function packagingSDK7z(finish){
	console.log('Packaging application into zip');
	var packer = require('child_process');
	// Create the tasks to unzip each entry in the zip file
	var child,
	stdout = '',
	stderr = '';

	child = packer.spawn(path.resolve(find7za().toString()), ['a', resultPath, workingDir + '/*', '-tzip']);
	child.stdout.on('data', function (data) {
		stdout += data.toString();
	});
	child.on('exit', function (code, signal) {
		if (finish) {
			if (code) {
				// if we're on windows, the error message is actually in stdout, so scan for it
				if (process.platform === 'win32') {
					var foundError = false,
						err = [];

					stdout.split('\n').forEach(function (line) {
						if (/^Error\:/.test(line)) {
							foundError = true;
						}
						if (foundError) {
							line && err.push(line.trim());
						}
					});
					if (err.length) {
						stderr = err.join('\n') + stderr;
					}
				}
				finish();
			} else {
				finish();
			}
		}
	});
}

function unzip7za(src, dest, callback){
	var packer = require('child_process');
	// Create the tasks to unzip each entry in the zip file
	var child,
	stdout = '',
	stderr = '';

	child = packer.spawn(path.resolve(find7za().toString()), ['x', src, '-o' + dest, '-y', '-bd']);
	child.stdout.on('data', function (data) {
		stdout += data.toString();
	});
	child.on('exit', function (code, signal) {
		if (callback) {
			if (code) {
				// if we're on windows, the error message is actually in stdout, so scan for it
				if (process.platform === 'win32') {
					var foundError = false,
						err = [];

					stdout.split('\n').forEach(function (line) {
						if (/^Error\:/.test(line)) {
							foundError = true;
						}
						if (foundError) {
							line && err.push(line.trim());
						}
					});

					if (err.length) {
						stderr = err.join('\n') + stderr;
					}
				}
				callback(null);
			} else {
				callback(null);
			}
		}
	});
}

function packagingSDKLinux(finish){
	var packer = require('child_process');
	var cmdzip = 'zip -r "' + resultPath + '" *';
	console.log('zip cmd: ' + cmdzip);
	packer.exec(
		cmdzip,
		{
			cwd: workingDir
		},
		function (err, stdout, stderr) {
			console.log(stdout);
			if(err != null){
				console.log(stderr);
			}else{
				console.log('compressing ok');
			}
			finish(null);
		});
}
<|endoftext|>


<commit_before>/*
 * vim: ts=4:sw=4:expandtab
 */
(function () {
    'use strict';

    window.Whisper = window.Whisper || {};

    var SocketView = Whisper.View.extend({
        className: 'status',
        initialize: function() {
            setInterval(this.updateStatus.bind(this), 5000);
        },
        updateStatus: function() {
            var className, message = '';
            if (typeof getSocketStatus === 'function') {
              switch(getSocketStatus()) {
                  case WebSocket.CONNECTING:
                      className = 'connecting';
                      break;
                  case WebSocket.OPEN:
                      className = 'open';
                      break;
                  case WebSocket.CLOSING:
                      className = 'closing';
                      break;
                  case WebSocket.CLOSED:
                      className = 'closed';
                      message = i18n('disconnected');
                      break;
              }
            if (!this.$el.hasClass(className)) {
                this.$el.attr('class', className);
                this.$el.text(message);
            }
          }
        }
    });

    Whisper.ConversationStack = Whisper.View.extend({
        className: 'conversation-stack',
        open: function(conversation) {
            var id = 'conversation-' + conversation.cid;
            if (id !== this.el.firstChild.id) {
                this.$el.first().find('video, audio').each(function() {
                    this.pause();
                });
                var $el = this.$('#'+id);
                if ($el === null || $el.length === 0) {
                    var view = new Whisper.ConversationView({
                        model: conversation,
                        appWindow: this.model.appWindow
                    });
                    $el = view.$el;
                }
                $el.prependTo(this.el);
                conversation.trigger('opened');
            }
        }
    });

    Whisper.FontSizeView = Whisper.View.extend({
        defaultSize: 14,
        maxSize: 30,
        minSize: 14,
        initialize: function() {
            this.currentSize = this.defaultSize;
            this.render();
        },
        events: { 'keydown': 'zoomText' },
        zoomText: function(e) {
            if (!e.ctrlKey)
                return;
            var keyCode = e.which || e.keyCode;
            var maxSize = 22; // if bigger text goes outside send-message textarea
            var minSize = 14;
            if (keyCode === 189 || keyCode == 109) {
                if (this.currentSize > minSize) {
                    this.currentSize--;
                }
            } else if (keyCode === 187 || keyCode == 107) {
                if (this.currentSize < maxSize) {
                    this.currentSize++;
                }
            }
            this.render();
        },
        render: function() {
            this.$el.css('font-size', this.currentSize + 'px');
        }
    });

    Whisper.InboxView = Whisper.View.extend({
        templateName: 'two-column',
        className: 'inbox',
        applyTheme: function() {
            var theme = storage.get('theme-setting') || 'android';
            this.$el.removeClass('ios')
                    .removeClass('android')
                    .addClass(theme);
        },
        initialize: function (options) {
            this.render();
            this.applyTheme();
            this.$el.attr('tabindex', '1');
            new Whisper.FontSizeView({ el: this.$el });
            this.conversation_stack = new Whisper.ConversationStack({
                el: this.$('.conversation-stack'),
                model: { appWindow: options.appWindow }
            });

            var inboxCollection = getInboxCollection();
            this.inboxListView = new Whisper.ConversationListView({
                el         : this.$('.inbox'),
                collection : inboxCollection
            }).render();

            this.inboxListView.listenTo(inboxCollection,
                    'add change:timestamp change:name change:number',
                    this.inboxListView.sort);

            this.searchView = new Whisper.ConversationSearchView({
                el    : this.$('.search-results'),
                input : this.$('input.search')
            });

            this.searchView.$el.hide();

            this.listenTo(this.searchView, 'hide', function() {
                this.searchView.$el.hide();
                this.inboxListView.$el.show();
            });
            this.listenTo(this.searchView, 'show', function() {
                this.searchView.$el.show();
                this.inboxListView.$el.hide();
            });
            this.listenTo(this.searchView, 'open',
                this.openConversation.bind(this, null));

            new SocketView().render().$el.appendTo(this.$('.socket-status'));

            extension.windows.onClosed(function() {
                this.inboxListView.stopListening();
            }.bind(this));

            if (extension.expired()) {
                var banner = new Whisper.ExpiredAlertBanner().render();
                banner.$el.prependTo(this.$el);
                this.$el.addClass('expired');
            }
        },
        render_attributes: {
            welcomeToSignal         : i18n('welcomeToSignal'),
            selectAContact          : i18n('selectAContact'),
            searchForPeopleOrGroups : i18n('searchForPeopleOrGroups'),
            submitDebugLog          : i18n('submitDebugLog'),
            settings                : i18n('settings'),
            restartSignal           : i18n('restartSignal'),
        },
        events: {
            'click': 'onClick',
            'click #header': 'focusHeader',
            'click .conversation': 'focusConversation',
            'click .global-menu .hamburger': 'toggleMenu',
            'click .show-debug-log': 'showDebugLog',
            'click .showSettings': 'showSettings',
            'select .gutter .conversation-list-item': 'openConversation',
            'input input.search': 'filterContacts',
            'click .restart-signal': 'reloadBackgroundPage',
            'show .lightbox': 'showLightbox'
        },
        focusConversation: function(e) {
            if (e && this.$(e.target).closest('.placeholder').length) {
                return;
            }

            this.$('#header, .gutter').addClass('inactive');
            this.$('.conversation-stack').removeClass('inactive');
        },
        focusHeader: function() {
            this.$('.conversation-stack').addClass('inactive');
            this.$('#header, .gutter').removeClass('inactive');
            this.$('.conversation:first .menu').trigger('close');
        },
        reloadBackgroundPage: function() {
            chrome.runtime.reload();
        },
        showSettings: function() {
            var view = new Whisper.SettingsView();
            view.$el.appendTo(this.el);
            view.$el.on('change-theme', this.applyTheme.bind(this));
        },
        filterContacts: function(e) {
            this.searchView.filterContacts(e);
            var input = this.$('input.search');
            if (input.val().length > 0) {
                input.addClass('active');
            } else {
                input.removeClass('active');
            }
        },
        openConversation: function(e, conversation) {
            this.searchView.hideHints();
            conversation = ConversationController.create(conversation);
            this.conversation_stack.open(conversation);
            this.focusConversation();
        },
        toggleMenu: function() {
            this.$('.global-menu .menu-list').toggle();
        },
        showDebugLog: function() {
            this.$('.debug-log').remove();
            new Whisper.DebugLogView().$el.appendTo(this.el);
        },
        showLightbox: function(e) {
            this.$el.append(e.target);
        },
        closeRecording: function(e) {
            if (e && this.$(e.target).closest('.capture-audio').length > 0 ) {
                return;
            }
            this.$('.conversation:first .recorder').trigger('close');
        },
        closeMenu: function(e) {
            if (e && this.$(e.target).parent('.global-menu').length > 0 ) {
                return;
            }

            this.$('.global-menu .menu-list').hide();
        },
        onClick: function(e) {
            this.closeMenu(e);
            this.closeRecording(e);
        }
    });

    Whisper.ExpiredAlertBanner = Whisper.View.extend({
        templateName: 'expired_alert',
        className: 'expiredAlert clearfix',
        render_attributes: function() {
            return {
                expiredWarning: i18n('expiredWarning'),
                upgrade: i18n('upgrade'),
            };
        }
    });

})();
<commit_msg>Style fix<commit_after>/*
 * vim: ts=4:sw=4:expandtab
 */
(function () {
    'use strict';

    window.Whisper = window.Whisper || {};

    var SocketView = Whisper.View.extend({
        className: 'status',
        initialize: function() {
            setInterval(this.updateStatus.bind(this), 5000);
        },
        updateStatus: function() {
            var className, message = '';
            if (typeof getSocketStatus === 'function') {
              switch(getSocketStatus()) {
                  case WebSocket.CONNECTING:
                      className = 'connecting';
                      break;
                  case WebSocket.OPEN:
                      className = 'open';
                      break;
                  case WebSocket.CLOSING:
                      className = 'closing';
                      break;
                  case WebSocket.CLOSED:
                      className = 'closed';
                      message = i18n('disconnected');
                      break;
              }
            if (!this.$el.hasClass(className)) {
                this.$el.attr('class', className);
                this.$el.text(message);
            }
          }
        }
    });

    Whisper.ConversationStack = Whisper.View.extend({
        className: 'conversation-stack',
        open: function(conversation) {
            var id = 'conversation-' + conversation.cid;
            if (id !== this.el.firstChild.id) {
                this.$el.first().find('video, audio').each(function() {
                    this.pause();
                });
                var $el = this.$('#'+id);
                if ($el === null || $el.length === 0) {
                    var view = new Whisper.ConversationView({
                        model: conversation,
                        appWindow: this.model.appWindow
                    });
                    $el = view.$el;
                }
                $el.prependTo(this.el);
                conversation.trigger('opened');
            }
        }
    });

    Whisper.FontSizeView = Whisper.View.extend({
        defaultSize: 14,
        maxSize: 30,
        minSize: 14,
        initialize: function() {
            this.currentSize = this.defaultSize;
            this.render();
        },
        events: { 'keydown': 'zoomText' },
        zoomText: function(e) {
            if (!e.ctrlKey) {
                return;
            }
            var keyCode = e.which || e.keyCode;
            var maxSize = 22; // if bigger text goes outside send-message textarea
            var minSize = 14;
            if (keyCode === 189 || keyCode == 109) {
                if (this.currentSize > minSize) {
                    this.currentSize--;
                }
            } else if (keyCode === 187 || keyCode == 107) {
                if (this.currentSize < maxSize) {
                    this.currentSize++;
                }
            }
            this.render();
        },
        render: function() {
            this.$el.css('font-size', this.currentSize + 'px');
        }
    });

    Whisper.InboxView = Whisper.View.extend({
        templateName: 'two-column',
        className: 'inbox',
        applyTheme: function() {
            var theme = storage.get('theme-setting') || 'android';
            this.$el.removeClass('ios')
                    .removeClass('android')
                    .addClass(theme);
        },
        initialize: function (options) {
            this.render();
            this.applyTheme();
            this.$el.attr('tabindex', '1');
            new Whisper.FontSizeView({ el: this.$el });
            this.conversation_stack = new Whisper.ConversationStack({
                el: this.$('.conversation-stack'),
                model: { appWindow: options.appWindow }
            });

            var inboxCollection = getInboxCollection();
            this.inboxListView = new Whisper.ConversationListView({
                el         : this.$('.inbox'),
                collection : inboxCollection
            }).render();

            this.inboxListView.listenTo(inboxCollection,
                    'add change:timestamp change:name change:number',
                    this.inboxListView.sort);

            this.searchView = new Whisper.ConversationSearchView({
                el    : this.$('.search-results'),
                input : this.$('input.search')
            });

            this.searchView.$el.hide();

            this.listenTo(this.searchView, 'hide', function() {
                this.searchView.$el.hide();
                this.inboxListView.$el.show();
            });
            this.listenTo(this.searchView, 'show', function() {
                this.searchView.$el.show();
                this.inboxListView.$el.hide();
            });
            this.listenTo(this.searchView, 'open',
                this.openConversation.bind(this, null));

            new SocketView().render().$el.appendTo(this.$('.socket-status'));

            extension.windows.onClosed(function() {
                this.inboxListView.stopListening();
            }.bind(this));

            if (extension.expired()) {
                var banner = new Whisper.ExpiredAlertBanner().render();
                banner.$el.prependTo(this.$el);
                this.$el.addClass('expired');
            }
        },
        render_attributes: {
            welcomeToSignal         : i18n('welcomeToSignal'),
            selectAContact          : i18n('selectAContact'),
            searchForPeopleOrGroups : i18n('searchForPeopleOrGroups'),
            submitDebugLog          : i18n('submitDebugLog'),
            settings                : i18n('settings'),
            restartSignal           : i18n('restartSignal'),
        },
        events: {
            'click': 'onClick',
            'click #header': 'focusHeader',
            'click .conversation': 'focusConversation',
            'click .global-menu .hamburger': 'toggleMenu',
            'click .show-debug-log': 'showDebugLog',
            'click .showSettings': 'showSettings',
            'select .gutter .conversation-list-item': 'openConversation',
            'input input.search': 'filterContacts',
            'click .restart-signal': 'reloadBackgroundPage',
            'show .lightbox': 'showLightbox'
        },
        focusConversation: function(e) {
            if (e && this.$(e.target).closest('.placeholder').length) {
                return;
            }

            this.$('#header, .gutter').addClass('inactive');
            this.$('.conversation-stack').removeClass('inactive');
        },
        focusHeader: function() {
            this.$('.conversation-stack').addClass('inactive');
            this.$('#header, .gutter').removeClass('inactive');
            this.$('.conversation:first .menu').trigger('close');
        },
        reloadBackgroundPage: function() {
            chrome.runtime.reload();
        },
        showSettings: function() {
            var view = new Whisper.SettingsView();
            view.$el.appendTo(this.el);
            view.$el.on('change-theme', this.applyTheme.bind(this));
        },
        filterContacts: function(e) {
            this.searchView.filterContacts(e);
            var input = this.$('input.search');
            if (input.val().length > 0) {
                input.addClass('active');
            } else {
                input.removeClass('active');
            }
        },
        openConversation: function(e, conversation) {
            this.searchView.hideHints();
            conversation = ConversationController.create(conversation);
            this.conversation_stack.open(conversation);
            this.focusConversation();
        },
        toggleMenu: function() {
            this.$('.global-menu .menu-list').toggle();
        },
        showDebugLog: function() {
            this.$('.debug-log').remove();
            new Whisper.DebugLogView().$el.appendTo(this.el);
        },
        showLightbox: function(e) {
            this.$el.append(e.target);
        },
        closeRecording: function(e) {
            if (e && this.$(e.target).closest('.capture-audio').length > 0 ) {
                return;
            }
            this.$('.conversation:first .recorder').trigger('close');
        },
        closeMenu: function(e) {
            if (e && this.$(e.target).parent('.global-menu').length > 0 ) {
                return;
            }

            this.$('.global-menu .menu-list').hide();
        },
        onClick: function(e) {
            this.closeMenu(e);
            this.closeRecording(e);
        }
    });

    Whisper.ExpiredAlertBanner = Whisper.View.extend({
        templateName: 'expired_alert',
        className: 'expiredAlert clearfix',
        render_attributes: function() {
            return {
                expiredWarning: i18n('expiredWarning'),
                upgrade: i18n('upgrade'),
            };
        }
    });

})();
<|endoftext|>


<commit_before>var write = require('fs').writeFile
var read = require('fs').readFileSync
var colors = require('irc').colors
var Bitly = require('bitly')
const owo = require('@zuzak/owo')

const plugin = require('../plugins/news')

var oldnews = {}

module.exports = {
  commands: {
    poll: {
      help: 'poll for news',
      privileged: true,
      command: function () {
        plugin.pollApis(true)
        return 'ok'
      }
    },
    clearnews: {
      help: 'Clears the news cache',
      command: function (bot) {
        oldnews = {}
        return 'News cache cleared. Take cover :)'
      }
    },
    corrections: {
      help: 'Sends link to BBC News corrections',
      command: function () {
        return 'http://www.bbc.co.uk/faqs/bbcnews_editorial'
      }
    }
  },
  onload: function () {
    try {
      oldnews = require(__rootdir + '/data/news.json') || {}
    } catch (e) {
      oldnews = {}
    }
  },
  events: {
    /**
     * The rawnews event is defined in plugins/news.js, and triggers on each poll
     * of the BBC News API. Here, we extract useable data from the rather idiosyncratic API
     * and send it to the news event.
     */
    'rawnews:bbc': function (bot, story) {
      if (story && story.headline) {
        bot.fireEvents('news', {
          color: 'dark_red',
          id: 'BBC' + story.headline + story.assetUri,
          text: story.headline,
          url: 'https://bbc.co.uk' + story.assetUri,
          prompt: 'BBC BREAKING'
        })
      }
    },
    'rawnews:reuters': function (bot, story) {
      if (!story.headline) return
      bot.fireEvents('news', {
        color: 'orange',
        id: story.headline,
        prompt: story.label ? story.label : 'Reuters',
        tail: story.tag ? story.tag : null,
        text: story.headline,
        url: story.url ? story.url : null
      })
    },
    'rawnews:mi5': function (bot, feed) {
      const item = feed.items[0]
      bot.fireEvents('news', {
        color: 'light_cyan',
        id: item.guid,
        prompt: feed.feed.title,
        text: item.content,
        url: item.link
      })
    },
    'rawnews:bloomberg': function (bot, stories) {
      for (var i = 0; i < stories.length; i++) {
        var story = stories[i]
        if (story) {
          bot.fireEvents('news', {
            color: 'purple',
            id: 'bbrg' + story.toString(),
            text: JSON.stringify(story),
            url: null,
            prompt: stories.editorialTitle,
            tail: 'Bloomberg (test)'
          })
        }
      }
    },
    'rawnews:reuwire': function (bot, stories) {
      for (let i = 0; i < stories.length; i++) {
        let story = stories[i]
        bot.fireEvents('news', {
          color: 'yellow',
          id: story.id,
          text: story.headline,
          prompt: 'Reuters',
          url: 'http://www.reuters.com' + story.url
        })
      }
    },
    'rawnews:aljaz': function (bot, story) {
      if (story.Alert) {
        for (var i = 0; i < story.AlertText.length; i++) {
          var curr = story.AlertText[0]
          bot.fireEvents('news', {
            color: 'orange',
            id: curr.GUID,
            prompt: 'Al Jazeera ' + curr.Type,
            text: curr.Text,
            url: curr.Url
          })
        }
      }
    },
    news: function (bot, news) {
      console.log('NEWSNEWSNEWS', news)
      if (!oldnews[news.id]) {
        bot.fireEvents('newNews', news)
      }
    },
    newNews: (bot, news) => {
      var bitly = new Bitly(bot.config.get('bitly.username'), bot.config.get('bitly.password'))
      bitly.shorten(news.url, function (err, res) {
        if (err) res = { data: { url: news.url } }
        var str = ''
        if (news.prompt) {
          str += colors.wrap(news.color, news.prompt + ': ')
        }
        // news transform
        try {
          if (bot.config.get('news.replace')) {
            var substitutions = JSON.parse(read(__rootdir + '/data/substitutions.json', { encoding: 'utf-8' }))
            var stringsToReplace = Object.keys(substitutions)
            var newstr = news.text
            for (var i = 0; i < stringsToReplace.length; i++) {
              newstr = newstr.replace(stringsToReplace[i], '\x1f' + substitutions[stringsToReplace[i]] + '\x0f')
            }
            str += newstr
          } else {
            str += news.text
          }
          if (Math.random() <= bot.config.get('news.owo')) {
            str = owo(str)
          }
        } catch (e) {
          str += news.text + '(err)'
        }
        if (res.data.url) {
          str += ' ' + colors.wrap('gray', res.data.url)
        }
        if (news.tail) {
          str += ' ' + colors.wrap('magenta', '(' + news.tail + ')')
        }

        bot.broadcast(str)
      })
      oldnews[news.id] = news
      write(__rootdir + '/data/news.json', JSON.stringify(oldnews))
    }
  }
}
<commit_msg>Remove console.log (#274)<commit_after>var write = require('fs').writeFile
var read = require('fs').readFileSync
var colors = require('irc').colors
var Bitly = require('bitly')
const owo = require('@zuzak/owo')

const plugin = require('../plugins/news')

var oldnews = {}

module.exports = {
  commands: {
    poll: {
      help: 'poll for news',
      privileged: true,
      command: function () {
        plugin.pollApis(true)
        return 'ok'
      }
    },
    clearnews: {
      help: 'Clears the news cache',
      command: function (bot) {
        oldnews = {}
        return 'News cache cleared. Take cover :)'
      }
    },
    corrections: {
      help: 'Sends link to BBC News corrections',
      command: function () {
        return 'http://www.bbc.co.uk/faqs/bbcnews_editorial'
      }
    }
  },
  onload: function () {
    try {
      oldnews = require(__rootdir + '/data/news.json') || {}
    } catch (e) {
      oldnews = {}
    }
  },
  events: {
    /**
     * The rawnews event is defined in plugins/news.js, and triggers on each poll
     * of the BBC News API. Here, we extract useable data from the rather idiosyncratic API
     * and send it to the news event.
     */
    'rawnews:bbc': function (bot, story) {
      if (story && story.headline) {
        bot.fireEvents('news', {
          color: 'dark_red',
          id: 'BBC' + story.headline + story.assetUri,
          text: story.headline,
          url: 'https://bbc.co.uk' + story.assetUri,
          prompt: 'BBC BREAKING'
        })
      }
    },
    'rawnews:reuters': function (bot, story) {
      if (!story.headline) return
      bot.fireEvents('news', {
        color: 'orange',
        id: story.headline,
        prompt: story.label ? story.label : 'Reuters',
        tail: story.tag ? story.tag : null,
        text: story.headline,
        url: story.url ? story.url : null
      })
    },
    'rawnews:mi5': function (bot, feed) {
      const item = feed.items[0]
      bot.fireEvents('news', {
        color: 'light_cyan',
        id: item.guid,
        prompt: feed.feed.title,
        text: item.content,
        url: item.link
      })
    },
    'rawnews:bloomberg': function (bot, stories) {
      for (var i = 0; i < stories.length; i++) {
        var story = stories[i]
        if (story) {
          bot.fireEvents('news', {
            color: 'purple',
            id: 'bbrg' + story.toString(),
            text: JSON.stringify(story),
            url: null,
            prompt: stories.editorialTitle,
            tail: 'Bloomberg (test)'
          })
        }
      }
    },
    'rawnews:reuwire': function (bot, stories) {
      for (let i = 0; i < stories.length; i++) {
        let story = stories[i]
        bot.fireEvents('news', {
          color: 'yellow',
          id: story.id,
          text: story.headline,
          prompt: 'Reuters',
          url: 'http://www.reuters.com' + story.url
        })
      }
    },
    'rawnews:aljaz': function (bot, story) {
      if (story.Alert) {
        for (var i = 0; i < story.AlertText.length; i++) {
          var curr = story.AlertText[0]
          bot.fireEvents('news', {
            color: 'orange',
            id: curr.GUID,
            prompt: 'Al Jazeera ' + curr.Type,
            text: curr.Text,
            url: curr.Url
          })
        }
      }
    },
    news: function (bot, news) {
      if (!oldnews[news.id]) {
        bot.fireEvents('newNews', news)
      }
    },
    newNews: (bot, news) => {
      var bitly = new Bitly(bot.config.get('bitly.username'), bot.config.get('bitly.password'))
      bitly.shorten(news.url, function (err, res) {
        if (err) res = { data: { url: news.url } }
        var str = ''
        if (news.prompt) {
          str += colors.wrap(news.color, news.prompt + ': ')
        }
        // news transform
        try {
          if (bot.config.get('news.replace')) {
            var substitutions = JSON.parse(read(__rootdir + '/data/substitutions.json', { encoding: 'utf-8' }))
            var stringsToReplace = Object.keys(substitutions)
            var newstr = news.text
            for (var i = 0; i < stringsToReplace.length; i++) {
              newstr = newstr.replace(stringsToReplace[i], '\x1f' + substitutions[stringsToReplace[i]] + '\x0f')
            }
            str += newstr
          } else {
            str += news.text
          }
          if (Math.random() <= bot.config.get('news.owo')) {
            str = owo(str)
          }
        } catch (e) {
          str += news.text + '(err)'
        }
        if (res.data.url) {
          str += ' ' + colors.wrap('gray', res.data.url)
        }
        if (news.tail) {
          str += ' ' + colors.wrap('magenta', '(' + news.tail + ')')
        }

        bot.broadcast(str)
      })
      oldnews[news.id] = news
      write(__rootdir + '/data/news.json', JSON.stringify(oldnews))
    }
  }
}
<|endoftext|>


<commit_before>
/*
 Map browser based on OpenLayers 5. Tracking.
 Bulletin board.

 Copyright (C) 2017-2018 Øyvind Hanssen, LA7ECA, ohanssen@acm.org

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published
 by the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * Bulletin board widget (in a popup window).
 */

pol.tracking.BullBoard = class extends pol.core.Widget {

    constructor() {
        super();
        this.classname = "tracking.BullBoard";
        this.server = CONFIG.server;
        var t = this;
        var groups = [];
        var messages = [];
        var announcements = [];
        var selectedGroup = 'APRS'; // FIXME: Save in sessionStorage

        /* Render a bulletin group */
        var showGroup = {
            view: function(vn) {
                return m("table", vn.attrs.msgs.map( x => {
                    return m("tr", [ m("td", x.sender), m("td", m("table", x.bulls.map( y => {
                        if (y!=null) return m("tr",
                            [m("td", y.text), m("td.time", formatAge(y.time))] );
                    })))]);
                }));
            }
        }

        this.widget = {
            view: function() {
                var i=0;
                return m("div#bullboard", [
                    m("h1", "APRS Bulletin Board"),
                    m("div.content", [
                    m("h4", "Groups:"),
                    groups.map( x => {
                        return [m("span",
                            {"class": (x==selectedGroup ? 'selected' :''), onclick:apply(selectGroup, x)},
                            x ), " " ];
                    }),
                    m("h4", "Bulletins ("+selectedGroup+"):"),
                    m(showGroup, {msgs: messages}),

                    m("h4", "Announcements:"),
                    m(showGroup, {msgs: announcements}) ])
                ]);
            }
        };

        selectedGroup = CONFIG.get('tracking.BullBoard.group');
        if (!selectedGroup)
            selectedGroup = 'APRS';

        getGroups();
        getMessages();
        getAnn();
        updateScreen();

        t.server.pubsub.subscribe("bullboard", x => {
            getGroups();
            getMessages();
            getAnn();
        });

        /* Re-render and if height extends viewport height, add a scrollbar */
        function updateScreen() {
            m.redraw();
            setTimeout( () => {
                var ht = $('#map').height() - t.pos[1] -80;
                if ($('#bullboard .content').parent().is( "#bullboard .scroll" ) )
                    $('#bullboard .content').unwrap();

                if ($('#bullboard .content').height() < ht)
                    ht = $('#bullboard .content').height()+20;
                else {
                    $('#bullboard .content').wrap('

');
                    $('#bullboard .scroll').height(Math.round(ht));
                }
            }, 500);
        }

        /* Select the bulletin group to be shown */
        function selectGroup(group) {
            selectedGroup = group;
            CONFIG.store('tracking.BullBoard.group', selectedGroup, false);
            getMessages();
        }

        /* Get set of groups from server */
        function getGroups() {
            t.server.GET("/bullboard/groups", "", x => {
                groups = JSON.parse(x);
                groups.unshift('APRS');
                m.redraw();
            } );
        }

        /* Get selected bulletin group from server */
        function getMessages() {
            var g = selectedGroup;
            if (g == 'APRS')
                g = '_B_';
            t.server.GET("/bullboard/"+g+"/messages", "", x => {
                messages = JSON.parse(x);
                updateScreen();
            } );
        }

        /* Get announcements from server */
        function getAnn() {
            t.server.GET("/bullboard/_A_/messages", "", x => {
                announcements = JSON.parse(x);
                updateScreen();
            } );
        }

        /* Format time as age */
        function formatAge(date) {
            var ltime = new Date(date);
            var now = new Date();
            var diff = now - ltime;
            var hour = Math.floor(diff/1000/60/60);
            var min = Math.floor((diff-hour*1000*60*60)/1000/60);
            if (hour==0)
                return min+"m";
            else
                return hour+"h"+min+"m";
        }

        /* Apply a function to an argument. Returns a new function */
        function apply(f, id) {return function() { f(id); }};

    }

} /* class */

pol.widget.setFactory( "tracking.BullBoard", {
        create: () => new pol.tracking.BullBoard()
    });

<commit_msg>Bullboard fixes<commit_after>
/*
 Map browser based on OpenLayers 5. Tracking.
 Bulletin board.

 Copyright (C) 2017-2018 Øyvind Hanssen, LA7ECA, ohanssen@acm.org

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published
 by the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * Bulletin board widget (in a popup window).
 */

pol.tracking.BullBoard = class extends pol.core.Widget {

    constructor() {
        super();
        this.classname = "tracking.BullBoard";
        this.server = CONFIG.server;
        var t = this;
        var groups = [];
        var messages = [];
        var announcements = [];
        var selectedGroup = 'Announcements';

        /* Render a bulletin group */
        var showGroup = {
            view: function(vn) {
                return m("table", vn.attrs.msgs.map( x => {
                    return m("tr", [ m("td", x.sender), m("td", m("table", x.bulls.map( y => {
                        if (y!=null) return m("tr",
                            [m("td", y.text), m("td.time", formatAge(y.time))] );
                    })))]);
                }));
            }
        }

        this.widget = {
            view: function() {
                var i=0;
                return m("div#bullboard", [
                    m("h1", "APRS Bulletin Board"),
                    m("div.content", [
                    m("h4", "Bulletin group:"),
                    m("div.bgroups",
                    groups.map( x => {
                        return [m("span",
                            {"class": (x==selectedGroup ? 'selected' :''), onclick:apply(selectGroup, x)},
                            x ), " " ];
                    })),
                    ( selectedGroup!="Announcements"
                        ? m(showGroup, {msgs: messages})
                        : m(showGroup, {msgs: announcements})
                    )
                ])]);
            }
        };

        selectedGroup = CONFIG.get('tracking.BullBoard.group');
        if (!selectedGroup)
            selectedGroup = 'APRS';

        getGroups();
        getMessages();
        getAnn();
        updateScreen();

        t.server.pubsub.subscribe("bullboard", x => {
            getGroups();
            getMessages();
            getAnn();
        });

        /* Re-render and if height extends viewport height, add a scrollbar */
        function updateScreen() {
            m.redraw();
            setTimeout( () => {
                var ht = $('#map').height() - t.pos[1] -80;
                if ($('#bullboard .content').parent().is( "#bullboard .scroll" ) )
                    $('#bullboard .content').unwrap();

                if ($('#bullboard .content').height() < ht)
                    ht = $('#bullboard .content').height()+20;
                else {
                    $('#bullboard .content').wrap('

');
                    $('#bullboard .scroll').height(Math.round(ht));
                }
            }, 500);
        }

        /* Select the bulletin group to be shown */
        function selectGroup(group) {
            selectedGroup = group;
            CONFIG.store('tracking.BullBoard.group', selectedGroup, false);
            if (group=='Announcements')
                getAnn();
            else
                getMessages();
        }

        /* Get set of groups from server */
        function getGroups() {
            t.server.GET("/bullboard/groups", "", x => {
                groups = JSON.parse(x);
                groups.unshift('APRS');
                groups.unshift('Announcements');
                m.redraw();
            } );
        }

        /* Get selected bulletin group from server */
        function getMessages() {
            var g = selectedGroup;
            if (g == 'APRS')
                g = '_B_';
            t.server.GET("/bullboard/"+g+"/messages", "", x => {
                messages = JSON.parse(x);
                updateScreen();
            } );
        }

        /* Get announcements from server */
        function getAnn() {
            t.server.GET("/bullboard/_A_/messages", "", x => {
                announcements = JSON.parse(x);
                console.log("ANN: ", x);
                updateScreen();
            } );
        }

        /* Format time as age */
        function formatAge(date) {
            var ltime = new Date(date);
            var now = new Date();
            var diff = now - ltime;
            var hour = Math.floor(diff/1000/60/60);
            var min = Math.floor((diff-hour*1000*60*60)/1000/60);
            if (hour==0)
                return min+"m";
            else
                return hour+"h"+min+"m";
        }

        /* Apply a function to an argument. Returns a new function */
        function apply(f, id) {return function() { f(id); }};

    }

} /* class */

pol.widget.setFactory( "tracking.BullBoard", {
        create: () => new pol.tracking.BullBoard()
    });

<|endoftext|>


<commit_before>google.load('visualization', '1.0', {packages:['table','map','timeline']});

var ConferenceTracker = ConferenceTracker || {};
ConferenceTracker.data = null;

ConferenceTracker.load = function(dataRows) {
  ConferenceTracker.data = new google.visualization.DataTable();

  //Setup table
  var data = ConferenceTracker.data;
  data.addColumn('string', 'Title');
  data.addColumn('string', 'Description');
  data.addColumn('string', 'Type');
  data.addColumn('string', 'Location');
  data.addColumn('date', 'Deadline');
  data.addColumn('date', 'Notification');
  data.addColumn('number', 'Lat');
  data.addColumn('number', 'Lon');
  data.addColumn('string','Website');

  var title, description, type, location, date, lat, lon, tooltip, website;

  for (var i=0;i<dataRows.length;i++){
      description = dataRows[i].description;
      title = dataRows[i].title;
      type = dataRows[i].type;
      location = dataRows[i].location;
      deadline = new Date(dataRows[i].deadline);
      notification = new Date(dataRows[i].notification);
      website = dataRows[i].url

      lat = dataRows[i].latitude;
      lon = dataRows[i].longitude;

      data.addRows([
           [title, description, type, location, deadline, notification, lat, lon, website]
      ]);
  }
}

ConferenceTracker.drawTable = function() {
  var tableOptions = {'showRowNumber': true, 'allowHtml': true/*, 'cssClassNames': cssClassNames*/ };
  tableOptions['page'] = 'enable';
  tableOptions['pageSize'] = 10;
  tableOptions['pagingSymbols'] = {prev: 'prev', next: 'next'};
  tableOptions['pagingButtonsConfiguration'] = 'auto';

  var tableView = new google.visualization.DataView(ConferenceTracker.data);
  tableView.setColumns([
    {calc:linkify, type:'string', label:'Title'},
    1,2,3,
    {calc:statusify, type:'string', label:'Deadline'},
    {calc:dateify, type:'string', label:'Notification'}
  ]);
  function linkify(dataTable, rowNum){
    var title = dataTable.getValue(rowNum, 0);
    var website = dataTable.getValue(rowNum, 8);

    return website == null ? title : "\" + title + "\";
  }
  function statusify(dataTable, rowNum){
    var deadline = dataTable.getValue(rowNum, 4);
    var today = new Date();

    if(Math.floor((deadline.getTime() - today.getTime())/(1000*60*60*24)) < 60 && Math.floor((deadline.getTime() - today.getTime())/(1000*60*60*24)) >0){
      return deadline.toLocaleDateString() + 'Soon';
    }
    else if(Math.floor((deadline.getTime() - today.getTime())/(1000*60*60*24)) < 0 ){
       return deadline.toLocaleDateString() + 'Closed';
    }
    else{
      return deadline.toLocaleDateString() + 'Open';
    }
  }
  function dateify(dataTable, rowNum){
    return dataTable.getValue(rowNum, 5).toLocaleDateString();
  }

  var table = new google.visualization.Table(document.getElementById('table_div'));
  table.draw(tableView, tableOptions);
  return table;
}

ConferenceTracker.drawMap = function() {
  var mapOptions = {showTip:true, useMapTypeControl:true, mapType:'normal', enableScrollWheel:true};

  var geoView = new google.visualization.DataView(ConferenceTracker.data);
  geoView.setColumns([6,7,{calc:tooltipify, type:'string', label:'Tooltip'}]);
  function tooltipify(dataTable, rowNum){
    var title = dataTable.getValue(rowNum, 0);
    var description = dataTable.getValue(rowNum, 1);
    var website = dataTable.getValue(rowNum, 8);

    return ''+title+': '+description;
  }

  var map = new google.visualization.Map(document.getElementById('map_div'));
  map.draw(geoView, mapOptions);
  return map;
}

ConferenceTracker.drawTimeline = function() {
  var chartView = new google.visualization.DataView(ConferenceTracker.data);
  chartView.setColumns([0,4,5]);

  var chart = new google.visualization.Timeline(document.getElementById('timeline_div'));

  var options = {
      timeline: { rowLabelStyle: {fontName: 'Ubuntu'},
                  barLabelStyle: {fontName: 'Ubuntu'} }
    };
  chart.draw(chartView, options);
  return chart;
}

ConferenceTracker.link = function() {
  for (var i=0;i<arguments.length;i++){
    for (var j=0;j<arguments.length;j++){
      if (i != j) {
        var source = arguments[i];
        var target = arguments[j];

        // NB: We have to build the callback using a closure in order to
        // fix the source and target variables inside the callback.
        var callback = function(s, t) {
            return function() { t.setSelection(s.getSelection()); };
        }(source, target);

        google.visualization.events.addListener(source, 'select', callback);
      }
    }
  }
}<commit_msg>Use location names rather than lat and long.<commit_after>google.load('visualization', '1.0', {packages:['table','map','timeline']});

var ConferenceTracker = ConferenceTracker || {};
ConferenceTracker.data = null;

ConferenceTracker.load = function(dataRows) {
  ConferenceTracker.data = new google.visualization.DataTable();

  //Setup table
  var data = ConferenceTracker.data;
  data.addColumn('string', 'Title');
  data.addColumn('string', 'Description');
  data.addColumn('string', 'Type');
  data.addColumn('string', 'Location');
  data.addColumn('date', 'Deadline');
  data.addColumn('date', 'Notification');
  data.addColumn('string','Website');

  var title, description, type, location, date, lat, lon, tooltip, website;

  for (var i=0;i<dataRows.length;i++){
      description = dataRows[i].description;
      title = dataRows[i].title;
      type = dataRows[i].type;
      location = dataRows[i].location;
      deadline = new Date(dataRows[i].deadline);
      notification = new Date(dataRows[i].notification);
      website = dataRows[i].url

      data.addRows([
           [title, description, type, location, deadline, notification, website]
      ]);
  }
}

ConferenceTracker.drawTable = function() {
  var tableOptions = {'showRowNumber': true, 'allowHtml': true/*, 'cssClassNames': cssClassNames*/ };
  tableOptions['page'] = 'enable';
  tableOptions['pageSize'] = 10;
  tableOptions['pagingSymbols'] = {prev: 'prev', next: 'next'};
  tableOptions['pagingButtonsConfiguration'] = 'auto';

  var tableView = new google.visualization.DataView(ConferenceTracker.data);
  tableView.setColumns([
    {calc:linkify, type:'string', label:'Title'},
    1,2,3,
    {calc:statusify, type:'string', label:'Deadline'},
    {calc:dateify, type:'string', label:'Notification'}
  ]);
  function linkify(dataTable, rowNum){
    var title = dataTable.getValue(rowNum, 0);
    var website = dataTable.getValue(rowNum, 6);

    return website == null ? title : "\" + title + "\";
  }
  function statusify(dataTable, rowNum){
    var deadline = dataTable.getValue(rowNum, 4);
    var today = new Date();

    if(Math.floor((deadline.getTime() - today.getTime())/(1000*60*60*24)) < 60 && Math.floor((deadline.getTime() - today.getTime())/(1000*60*60*24)) >0){
      return deadline.toLocaleDateString() + 'Soon';
    }
    else if(Math.floor((deadline.getTime() - today.getTime())/(1000*60*60*24)) < 0 ){
       return deadline.toLocaleDateString() + 'Closed';
    }
    else{
      return deadline.toLocaleDateString() + 'Open';
    }
  }
  function dateify(dataTable, rowNum){
    return dataTable.getValue(rowNum, 5).toLocaleDateString();
  }

  var table = new google.visualization.Table(document.getElementById('table_div'));
  table.draw(tableView, tableOptions);
  return table;
}

ConferenceTracker.drawMap = function() {
  var mapOptions = {showTip:true, useMapTypeControl:true, mapType:'normal', enableScrollWheel:true};

  var geoView = new google.visualization.DataView(ConferenceTracker.data);
  geoView.setColumns([3,{calc:tooltipify, type:'string', label:'Tooltip'}]);
  function tooltipify(dataTable, rowNum){
    var title = dataTable.getValue(rowNum, 0);
    var description = dataTable.getValue(rowNum, 1);
    var website = dataTable.getValue(rowNum, 6);

    return ''+title+': '+description;
  }

  var map = new google.visualization.Map(document.getElementById('map_div'));
  map.draw(geoView, mapOptions);
  return map;
}

ConferenceTracker.drawTimeline = function() {
  var chartView = new google.visualization.DataView(ConferenceTracker.data);
  chartView.setColumns([0,4,5]);

  var chart = new google.visualization.Timeline(document.getElementById('timeline_div'));

  var options = {
      timeline: { rowLabelStyle: {fontName: 'Ubuntu'},
                  barLabelStyle: {fontName: 'Ubuntu'} }
    };
  chart.draw(chartView, options);
  return chart;
}

ConferenceTracker.link = function() {
  for (var i=0;i<arguments.length;i++){
    for (var j=0;j<arguments.length;j++){
      if (i != j) {
        var source = arguments[i];
        var target = arguments[j];

        // NB: We have to build the callback using a closure in order to
        // fix the source and target variables inside the callback.
        var callback = function(s, t) {
            return function() { t.setSelection(s.getSelection()); };
        }(source, target);

        google.visualization.events.addListener(source, 'select', callback);
      }
    }
  }
}<|endoftext|>


<commit_before>/* jQuery Image Magnify script v1.1
* This notice must stay intact for usage
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code

* Nov 16th, 09 (v1.1): Adds ability to dynamically apply/reapply magnify effect to an image, plus magnify to a specific width in pixels.
* Feb 8th, 11 (v1.11): Fixed bug that caused script to not work in newever versions of jQuery (ie: v1.4.4)
*/

jQuery.noConflict()

jQuery.imageMagnify={
	dsettings: {
		magnifyby: 3, //default increase factor of enlarged image
		duration: 500, //default duration of animation, in millisec
		imgopacity: 0.2 //opacify of original image when enlarged image overlays it
 	},
	cursorcss: 'url(js/magnify.cur), -moz-zoom-in', //Value for CSS's 'cursor' attribute, added to original image
	zIndexcounter: 100,

	refreshoffsets:function($window, $target, warpshell){
		var $offsets=$target.offset()
		var winattrs={x:$window.scrollLeft(), y:$window.scrollTop(), w:$window.width(), h:$window.height()}
		warpshell.attrs.x=$offsets.left //update x position of original image relative to page
		warpshell.attrs.y=$offsets.top
		warpshell.newattrs.x=winattrs.x+winattrs.w/2-warpshell.newattrs.w/2
		warpshell.newattrs.y=winattrs.y+winattrs.h/2-warpshell.newattrs.h/2
		if (warpshell.newattrs.x<winattrs.x+5){ //no space to the left?
			warpshell.newattrs.x=winattrs.x+5
		}
		else if (warpshell.newattrs.x+warpshell.newattrs.w > winattrs.x+winattrs.w){//no space to the right?
			warpshell.newattrs.x=winattrs.x+5
		}
		if (warpshell.newattrs.y<winattrs.y+5){ //no space at the top?
			warpshell.newattrs.y=winattrs.y+5
		}
	},

	magnify:function($, $target, options){
		var setting={} //create blank object to store combined settings
		var setting=jQuery.extend(setting, this.dsettings, options)
		var attrs=(options.thumbdimensions)? {w:options.thumbdimensions[0], h:options.thumbdimensions[1]} : {w:$target.outerWidth(), h:$target.outerHeight()}
		var newattrs={}
		newattrs.w=(setting.magnifyto)? setting.magnifyto : Math.round(attrs.w*setting.magnifyby)
		newattrs.h=(setting.magnifyto)? Math.round(attrs.h*newattrs.w/attrs.w) : Math.round(attrs.h*setting.magnifyby)
		$target.css('cursor', jQuery.imageMagnify.cursorcss)
		if ($target.data('imgshell')){
			$target.data('imgshell').$clone.remove()
			$target.css({opacity:1}).unbind('click.magnify')
		}
		var $clone=$target.clone().css({position:'absolute', left:0, top:0, visibility:'hidden', border:'1px solid #ccc', cursor:'pointer'}).appendTo(document.body)
		$clone.data('$relatedtarget', $target) //save $target image this enlarged image is associated with
		$target.data('imgshell', {$clone:$clone, attrs:attrs, newattrs:newattrs})
		$target.bind('click.magnify', function(e){ //action when original image is clicked on
			var $this=$(this).css({opacity:setting.imgopacity})
			var imageinfo=$this.data('imgshell')
			jQuery.imageMagnify.refreshoffsets($(window), $this, imageinfo) //refresh offset positions of original and warped images
			var $clone=imageinfo.$clone
			$clone.stop().css({zIndex:++jQuery.imageMagnify.zIndexcounter, left:imageinfo.attrs.x, top:imageinfo.attrs.y, width:imageinfo.attrs.w, height:imageinfo.attrs.h, opacity:0, visibility:'visible', display:'block'})
			.animate({opacity:1, left:imageinfo.newattrs.x, top:imageinfo.newattrs.y, width:imageinfo.newattrs.w, height:imageinfo.newattrs.h}, setting.duration,
			function(){ //callback function after warping is complete
				//none added
			}) //end animate
		}) //end click
		$clone.click(function(e){ //action when magnified image is clicked on
			var $this=$(this)
			var imageinfo=$this.data('$relatedtarget').data('imgshell')
			jQuery.imageMagnify.refreshoffsets($(window), $this.data('$relatedtarget'), imageinfo) //refresh offset positions of original and warped images
			$this.stop().animate({opacity:0, left:imageinfo.attrs.x, top:imageinfo.attrs.y, width:imageinfo.attrs.w, height:imageinfo.attrs.h},  setting.duration,
			function(){
				$this.hide()
				$this.data('$relatedtarget').css({opacity:1}) //reveal original image
			}) //end animate
		}) //end click
	}
};

jQuery.fn.imageMagnify=function(options){
	var $=jQuery
	return this.each(function(){ //return jQuery obj
		var $imgref=$(this)
		if (this.tagName!="IMG")
			return true //skip to next matched element
		if (parseInt($imgref.css('width'))>0 && parseInt($imgref.css('height'))>0 || options.thumbdimensions){ //if image has explicit width/height attrs defined
			jQuery.imageMagnify.magnify($, $imgref, options)
		}
		else if (this.complete){ //account for IE not firing image.onload
			jQuery.imageMagnify.magnify($, $imgref, options)
		}
		else{
			$(this).bind('load', function(){
				jQuery.imageMagnify.magnify($, $imgref, options)
			})
		}
	})
};

jQuery.fn.applyMagnifier=function(options){ //dynamic version of imageMagnify() to apply magnify effect to an image dynamically
	var $=jQuery
	return this.each(function(){ //return jQuery obj
		var $imgref=$(this)
		if (this.tagName!="IMG")
			return true //skip to next matched element

	})

};

//** The following applies the magnify effect to images with class="magnify" and optional "data-magnifyby" and "data-magnifyduration" attrs
//** It also looks for links with attr rel="magnify[targetimageid]" and makes them togglers for that image

jQuery(document).ready(function($){
	var $targets=$('.magnify')
	$targets.each(function(i){
		var $target=$(this)
		var options={}
		if ($target.attr('data-magnifyto'))
			options.magnifyto=parseFloat($target.attr('data-magnifyto'))
		if ($target.attr('data-magnifyby'))
			options.magnifyby=parseFloat($target.attr('data-magnifyby'))
		if ($target.attr('data-magnifyduration'))
			options.duration=parseInt($target.attr('data-magnifyduration'))
		$target.imageMagnify(options)
	})
	var $triggers=$('a[rel^="magnify["]')
	$triggers.each(function(i){
		var $trigger=$(this)
		var targetid=$trigger.attr('rel').match(/\[.+\]/)[0].replace(/[\[\]']/g, '') //parse 'id' from rel='magnify[id]'
		$trigger.data('magnifyimageid', targetid)
		$trigger.click(function(e){
			$('#'+$(this).data('magnifyimageid')).trigger('click.magnify')
			e.preventDefault()
		})
	})
})

<commit_msg>Update jquery.magnifier.js<commit_after>/* jQuery Image Magnify script v1.1
* This notice must stay intact for usage
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code

* Nov 16th, 09 (v1.1): Adds ability to dynamically apply/reapply magnify effect to an image, plus magnify to a specific width in pixels.
* Feb 8th, 11 (v1.11): Fixed bug that caused script to not work in newever versions of jQuery (ie: v1.4.4)
*/

jQuery.noConflict()

jQuery.imageMagnify={
	dsettings: {
		magnifyby: 2, //default increase factor of enlarged image
		duration: 500, //default duration of animation, in millisec
		imgopacity: 0.2 //opacify of original image when enlarged image overlays it
 	},
	cursorcss: 'url(js/magnify.cur), -moz-zoom-in', //Value for CSS's 'cursor' attribute, added to original image
	zIndexcounter: 100,

	refreshoffsets:function($window, $target, warpshell){
		var $offsets=$target.offset()
		var winattrs={x:$window.scrollLeft(), y:$window.scrollTop(), w:$window.width(), h:$window.height()}
		warpshell.attrs.x=$offsets.left //update x position of original image relative to page
		warpshell.attrs.y=$offsets.top
		warpshell.newattrs.x=winattrs.x+winattrs.w/2-warpshell.newattrs.w/2
		warpshell.newattrs.y=winattrs.y+winattrs.h/2-warpshell.newattrs.h/2
		if (warpshell.newattrs.x<winattrs.x+5){ //no space to the left?
			warpshell.newattrs.x=winattrs.x+5
		}
		else if (warpshell.newattrs.x+warpshell.newattrs.w > winattrs.x+winattrs.w){//no space to the right?
			warpshell.newattrs.x=winattrs.x+5
		}
		if (warpshell.newattrs.y<winattrs.y+5){ //no space at the top?
			warpshell.newattrs.y=winattrs.y+5
		}
	},

	magnify:function($, $target, options){
		var setting={} //create blank object to store combined settings
		var setting=jQuery.extend(setting, this.dsettings, options)
		var attrs=(options.thumbdimensions)? {w:options.thumbdimensions[0], h:options.thumbdimensions[1]} : {w:$target.outerWidth(), h:$target.outerHeight()}
		var newattrs={}
		newattrs.w=(setting.magnifyto)? setting.magnifyto : Math.round(attrs.w*setting.magnifyby)
		newattrs.h=(setting.magnifyto)? Math.round(attrs.h*newattrs.w/attrs.w) : Math.round(attrs.h*setting.magnifyby)
		$target.css('cursor', jQuery.imageMagnify.cursorcss)
		if ($target.data('imgshell')){
			$target.data('imgshell').$clone.remove()
			$target.css({opacity:1}).unbind('click.magnify')
		}
		var $clone=$target.clone().css({position:'absolute', left:0, top:0, visibility:'hidden', border:'1px solid #ccc', cursor:'pointer'}).appendTo(document.body)
		$clone.data('$relatedtarget', $target) //save $target image this enlarged image is associated with
		$target.data('imgshell', {$clone:$clone, attrs:attrs, newattrs:newattrs})
		$target.bind('click.magnify', function(e){ //action when original image is clicked on
			var $this=$(this).css({opacity:setting.imgopacity})
			var imageinfo=$this.data('imgshell')
			jQuery.imageMagnify.refreshoffsets($(window), $this, imageinfo) //refresh offset positions of original and warped images
			var $clone=imageinfo.$clone
			$clone.stop().css({zIndex:++jQuery.imageMagnify.zIndexcounter, left:imageinfo.attrs.x, top:imageinfo.attrs.y, width:imageinfo.attrs.w, height:imageinfo.attrs.h, opacity:0, visibility:'visible', display:'block'})
			.animate({opacity:1, left:imageinfo.newattrs.x, top:imageinfo.newattrs.y, width:imageinfo.newattrs.w, height:imageinfo.newattrs.h}, setting.duration,
			function(){ //callback function after warping is complete
				//none added
			}) //end animate
		}) //end click
		$clone.click(function(e){ //action when magnified image is clicked on
			var $this=$(this)
			var imageinfo=$this.data('$relatedtarget').data('imgshell')
			jQuery.imageMagnify.refreshoffsets($(window), $this.data('$relatedtarget'), imageinfo) //refresh offset positions of original and warped images
			$this.stop().animate({opacity:0, left:imageinfo.attrs.x, top:imageinfo.attrs.y, width:imageinfo.attrs.w, height:imageinfo.attrs.h},  setting.duration,
			function(){
				$this.hide()
				$this.data('$relatedtarget').css({opacity:1}) //reveal original image
			}) //end animate
		}) //end click
	}
};

jQuery.fn.imageMagnify=function(options){
	var $=jQuery
	return this.each(function(){ //return jQuery obj
		var $imgref=$(this)
		if (this.tagName!="IMG")
			return true //skip to next matched element
		if (parseInt($imgref.css('width'))>0 && parseInt($imgref.css('height'))>0 || options.thumbdimensions){ //if image has explicit width/height attrs defined
			jQuery.imageMagnify.magnify($, $imgref, options)
		}
		else if (this.complete){ //account for IE not firing image.onload
			jQuery.imageMagnify.magnify($, $imgref, options)
		}
		else{
			$(this).bind('load', function(){
				jQuery.imageMagnify.magnify($, $imgref, options)
			})
		}
	})
};

jQuery.fn.applyMagnifier=function(options){ //dynamic version of imageMagnify() to apply magnify effect to an image dynamically
	var $=jQuery
	return this.each(function(){ //return jQuery obj
		var $imgref=$(this)
		if (this.tagName!="IMG")
			return true //skip to next matched element

	})

};

//** The following applies the magnify effect to images with class="magnify" and optional "data-magnifyby" and "data-magnifyduration" attrs
//** It also looks for links with attr rel="magnify[targetimageid]" and makes them togglers for that image

jQuery(document).ready(function($){
	var $targets=$('.magnify')
	$targets.each(function(i){
		var $target=$(this)
		var options={}
		if ($target.attr('data-magnifyto'))
			options.magnifyto=parseFloat($target.attr('data-magnifyto'))
		if ($target.attr('data-magnifyby'))
			options.magnifyby=parseFloat($target.attr('data-magnifyby'))
		if ($target.attr('data-magnifyduration'))
			options.duration=parseInt($target.attr('data-magnifyduration'))
		$target.imageMagnify(options)
	})
	var $triggers=$('a[rel^="magnify["]')
	$triggers.each(function(i){
		var $trigger=$(this)
		var targetid=$trigger.attr('rel').match(/\[.+\]/)[0].replace(/[\[\]']/g, '') //parse 'id' from rel='magnify[id]'
		$trigger.data('magnifyimageid', targetid)
		$trigger.click(function(e){
			$('#'+$(this).data('magnifyimageid')).trigger('click.magnify')
			e.preventDefault()
		})
	})
})

<|endoftext|>