<commit_before>var Path = require('path');
var ugly = require("uglify-js");
var clean = require("clean-css");
var fs = require('fs');
var jsp = ugly.parser;
var pro = ugly.uglify;
var fexistsSync = fs.existsSync || Path.existsSync;
var mkdirp;
try {
	mkdirp = require('mkdirp');
} catch(e) {}

module.exports = function(view, opts) {
	var $ = view.window.$;
	var settings = {
		minify: opts.settings.minify == null || opts.settings.minify,
		statics: opts.settings.statics || process.cwd() + '/public',
		viewmtime: view.mtime
	}
	processTags('script', 'src', concatenateJS, $, settings);
	processTags('link', 'href', concatenateCSS, $, settings);
};

function processTags(tag, att, minfun, $, settings) {
	var files = {};
	$(":root > head > " + tag + '[notemplate\\:minify]').each(function() {
		if (settings.minify) {
			var src = $(this).attr(att);
			var dst = $(this).attr("notemplate:minify");
			var list = files[dst] || {sources: [], classes: [], atts: {}};
			list.sources.push(src);
			list.classes.push($(this).attr('class'));
			for (var i=0, len = this.attributes.length; i < len; i++) {
				var item = this.attributes.item(i);
				if (item.name && item.name.indexOf('notemplate:') == 0 && item.name.indexOf('notemplate:minify') < 0) list.atts[item.name] = item.value;
			}
			if (!files[dst]) files[dst] = list;
		} else {
			$(this).get(0).attributes.removeNamedItem('notemplate:minify');
		}
	});
	if (settings.minify) {
		for (var dst in files) {
			var lists = files[dst];
			if (!minified(settings.viewmtime, settings.statics, dst, lists.sources)) {
				// ensures dst dir exists
				var dirdst = Path.dirname(Path.join(settings.statics, dst));
				if (!fexistsSync(dirdst)) {
					if (!mkdirp) throw new Error("No such directory: " + dirdst + "\nInstall mkdirp to automatically create one.");
					mkdirp.sync(dirdst);
				}
				minfun(settings.statics, dst, lists.sources, settings.minify);
			}
			var nodes = $(tag+'[notemplate\\:minify="'+dst+'"]');
			var last = nodes.last();
			nodes.slice(0, -1).remove();
			last.removeAttr('notemplate:minify');
			last.attr(att, dst);
			last.addClass(lists.classes.join(' '));
			for (var name in lists.atts) {
				last.attr(name, lists.atts[name]);
			}
		}
	}
}

function minified(viewmtime, public, dst, sources) {
	// return true if dst exists has been modified after all files
	var dst = Path.join(public, dst);
	if (!fexistsSync(dst)) return false;
	var dstTime = fs.statSync(dst).mtime.getTime();
	var tmplTime = viewmtime.getTime();
	if (tmplTime > dstTime) return false;
	return sources.every(function(src) {
		var src = Path.join(public, src);
		if (!fexistsSync(src)) {
			console.error("Cannot check if missing file is minified :", src);
			return false;
		}
		if (fs.statSync(src).mtime.getTime() > dstTime) return false;
		return true;
	});
}

function concatenateJS(public, dst, sources, minify) {
	var dst = Path.join(public, dst);
	var fd = fs.openSync(dst, 'w');
	sources.forEach(function(src) {
		var src = Path.join(public, src);
		var buf = fs.readFileSync(src);
		if (buf == null) return console.error("Cannot minify empty file :", src);
		if (minify != "cat") {
			var ast = jsp.parse(buf.toString());
			ast = pro.ast_mangle(ast);
			ast = pro.ast_squeeze(ast);
			buf = pro.gen_code(ast);
		}
		fs.writeSync(fd, buf + ";\n");
	});
	fs.closeSync(fd);
}

function concatenateCSS(public, dst, sources, minify) {
	var dst = Path.join(public, dst);
	var fd = fs.openSync(dst, 'w');
	sources.forEach(function(src) {
		var src = Path.join(public, src);
		var buf = cssImportRule(src, dst);
		if (minify != "cat") {
			buf = clean.process(buf, {keepSpecialComments:0});
		}
		fs.writeSync(fd, buf + "\n");
	});
	fs.closeSync(fd);
}

function fixRelativePaths(src, dst, text) {
	var srcDir = Path.dirname(src);
	var dstDir = Path.dirname(dst);
	var relativePath = Path.relative(Path.dirname(dst), Path.dirname(src));
	if (!relativePath) return text;
	var text = text.replace(/(url\(["'])([^"']*)(["']\))|(@import\s+(?:url\()?["'])([^"']*)(["'])(?:\))?/gm, function(match, p1, p2, p3, p4, p5, p6, offset, s) {
		var left = p1 || p4;
		var inside = p2 || p5;
		if (!/^\s*data:/.test(inside)) inside = Path.join(relativePath, inside);
		var right = p3 || p6;
		return left + inside + right;
	});
	return text;
}

function cssImportRule(src, dst) {
	var text = fs.readFileSync(src, 'utf8');
	if (text == null) return "";
	text = fixRelativePaths(src, dst, text);

	return text.replace(/^\s*@import\s+(?:url\()?["']([^"']*)["'](?:\))?;?/gm, function(match, p1, offset, s) {
		var newsrc = Path.join(Path.dirname(dst), p1);
		return cssImportRule(newsrc, dst);
	});
}
<commit_msg>Extend regexp for non-relative url<commit_after>var Path = require('path');
var ugly = require("uglify-js");
var clean = require("clean-css");
var fs = require('fs');
var jsp = ugly.parser;
var pro = ugly.uglify;
var fexistsSync = fs.existsSync || Path.existsSync;
var mkdirp;
try {
	mkdirp = require('mkdirp');
} catch(e) {}

module.exports = function(view, opts) {
	var $ = view.window.$;
	var settings = {
		minify: opts.settings.minify == null || opts.settings.minify,
		statics: opts.settings.statics || process.cwd() + '/public',
		viewmtime: view.mtime
	}
	processTags('script', 'src', concatenateJS, $, settings);
	processTags('link', 'href', concatenateCSS, $, settings);
};

function processTags(tag, att, minfun, $, settings) {
	var files = {};
	$(":root > head > " + tag + '[notemplate\\:minify]').each(function() {
		if (settings.minify) {
			var src = $(this).attr(att);
			var dst = $(this).attr("notemplate:minify");
			var list = files[dst] || {sources: [], classes: [], atts: {}};
			list.sources.push(src);
			list.classes.push($(this).attr('class'));
			for (var i=0, len = this.attributes.length; i < len; i++) {
				var item = this.attributes.item(i);
				if (item.name && item.name.indexOf('notemplate:') == 0 && item.name.indexOf('notemplate:minify') < 0) list.atts[item.name] = item.value;
			}
			if (!files[dst]) files[dst] = list;
		} else {
			$(this).get(0).attributes.removeNamedItem('notemplate:minify');
		}
	});
	if (settings.minify) {
		for (var dst in files) {
			var lists = files[dst];
			if (!minified(settings.viewmtime, settings.statics, dst, lists.sources)) {
				// ensures dst dir exists
				var dirdst = Path.dirname(Path.join(settings.statics, dst));
				if (!fexistsSync(dirdst)) {
					if (!mkdirp) throw new Error("No such directory: " + dirdst + "\nInstall mkdirp to automatically create one.");
					mkdirp.sync(dirdst);
				}
				minfun(settings.statics, dst, lists.sources, settings.minify);
			}
			var nodes = $(tag+'[notemplate\\:minify="'+dst+'"]');
			var last = nodes.last();
			nodes.slice(0, -1).remove();
			last.removeAttr('notemplate:minify');
			last.attr(att, dst);
			last.addClass(lists.classes.join(' '));
			for (var name in lists.atts) {
				last.attr(name, lists.atts[name]);
			}
		}
	}
}

function minified(viewmtime, public, dst, sources) {
	// return true if dst exists has been modified after all files
	var dst = Path.join(public, dst);
	if (!fexistsSync(dst)) return false;
	var dstTime = fs.statSync(dst).mtime.getTime();
	var tmplTime = viewmtime.getTime();
	if (tmplTime > dstTime) return false;
	return sources.every(function(src) {
		var src = Path.join(public, src);
		if (!fexistsSync(src)) {
			console.error("Cannot check if missing file is minified :", src);
			return false;
		}
		if (fs.statSync(src).mtime.getTime() > dstTime) return false;
		return true;
	});
}

function concatenateJS(public, dst, sources, minify) {
	var dst = Path.join(public, dst);
	var fd = fs.openSync(dst, 'w');
	sources.forEach(function(src) {
		var src = Path.join(public, src);
		var buf = fs.readFileSync(src);
		if (buf == null) return console.error("Cannot minify empty file :", src);
		if (minify != "cat") {
			var ast = jsp.parse(buf.toString());
			ast = pro.ast_mangle(ast);
			ast = pro.ast_squeeze(ast);
			buf = pro.gen_code(ast);
		}
		fs.writeSync(fd, buf + ";\n");
	});
	fs.closeSync(fd);
}

function concatenateCSS(public, dst, sources, minify) {
	var dst = Path.join(public, dst);
	var fd = fs.openSync(dst, 'w');
	sources.forEach(function(src) {
		var src = Path.join(public, src);
		var buf = cssImportRule(src, dst);
		if (minify != "cat") {
			buf = clean.process(buf, {keepSpecialComments:0});
		}
		fs.writeSync(fd, buf + "\n");
	});
	fs.closeSync(fd);
}

function fixRelativePaths(src, dst, text) {
	var srcDir = Path.dirname(src);
	var dstDir = Path.dirname(dst);
	var relativePath = Path.relative(Path.dirname(dst), Path.dirname(src));
	if (!relativePath) return text;
	var text = text.replace(/(url\(["'])([^"']*)(["']\))|(@import\s+(?:url\()?["'])([^"']*)(["'])(?:\))?/gm, function(match, p1, p2, p3, p4, p5, p6, offset, s) {
		var left = p1 || p4;
		var inside = p2 || p5;
		if (!/^\s*(data:|https?:\/\/|\/\/)/.test(inside)) inside = Path.join(relativePath, inside);
		var right = p3 || p6;
		return left + inside + right;
	});
	return text;
}

function cssImportRule(src, dst) {
	var text = fs.readFileSync(src, 'utf8');
	if (text == null) return "";
	text = fixRelativePaths(src, dst, text);

	return text.replace(/^\s*@import\s+(?:url\()?["']([^"']*)["'](?:\))?;?/gm, function(match, p1, offset, s) {
		var newsrc = Path.join(Path.dirname(dst), p1);
		return cssImportRule(newsrc, dst);
	});
}
<|endoftext|>


<commit_before>/* eslint no-var: 0 */
var command = require("./command");
var packageJson = require("./../package.json");
var webpackConfig = require("./../webpack.config");
var utils = require("./utils");

/*------ Update package.json ------*/

var json = utils.getPropertiesFromObj(packageJson,[
    "dependencies"
]);

var newJson = {
	"main" : "lib/" + webpackConfig.output.library + ".js",
    "devDependencies": json.dependencies,
    "scripts":{
        "prebuild": "node scripts/prebuild.js",
        "build": "node scripts/build.js production",
        "postbuild": "node scripts/postbuild.js"
    },
	"files": [
		"lib"
	]
};

//todo implement
//command.execute("../../node_modules/.bin/eslint --init")

command.createDir( "../../src",function(){
    command.createDir( "../../test",function(){
        command.createDir( "../../lib",function(){
            command.copyDir( "./scripts", "../../scripts",function(){
	            command.copyDir( "./src", "../../src",function(){
	                command.copyFile( "./webpack.config.js", "../../webpack.config.js",function(){
	                    command.copyFile( "./.babelrc", "../../.babelrc",function(){
		                    command.moveFile( "./.gitignore", "../../.gitignore",function(){
			                    command.copyFile( "./.eslintrc.json", "../../.eslintrc.json",function(){
				                    command.updateJson( "../../package.json", newJson,function(){
					                    command.remove("../../scripts/postinstall.js",function(){
						                    command.remove("../../node_modules/library-boilerplate")
					                    })
				                    });
			                    })
		                    });
	                    });
	                });
                });
            });
        });
    });
});

<commit_msg>gitigonore disabled<commit_after>/* eslint no-var: 0 */
var command = require("./command");
var packageJson = require("./../package.json");
var webpackConfig = require("./../webpack.config");
var utils = require("./utils");

/*------ Update package.json ------*/

var json = utils.getPropertiesFromObj(packageJson,[
    "dependencies"
]);

var newJson = {
	"main" : "lib/" + webpackConfig.output.library + ".js",
    "devDependencies": json.dependencies,
    "scripts":{
        "prebuild": "node scripts/prebuild.js",
        "build": "node scripts/build.js production",
        "postbuild": "node scripts/postbuild.js"
    },
	"files": [
		"lib"
	]
};

//todo implement
//command.execute("../../node_modules/.bin/eslint --init")

command.createDir( "../../src",function(){
    command.createDir( "../../test",function(){
        command.createDir( "../../lib",function(){
            command.copyDir( "./scripts", "../../scripts",function(){
	            command.copyDir( "./src", "../../src",function(){
	                command.copyFile( "./webpack.config.js", "../../webpack.config.js",function(){
	                    command.copyFile( "./.babelrc", "../../.babelrc",function(){
                            command.copyFile( "./.eslintrc.json", "../../.eslintrc.json",function(){
                                command.updateJson( "../../package.json", newJson,function(){
                                    command.remove("../../scripts/postinstall.js",function(){
                                        command.remove("../../node_modules/library-boilerplate")
                                    })
                                });
                            })
	                    });
	                });
                });
            });
        });
    });
});

/*command.copyFile( "./.gitignore", "../../.gitignore",function(){
    command.copyFile( "./.eslintrc.json", "../../.eslintrc.json",function(){
        command.updateJson( "../../package.json", newJson,function(){
            command.remove("../../scripts/postinstall.js",function(){
                command.remove("../../node_modules/library-boilerplate")
            })
        });
    })
});*/

<|endoftext|>


<commit_before>var async = require('async');
var expressUtils = require('express/lib/utils');
var contextMiddleware = require('./lib/contextMiddleware');

var context = module.exports;

/**
 * The init() hook.
 */
context.init = function(application, callback) {
  // Load all contexts.
  var Context = this.application.type('context');
  Context.list({}, function(err, contexts) {
    application.application.use(contextMiddleware(application));
    callback();
  });
};

/**
 * The permission() hook.
 */
context.permission = function(permissions, callback) {
  var newPermissions = {};

  newPermissions['manage-contexts'] = {
    title: 'Manage contexts',
    description: 'List, create and edit contexts.'
  };

  callback(null, newPermissions);
};

/**
 * The type() hook.
 */
context.type = function(types, callback) {
  var newTypes = {};

  newTypes['context'] = {
    title: 'Context',
    description: 'Contexts are set of conditions that results in reactions.',
    fields: {
      name: {
        title: 'Name',
        type: 'text',
      },
      title: {
        title: 'Title',
        type: 'text',
      },
      conditions: {
        title: 'Conditions',
        type: 'reference',
        reference: {
          type: 'contextCondition',
          multiple: true,
          inline: true,
          object: true
        }
      },
      reactions: {
        title: 'Reactions',
        type: 'reference',
        reference: {
          type: 'contextReaction',
          multiple: true,
          inline: true,
          object: true
        }
      }
    },
    access: {
      'list': 'manage-contexts',
      'load': 'manage-contexts',
      'add': 'manage-contexts',
      'edit': 'manage-contexts',
      'delete': 'manage-contexts'
    },
    methods: {
      execute: function(request, response, callback) {
        var self = this;

        // Call callback bellow on the first conditionType that pass.
        // @todo: Eventually we may want to add an operator and also allow OR
        // and ANDs.
        this.conditions = this.conditions || {};
        async.detect(Object.keys(this.conditions), function(conditionTypeName, next) {
          self.application.load('contextConditionType', conditionTypeName, function(err, conditionType) {
            conditionType.check(request, self.conditions[conditionTypeName], function(match) {
              next(match);
            });
          });
        }, function(result) {
          if (!result) {
            return callback(false);
          }
          self.reactions = self.reactions || {};
          async.each(Object.keys(self.reactions), function(reactionTypeName, next) {
            self.application.load('contextReactionType', reactionTypeName, function(err, reactionType) {
              reactionType.react(request, response, self.reactions[reactionTypeName], function(err) {
                next(err);
              });
            });
          }, function() {
            callback(true);
          });
        });
      }
    }
  };

  newTypes['contextCondition'] = {
    title: 'Context condition',
    description: 'Conditions that form contexts.',
    standalone: false,
    polymorphic: true,
    access: {
      'list': 'manage-contexts',
      'load': 'manage-contexts',
      'add': 'manage-contexts',
      'edit': 'manage-contexts',
      'delete': 'manage-contexts'
    }
  };

  newTypes['contextReaction'] = {
    title: 'Context reaction',
    description: 'Reactions a context can result on.',
    standalone: false,
    polymorphic: true,
    access: {
      'list': 'manage-contexts',
      'load': 'manage-contexts',
      'add': 'manage-contexts',
      'edit': 'manage-contexts',
      'delete': 'manage-contexts'
    }
  };

  callback(null, newTypes);
};

/**
 * The context() hook.
 */
context.context = function(contexts, callback) {
  var newContexts = {};

  newContexts['global'] = {
    title: 'Global',
    description: 'Application wide context.',
    weight: -10,
    conditions: {
      siteWide: true
    },
    reactions: {
      theme: 'default',
      layout: 'one-column',
      panel: {
        'navbar-header': [{
          name: 'brand',
          weight: 0
        }],
        'navbar-left': [{
          name: 'navigation-main',
          weight: 0
        }],
        'footer': [{
          name: 'powered-by',
          weight: 0
        }]
      }
    }
  };

  callback(null, newContexts);
};

/**
 * The contextConditionType() hook.
 */
context.contextConditionType = function(conditionTypes, callback) {
  var newConditionTypes = {};

  newConditionTypes['siteWide'] = {
    title: 'Site wide',
    standalone: false,
    fields: {
      // @todo: this may not need an operator or no field at all.
      operator: {
        title: 'Operator',
        type: 'text'
      },
      value: {
        title: 'Value',
        type: 'boolean'
      }
    },
    check: function(request, value, callback) {
      callback(value);
    }
  };

  newConditionTypes['path'] = {
    title: 'Path',
    standalone: false,
    fields: {
      operator: {
        title: 'Operator',
        type: 'text'
      },
      value: {
        title: 'Value',
        type: 'text'
      }
    },
    check: function(request, urls, callback) {
      // Use express regex to match URL.
      var regex = expressUtils.pathRegexp(urls);
      async.detect(urls, function(url, next) {
        next(regex.exec(request.url));
      }, function(result) {
        callback(result !== undefined);
      });
    }
  };

  callback(null, newConditionTypes);
};

/**
 * The contextReactionType() hook.
 */
context.contextReactionType = function(reactionTypes, callback) {
  var newReactionTypes = {};

  newReactionTypes['addCSS'] = {
    title: 'Add CSS',
    description: 'Add a CSS file.',
    standalone: false,
    fields: {
      styles: {
        title: 'Styles',
        description: 'Styles to add.',
        type: 'text'
      }
    },
    react: function(request, response, styles, callback) {
      response.payload.styles = response.payload.styles ? response.payload.styles.merge(styles) : styles;
      callback();
    }
  };

  newReactionTypes['addJS'] = {
    title: 'Add JavaScript',
    description: 'Add a JavaScript file.',
    standalone: false,
    fields: {
      scripts: {
        title: 'Scripts',
        description: 'Scripts to add.',
        type: 'text'
      }
    },
    react: function(request, response, scripts, callback) {
      response.payload.scripts = response.payload.scripts ? response.payload.scripts.merge(scripts) : scripts;
      callback();
    }
  };

  callback(null, newReactionTypes);
};
<commit_msg>Adding "form titles" to context condition and reaction types.<commit_after>var async = require('async');
var expressUtils = require('express/lib/utils');
var contextMiddleware = require('./lib/contextMiddleware');

var context = module.exports;

/**
 * The init() hook.
 */
context.init = function(application, callback) {
  // Load all contexts.
  var Context = this.application.type('context');
  Context.list({}, function(err, contexts) {
    application.application.use(contextMiddleware(application));
    callback();
  });
};

/**
 * The permission() hook.
 */
context.permission = function(permissions, callback) {
  var newPermissions = {};

  newPermissions['manage-contexts'] = {
    title: 'Manage contexts',
    description: 'List, create and edit contexts.'
  };

  callback(null, newPermissions);
};

/**
 * The type() hook.
 */
context.type = function(types, callback) {
  var newTypes = {};

  newTypes['context'] = {
    title: 'Context',
    description: 'Contexts are set of conditions that results in reactions.',
    fields: {
      name: {
        title: 'Name',
        type: 'text',
      },
      title: {
        title: 'Title',
        type: 'text',
      },
      conditions: {
        title: 'Conditions',
        type: 'reference',
        reference: {
          type: 'contextCondition',
          multiple: true,
          inline: true,
          object: true
        }
      },
      reactions: {
        title: 'Reactions',
        type: 'reference',
        reference: {
          type: 'contextReaction',
          multiple: true,
          inline: true,
          object: true
        }
      }
    },
    access: {
      'list': 'manage-contexts',
      'load': 'manage-contexts',
      'add': 'manage-contexts',
      'edit': 'manage-contexts',
      'delete': 'manage-contexts'
    },
    methods: {
      execute: function(request, response, callback) {
        var self = this;

        // Call callback bellow on the first conditionType that pass.
        // @todo: Eventually we may want to add an operator and also allow OR
        // and ANDs.
        this.conditions = this.conditions || {};
        async.detect(Object.keys(this.conditions), function(conditionTypeName, next) {
          self.application.load('contextConditionType', conditionTypeName, function(err, conditionType) {
            conditionType.check(request, self.conditions[conditionTypeName], function(match) {
              next(match);
            });
          });
        }, function(result) {
          if (!result) {
            return callback(false);
          }
          self.reactions = self.reactions || {};
          async.each(Object.keys(self.reactions), function(reactionTypeName, next) {
            self.application.load('contextReactionType', reactionTypeName, function(err, reactionType) {
              reactionType.react(request, response, self.reactions[reactionTypeName], function(err) {
                next(err);
              });
            });
          }, function() {
            callback(true);
          });
        });
      }
    }
  };

  newTypes['contextCondition'] = {
    title: 'Context condition',
    formTitle: 'Condition',
    description: 'Conditions that form contexts.',
    standalone: false,
    polymorphic: true,
    access: {
      'list': 'manage-contexts',
      'load': 'manage-contexts',
      'add': 'manage-contexts',
      'edit': 'manage-contexts',
      'delete': 'manage-contexts'
    }
  };

  newTypes['contextReaction'] = {
    title: 'Context reaction',
    formTitle: 'Reaction',
    description: 'Reactions a context can result on.',
    standalone: false,
    polymorphic: true,
    access: {
      'list': 'manage-contexts',
      'load': 'manage-contexts',
      'add': 'manage-contexts',
      'edit': 'manage-contexts',
      'delete': 'manage-contexts'
    }
  };

  callback(null, newTypes);
};

/**
 * The context() hook.
 */
context.context = function(contexts, callback) {
  var newContexts = {};

  newContexts['global'] = {
    title: 'Global',
    description: 'Application wide context.',
    weight: -10,
    conditions: {
      siteWide: true
    },
    reactions: {
      theme: 'default',
      layout: 'one-column',
      panel: {
        'navbar-header': [{
          name: 'brand',
          weight: 0
        }],
        'navbar-left': [{
          name: 'navigation-main',
          weight: 0
        }],
        'footer': [{
          name: 'powered-by',
          weight: 0
        }]
      }
    }
  };

  callback(null, newContexts);
};

/**
 * The contextConditionType() hook.
 */
context.contextConditionType = function(conditionTypes, callback) {
  var newConditionTypes = {};

  newConditionTypes['siteWide'] = {
    title: 'Site wide',
    standalone: false,
    fields: {
      // @todo: this may not need an operator or no field at all.
      operator: {
        title: 'Operator',
        type: 'text'
      },
      value: {
        title: 'Value',
        type: 'boolean'
      }
    },
    check: function(request, value, callback) {
      callback(value);
    }
  };

  newConditionTypes['path'] = {
    title: 'Path',
    standalone: false,
    fields: {
      operator: {
        title: 'Operator',
        type: 'text'
      },
      value: {
        title: 'Value',
        type: 'text'
      }
    },
    check: function(request, urls, callback) {
      // Use express regex to match URL.
      var regex = expressUtils.pathRegexp(urls);
      async.detect(urls, function(url, next) {
        next(regex.exec(request.url));
      }, function(result) {
        callback(result !== undefined);
      });
    }
  };

  callback(null, newConditionTypes);
};

/**
 * The contextReactionType() hook.
 */
context.contextReactionType = function(reactionTypes, callback) {
  var newReactionTypes = {};

  newReactionTypes['addCSS'] = {
    title: 'Add CSS',
    description: 'Add a CSS file.',
    standalone: false,
    fields: {
      styles: {
        title: 'Styles',
        description: 'Styles to add.',
        type: 'text'
      }
    },
    react: function(request, response, styles, callback) {
      response.payload.styles = response.payload.styles ? response.payload.styles.merge(styles) : styles;
      callback();
    }
  };

  newReactionTypes['addJS'] = {
    title: 'Add JavaScript',
    description: 'Add a JavaScript file.',
    standalone: false,
    fields: {
      scripts: {
        title: 'Scripts',
        description: 'Scripts to add.',
        type: 'text'
      }
    },
    react: function(request, response, scripts, callback) {
      response.payload.scripts = response.payload.scripts ? response.payload.scripts.merge(scripts) : scripts;
      callback();
    }
  };

  callback(null, newReactionTypes);
};
<|endoftext|>


<commit_before>import path from 'path'
import webpack from 'webpack'
import DashboardPlugin from 'webpack-dashboard/plugin'
import webpackBaseConfig from './webpack.config.base.babel'
import config from '../config'

export default {
  ...webpackBaseConfig,

  cache: true,
  devtool: 'eval',

  entry: [
    'react-hot-loader/patch',
    `webpack-hot-middleware/client?path=http://${config.host}:${config.wdsPort}/__webpack_hmr`,
    path.join(process.cwd(), 'src/app/styles/global/app.scss'),
    path.join(process.cwd(), '.noxt/app/app.dev.js'),
  ],

  output: {
    ...webpackBaseConfig.output,
    publicPath: `http://${config.host}:${config.wdsPort}/build/`,
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
  },

  module: {
    ...webpackBaseConfig.module,
    rules: [
      ...webpackBaseConfig.module.rules,
      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true,
        },
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              module: true,
              importLoaders: 1,
              sourceMap: true,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              includePaths: [path.join(process.cwd(), 'src/app/styles')],
            },
          },
        ],
      },
      {
        test: /\.(jpg|png|gif)$/,
        loader: 'file-loader',
      },
    ],
  },

  plugins: [
    ...webpackBaseConfig.plugins,
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('development'),
        BROWSER: JSON.stringify(true),
      },
    }),
    new DashboardPlugin(),
    new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require('../../static/build/react-manifest.json'),
    }),
  ],
}
<commit_msg>remove webpack dashboard<commit_after>import path from 'path'
import webpack from 'webpack'
import webpackBaseConfig from './webpack.config.base.babel'
import config from '../config'

export default {
  ...webpackBaseConfig,

  cache: true,
  devtool: 'eval',

  entry: [
    'react-hot-loader/patch',
    `webpack-hot-middleware/client?path=http://${config.host}:${config.wdsPort}/__webpack_hmr`,
    path.join(process.cwd(), 'src/app/styles/global/app.scss'),
    path.join(process.cwd(), '.noxt/app/app.dev.js'),
  ],

  output: {
    ...webpackBaseConfig.output,
    publicPath: `http://${config.host}:${config.wdsPort}/build/`,
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
  },

  module: {
    ...webpackBaseConfig.module,
    rules: [
      ...webpackBaseConfig.module.rules,
      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true,
        },
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              module: true,
              importLoaders: 1,
              sourceMap: true,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              includePaths: [path.join(process.cwd(), 'src/app/styles')],
            },
          },
        ],
      },
      {
        test: /\.(jpg|png|gif)$/,
        loader: 'file-loader',
      },
    ],
  },

  plugins: [
    ...webpackBaseConfig.plugins,
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('development'),
        BROWSER: JSON.stringify(true),
      },
    }),
    new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require('../../static/build/react-manifest.json'),
    }),
  ],
}
<|endoftext|>


<commit_before>var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">")}function b(p){for(var o=p.firstChild;o;o=o.nextSibling){if(o.nodeName=="CODE"){return o}if(!(o.nodeType==3&&o.nodeValue.match(/\s+/))){break}}}function h(p,o){return Array.prototype.map.call(p.childNodes,function(q){if(q.nodeType==3){return o?q.nodeValue.replace(/\n/g,""):q.nodeValue}if(q.nodeName=="BR"){return"\n"}return h(q,o)}).join("")}function a(q){var p=(q.className+" "+(q.parentNode?q.parentNode.className:"")).split(/\s+/);p=p.map(function(r){return r.replace(/^language-/,"")});for(var o=0;o<p.length;o++){if(e[p[o]]||p[o]=="no-highlight"){return p[o]}}}function c(q){var o=[];(function p(r,s){for(var t=r.firstChild;t;t=t.nextSibling){if(t.nodeType==3){s+=t.nodeValue.length}else{if(t.nodeName=="BR"){s+=1}else{if(t.nodeType==1){o.push({event:"start",offset:s,node:t});s=p(t,s);o.push({event:"stop",offset:s,node:t})}}}}return s})(q,0);return o}function j(x,v,w){var p=0;var y="";var r=[];function t(){if(x.length&&v.length){if(x[0].offset!=v[0].offset){return(x[0].offset<v[0].offset)?x:v}else{return v[0].event=="start"?x:v}}else{return x.length?x:v}}function s(A){function z(B){return" "+B.nodeName+'="'+l(B.value)+'"'}return"<"+A.nodeName+Array.prototype.map.call(A.attributes,z).join("")+">"}while(x.length||v.length){var u=t().splice(0,1)[0];y+=l(w.substr(p,u.offset-p));p=u.offset;if(u.event=="start"){y+=s(u.node);r.push(u.node)}else{if(u.event=="stop"){var o,q=r.length;do{q--;o=r[q];y+=("</"+o.nodeName.toLowerCase()+">")}while(o!=u.node);r.splice(q,1);while(q<r.length){y+=s(r[q]);q++}}}}return y+l(w.substr(p))}function f(r){function o(s){return(s&&s.source)||s}function p(t,s){return RegExp(o(t),"m"+(r.cI?"i":"")+(s?"g":""))}function q(z,x){if(z.compiled){return}z.compiled=true;var u=[];if(z.k){var s={};function A(B,t){t.split(" ").forEach(function(C){var D=C.split("|");s[D[0]]=[B,D[1]?Number(D[1]):1];u.push(D[0])})}z.lR=p(z.l||hljs.IR+"(?!\\.)",true);if(typeof z.k=="string"){A("keyword",z.k)}else{for(var y in z.k){if(!z.k.hasOwnProperty(y)){continue}A(y,z.k[y])}}z.k=s}if(x){if(z.bWK){z.b="\\b("+u.join("|")+")\\b(?!\\.)\\s*"}z.bR=p(z.b?z.b:"\\B|\\b");if(!z.e&&!z.eW){z.e="\\B|\\b"}if(z.e){z.eR=p(z.e)}z.tE=o(z.e)||"";if(z.eW&&x.tE){z.tE+=(z.e?"|":"")+x.tE}}if(z.i){z.iR=p(z.i)}if(z.r===undefined){z.r=1}if(!z.c){z.c=[]}for(var w=0;w<z.c.length;w++){if(z.c[w]=="self"){z.c[w]=z}q(z.c[w],z)}if(z.starts){q(z.starts,x)}var v=[];for(var w=0;w<z.c.length;w++){v.push(o(z.c[w].b))}if(z.tE){v.push(o(z.tE))}if(z.i){v.push(o(z.i))}z.t=v.length?p(v.join("|"),true):{exec:function(t){return null}}}q(r)}function d(E,F,C){function o(r,N){for(var M=0;M<N.c.length;M++){var L=N.c[M].bR.exec(r);if(L&&L.index==0){return N.c[M]}}}function s(L,r){if(L.e&&L.eR.test(r)){return L}if(L.eW){return s(L.parent,r)}}function t(r,L){return !C&&L.i&&L.iR.test(r)}function y(M,r){var L=G.cI?r[0].toLowerCase():r[0];return M.k.hasOwnProperty(L)&&M.k[L]}function H(){var L=l(w);if(!A.k){return L}var r="";var O=0;A.lR.lastIndex=0;var M=A.lR.exec(L);while(M){r+=L.substr(O,M.index-O);var N=y(A,M);if(N){v+=N[1];r+=''+M[0]+""}else{r+=M[0]}O=A.lR.lastIndex;M=A.lR.exec(L)}return r+L.substr(O)}function z(){if(A.sL&&!e[A.sL]){return l(w)}var r=A.sL?d(A.sL,w):g(w);if(A.r>0){v+=r.keyword_count;B+=r.r}return''+r.value+""}function K(){return A.sL!==undefined?z():H()}function J(M,r){var L=M.cN?'':"";if(M.rB){x+=L;w=""}else{if(M.eB){x+=l(r)+L;w=""}else{x+=L;w=r}}A=Object.create(M,{parent:{value:A}})}function D(L,r){w+=L;if(r===undefined){x+=K();return 0}var N=o(r,A);if(N){x+=K();J(N,r);return N.rB?0:r.length}var O=s(A,r);if(O){var M=A;if(!(M.rE||M.eE)){w+=r}x+=K();do{if(A.cN){x+=""}B+=A.r;A=A.parent}while(A!=O.parent);if(M.eE){x+=l(r)}w="";if(O.starts){J(O.starts,"")}return M.rE?0:r.length}if(t(r,A)){throw new Error('Illegal lexem "'+r+'" for mode "'+(A.cN||"<unnamed>")+'"')}w+=r;return r.length||1}var G=e[E];f(G);var A=G;var w="";var B=0;var v=0;var x="";try{var u,q,p=0;while(true){A.t.lastIndex=p;u=A.t.exec(F);if(!u){break}q=D(F.substr(p,u.index-p),u[0]);p=u.index+q}D(F.substr(p));return{r:B,keyword_count:v,value:x,language:E}}catch(I){if(I.message.indexOf("Illegal")!=-1){return{r:0,keyword_count:0,value:l(F)}}else{throw I}}}function g(s){var o={keyword_count:0,r:0,value:l(s)};var q=o;for(var p in e){if(!e.hasOwnProperty(p)){continue}var r=d(p,s,false);r.language=p;if(r.keyword_count+r.r>q.keyword_count+q.r){q=r}if(r.keyword_count+r.r>o.keyword_count+o.r){q=o;o=r}}if(q.language){o.second_best=q}return o}function i(q,p,o){if(p){q=q.replace(/^((<[^>]+>|\t)+)/gm,function(r,v,u,t){return v.replace(/\t/g,p)})}if(o){q=q.replace(/\n/g,"
")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v,true):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagName("pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.lean=function(a){return{l:"[A-z0-9\\-_]+",k:"_",cI:false,c:[{cN:"lean_keyword",b:"Theorem|Definition|Infix|Notation|Axiom|Variable|Coercion",r:10},{cN:"op",b:":=|→|Π|λ",r:10},{cN:"type",b:"Type",relevence:10},{cN:"metavar",b:"[?]m",relevence:10},a.NM,]}}(hljs);<commit_msg>fix(plugin/highlight): import new highlighter<commit_after>var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">")}function b(p){for(var o=p.firstChild;o;o=o.nextSibling){if(o.nodeName=="CODE"){return o}if(!(o.nodeType==3&&o.nodeValue.match(/\s+/))){break}}}function h(p,o){return Array.prototype.map.call(p.childNodes,function(q){if(q.nodeType==3){return o?q.nodeValue.replace(/\n/g,""):q.nodeValue}if(q.nodeName=="BR"){return"\n"}return h(q,o)}).join("")}function a(q){var p=(q.className+" "+(q.parentNode?q.parentNode.className:"")).split(/\s+/);p=p.map(function(r){return r.replace(/^language-/,"")});for(var o=0;o<p.length;o++){if(e[p[o]]||p[o]=="no-highlight"){return p[o]}}}function c(q){var o=[];(function p(r,s){for(var t=r.firstChild;t;t=t.nextSibling){if(t.nodeType==3){s+=t.nodeValue.length}else{if(t.nodeName=="BR"){s+=1}else{if(t.nodeType==1){o.push({event:"start",offset:s,node:t});s=p(t,s);o.push({event:"stop",offset:s,node:t})}}}}return s})(q,0);return o}function j(x,v,w){var p=0;var y="";var r=[];function t(){if(x.length&&v.length){if(x[0].offset!=v[0].offset){return(x[0].offset<v[0].offset)?x:v}else{return v[0].event=="start"?x:v}}else{return x.length?x:v}}function s(A){function z(B){return" "+B.nodeName+'="'+l(B.value)+'"'}return"<"+A.nodeName+Array.prototype.map.call(A.attributes,z).join("")+">"}while(x.length||v.length){var u=t().splice(0,1)[0];y+=l(w.substr(p,u.offset-p));p=u.offset;if(u.event=="start"){y+=s(u.node);r.push(u.node)}else{if(u.event=="stop"){var o,q=r.length;do{q--;o=r[q];y+=("</"+o.nodeName.toLowerCase()+">")}while(o!=u.node);r.splice(q,1);while(q<r.length){y+=s(r[q]);q++}}}}return y+l(w.substr(p))}function f(r){function o(s){return(s&&s.source)||s}function p(t,s){return RegExp(o(t),"m"+(r.cI?"i":"")+(s?"g":""))}function q(z,x){if(z.compiled){return}z.compiled=true;var u=[];if(z.k){var s={};function A(B,t){t.split(" ").forEach(function(C){var D=C.split("|");s[D[0]]=[B,D[1]?Number(D[1]):1];u.push(D[0])})}z.lR=p(z.l||hljs.IR+"(?!\\.)",true);if(typeof z.k=="string"){A("keyword",z.k)}else{for(var y in z.k){if(!z.k.hasOwnProperty(y)){continue}A(y,z.k[y])}}z.k=s}if(x){if(z.bWK){z.b="\\b("+u.join("|")+")\\b(?!\\.)\\s*"}z.bR=p(z.b?z.b:"\\B|\\b");if(!z.e&&!z.eW){z.e="\\B|\\b"}if(z.e){z.eR=p(z.e)}z.tE=o(z.e)||"";if(z.eW&&x.tE){z.tE+=(z.e?"|":"")+x.tE}}if(z.i){z.iR=p(z.i)}if(z.r===undefined){z.r=1}if(!z.c){z.c=[]}for(var w=0;w<z.c.length;w++){if(z.c[w]=="self"){z.c[w]=z}q(z.c[w],z)}if(z.starts){q(z.starts,x)}var v=[];for(var w=0;w<z.c.length;w++){v.push(o(z.c[w].b))}if(z.tE){v.push(o(z.tE))}if(z.i){v.push(o(z.i))}z.t=v.length?p(v.join("|"),true):{exec:function(t){return null}}}q(r)}function d(E,F,C){function o(r,N){for(var M=0;M<N.c.length;M++){var L=N.c[M].bR.exec(r);if(L&&L.index==0){return N.c[M]}}}function s(L,r){if(L.e&&L.eR.test(r)){return L}if(L.eW){return s(L.parent,r)}}function t(r,L){return !C&&L.i&&L.iR.test(r)}function y(M,r){var L=G.cI?r[0].toLowerCase():r[0];return M.k.hasOwnProperty(L)&&M.k[L]}function H(){var L=l(w);if(!A.k){return L}var r="";var O=0;A.lR.lastIndex=0;var M=A.lR.exec(L);while(M){r+=L.substr(O,M.index-O);var N=y(A,M);if(N){v+=N[1];r+=''+M[0]+""}else{r+=M[0]}O=A.lR.lastIndex;M=A.lR.exec(L)}return r+L.substr(O)}function z(){if(A.sL&&!e[A.sL]){return l(w)}var r=A.sL?d(A.sL,w):g(w);if(A.r>0){v+=r.keyword_count;B+=r.r}return''+r.value+""}function K(){return A.sL!==undefined?z():H()}function J(M,r){var L=M.cN?'':"";if(M.rB){x+=L;w=""}else{if(M.eB){x+=l(r)+L;w=""}else{x+=L;w=r}}A=Object.create(M,{parent:{value:A}})}function D(L,r){w+=L;if(r===undefined){x+=K();return 0}var N=o(r,A);if(N){x+=K();J(N,r);return N.rB?0:r.length}var O=s(A,r);if(O){var M=A;if(!(M.rE||M.eE)){w+=r}x+=K();do{if(A.cN){x+=""}B+=A.r;A=A.parent}while(A!=O.parent);if(M.eE){x+=l(r)}w="";if(O.starts){J(O.starts,"")}return M.rE?0:r.length}if(t(r,A)){throw new Error('Illegal lexem "'+r+'" for mode "'+(A.cN||"<unnamed>")+'"')}w+=r;return r.length||1}var G=e[E];f(G);var A=G;var w="";var B=0;var v=0;var x="";try{var u,q,p=0;while(true){A.t.lastIndex=p;u=A.t.exec(F);if(!u){break}q=D(F.substr(p,u.index-p),u[0]);p=u.index+q}D(F.substr(p));return{r:B,keyword_count:v,value:x,language:E}}catch(I){if(I.message.indexOf("Illegal")!=-1){return{r:0,keyword_count:0,value:l(F)}}else{throw I}}}function g(s){var o={keyword_count:0,r:0,value:l(s)};var q=o;for(var p in e){if(!e.hasOwnProperty(p)){continue}var r=d(p,s,false);r.language=p;if(r.keyword_count+r.r>q.keyword_count+q.r){q=r}if(r.keyword_count+r.r>o.keyword_count+o.r){q=o;o=r}}if(q.language){o.second_best=q}return o}function i(q,p,o){if(p){q=q.replace(/^((<[^>]+>|\t)+)/gm,function(r,v,u,t){return v.replace(/\t/g,p)})}if(o){q=q.replace(/\n/g,"
")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v,true):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagName("pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.lean=function(a){return{l:"[A-z0-9\\-_]+",k:"_",cI:false,c:[{cN:"lean_keyword",b:"Theorem|Definition|Infix|Notation|Axiom|Variable|Coercion",r:90},{cN:"op",b:":=|→|Π|λ",r:10},{cN:"type",b:"Type",relevence:10},{cN:"metavar",b:"[?]m[A-z]+",relevence:10},a.NM,]}}(hljs);hljs.LANGUAGES.smt2=function(a){return{l:"[A-z0-9\\-_]+",cI:false,k:{literal:"true false sin cos tan exp arcsin arccos arctan arctan2 and or not",},c:[{cN:"keyword",b:"set-logic|declare-fun|check-sat|assert|Real|define-ode|exit|forall_t",r:10},{cN:"built_in",b:"d\\/dt",r:10},{cN:"built_in",b:"=|<=|>=|>|<|\\*|\\^|\\+",relevence:0},a.HCM,a.NM,]}}(hljs);<|endoftext|>


<commit_before>var tabs = '';
var news = '';
var team = '';
var stats = '';
var gamelog = '';
var headshot = '';
var playerID = 0;
var playerName = '';
var teamID = 0;
var teamCity = '';
var teamName = '';
var teamWinPercentage = 0;
var teamLossPercentage = 0;
var teamTiePercentage = 0;
var baseURL = 'http://espn.com';

var callsMade = 0;
var numberOfCalls = 3;

items = [];
items[0] = [];
items[0]['a'] = '';
items[0]['h'] = '';
items[0]['s'] = 'ESPN';
items[0]['force_big_header'] = 1;
items[0]['force_no_fold'] = 1;

function ddg_spice_espn_team_query(re) {
    var team = re.sports[0].leagues[0].teams[0];
    console.log(team);

    items[0]['a'] = '
'
                  + '
';
    items[0]['u'] = baseURL;
    items[0]['h'] = team.location + " " + team.name + " (Basketball)";
    nra(items);
}

function ddg_spice_espn(response) {

    var player = response.sports[0].leagues[0].athletes[0];
    var playerTeam = player.competitors[0].team;
    playerID = player.id;
    headshot = player.headshots.gamecast;
    teamID = playerTeam.id;
    teamCity = playerTeam.location;
    teamName = playerTeam.name;

    nrj("/js/spice/espn/basketball/nba/athletes/"
            + player.id + "/news/foo/ddg_spice_espn_news");
    nrj("/js/spice/espn/basketball/nba/teams/"
            + teamID + "/foo/bar/ddg_spice_espn_team");
    nrj("/js/spice/espn/basketball/nba/teams/"
            + teamID + "/events/dates/ddg_spice_espn_events");

    stats = player.stats;
    playerName = player.displayName;
    items[0]['u'] = baseURL + "/nba/player/_/id/" + playerID;
    items[0]['h'] = ''
                  + playerName
                  + ''
                  + ' (Basketball)';

    console.log(player);

    tabs = [ 'news', 'stats', 'gamelog' ];
    tabs = tabs.map(function(s, index, array) {
        return ''
            +  s.charAt(0).toUpperCase() + s.slice(1)
            +  '' + (index == array.length - 1 ? "" : " | ");
    }).join("");

    var playerStats = {
        //'assists'                : 'assists',
        //'athleteStatus'          : 'athleteStatus',
        //'height'                 : 'height',
        //'weight'                 : 'weight',
        //'blocks'                 : 'blocks',
        //'defensiveRebounds'      : 'defensiveRebounds',
        //'doubleDouble'           : 'doubleDouble',
        //'ejections'              : 'ejections',
        //'fieldGoalsMade'         : 'fieldGoalsMade',
        //'fieldGoalsAttempted'    : 'fieldGoalsAttempted',
        //'fouls'                  : 'fouls',
        //'freeThrowsMade'         : 'freeThrowsMade',
        //'freeThrowsAttempted'    : 'freeThrowsAttempted',
        //'gamesStarted'           : 'gamesStarted',
        //'minutes'                : 'minutes',
        //'offensiveRebounds'      : 'offensiveRebounds',
        //'rebounds'               : 'rebounds',
        //'steals'                 : 'steals',
        //'threePointersMade'      : 'threePointersMade',
        //'threePointersAttempted' : 'threePointersAttempted',
        //'tripleDouble'           : 'tripleDouble',
        //'turnovers'              : 'turnovers',
        'points'                 : 'Average Points Per Game',
        'threePointPercentage'   : '3-Point Field Goal Percentage (3P%)',
        'fieldGoalPercentage'    : 'Field Goal Percentage (FG%)',
        'freeThrowPercentage'    : 'Free Throw Percentage (FT%)',
    };

    function prepareStat(display, index, array) {
        stat = (player[display] ? player[display] : stats[display]) + '';
        if (display == 'points') stat = (stat / stats.gamesStarted).toFixed(1) + '';
        else if (display == 'threePointPercentage') stat = ((stat + 0) * 100) + '';
        if (display.indexOf('Percentage') != -1) {
            stat = (stat.split('.')[0].length == 1 ? '0' : '')
                    + (Math.round(stat*10)/10).toFixed(1) + '%';
        }
        display = '
' + playerStats[display] + ':	' + stat + '
';
        return display;
    }

    var statsHTML = Object.keys(playerStats).map(prepareStat).join('');
    var statsTimeFrame = "'" + ((stats.season.year + '').substr(2, 2) - 1)
                       + "-'" + (stats.season.year + '').substr(2, 2);

    stats  = '
'
           + '
'
           + playerName + ' '
           + statsTimeFrame + ' '
           + stats.season.description + ' season statistics:'
           + '
'
           + '
'
           + statsHTML
           + '
'
           + '
';
}

function ddg_spice_espn_events(response) {
    var events = response.sports[0].leagues[0].events;
    console.log(response);
    test = response;
    gamelog = '
'
            + '
The ' + teamCity + ' ' + teamName
            + ' have won ' + teamWinPercentage + '% of their season games.'
            + '

'
            + '	Home		Away	'
            + '
';
    var recentGamesFound = 0;
    for (var i = events.length - 1; i > 0 && recentGamesFound < 5; i--) {
        var date = new Date(events[i].date);
        if (date.getTime() > new Date().getTime() - 24*60*60*1000)
            continue;
        recentGamesFound++;
        var competitors = events[i].competitions[0].competitors;
        date.setMonth(date.getMonth()+1);
        var outcome = '';
        gamelog += '' + date.getUTCMonth() + '/' + date.getUTCDate() + '	';
        competitors.map(function(competitor, index, array) {
            teamDisplayName = competitor.team.location
                            + " " + competitor.team.name
            gamelog += '' + teamDisplayName + '	'
                    +  (index == 0 ? ' vs ' : '	');
            if (index == 1) {
                outcome = competitor.score > array[0].score;
                var win = 'W ';
                var loss = 'L ';
                gamelog += ''
                        +  ''
                        +  (competitor.team.id == teamID ?
                                (outcome ? win : loss)
                                + competitor.score
                                + '-' + array[0].score
                            : (outcome ? loss : win)
                                + array[0].score + '-'
                                + competitor.score)
                        +  '	';
            }
        });
        gamelog += '
';
    }
    gamelog += '

';
    ddg_spice_espn_bind();

}

function ddg_spice_espn_news(response) {
    console.log(response);
    headlines = response.headlines;

    news = '
'
         + ''
         + '
'
         + playerName + ' is an American professional basketball player '
         + 'for the ' + teamCity  + ' ' + teamName + ' (NBA).'
         + '

';

    for (var i = 0; i < 3 && i < headlines.length; i++) {
        var article = headlines[i];
        news += '
' + article.headline + ''
             +  ' (' + article.source + ')
';
    }
    news += '
'
         +  '
';

    ddg_spice_espn_bind();
}

function ddg_spice_espn_team(response) {
    response = response.sports[0].leagues[0].teams[0];
    var record = response.record;
    var stats = response.stats;
    var roster = response.athletes;
    var logo = response.logos.large.href;
    var teamColor = response.color;
    var totalGames = record.wins + record.losses + record.ties;
    teamWinPercentage = Math.floor(record.wins / totalGames * 100);
    teamLossPercentage = Math.floor(record.losses / totalGames * 100);
    teamTiePercentage = 100 - teamWinPercentage - teamLossPercentage;
    console.log(response);

    ddg_spice_espn_bind();
}

function ddg_spice_espn_bind() {
    if (++callsMade != numberOfCalls) return;

    items[0]['a'] = tabs
                  + news
                  + team
                  + stats
                  + gamelog;

	nra(items);

    zci = document.getElementById("zero_click_abstract");
    YAHOO.util.Dom.setStyle(zci, "margin", "4px");
    YAHOO.util.Dom.removeClass(zci, "zero_click_snippet");

    ids = [ "espn_zci_gamelog_link",
            "espn_zci_stats_link",
            "espn_zci_news_link"
          ];

    var bgtabs = [];
    ids.map( function(id) {
        bgtabs.push(document.getElementById(id.replace("_link","")))
    });

    var current_link = document.getElementById("espn_zci_news_link");
    YAHOO.util.Dom.setStyle(current_link, "text-decoration", "underline");

    YAHOO.util.Event.addListener(ids, "click", function(e) {
        YAHOO.util.Dom.setStyle(current_link, "text-decoration", "none");
        current_link = this;
        YAHOO.util.Dom.setStyle(this, "text-decoration", "underline");
        var current_tab = this.id.replace("_link", "");
        bgtabs.map(function(i){i.style.display="none";});
        current_tab = document.getElementById(current_tab);
        current_tab.style.display = "block";

        moreAtLink = YAHOO.util.Dom.getElementsByClassName(
                        "zero_click_more_at_link", "a", zci
                     )[0];

        switch (current_tab.id) {
            case "espn_zci_gamelog":
                moreAtLink.href = baseURL + "/nba/player/gamelog/_/id/"
                                + playerID;
                break;
            case "espn_zci_stats":
                moreAtLink.href = baseURL + "/nba/player/stats/_/id/"
                                + playerID;
                break;
            default:
                moreAtLink.href = baseURL + "/nba/player/_/id/"
                                + playerID;
        }

        e.stopImmediatePropagation();
    });

    YAHOO.util.Event.addListener(ids, "mouseenter", function(e) {
        YAHOO.util.Dom.setStyle(this, 'text-decoration', 'underline');
    });

    YAHOO.util.Event.addListener(ids, "mouseleave", function(e) {
        if (this != current_link) {
            YAHOO.util.Dom.setStyle(this, 'text-decoration', 'none');
        }
    });
}
<commit_msg>point gamelog team links to ESPN<commit_after>var tabs = '';
var news = '';
var team = '';
var stats = '';
var gamelog = '';
var headshot = '';
var playerID = 0;
var playerName = '';
var teamID = 0;
var teamCity = '';
var teamName = '';
var teamWinPercentage = 0;
var teamLossPercentage = 0;
var teamTiePercentage = 0;
var baseURL = 'http://espn.com';

var callsMade = 0;
var numberOfCalls = 3;

items = [];
items[0] = [];
items[0]['a'] = '';
items[0]['h'] = '';
items[0]['s'] = 'ESPN';
items[0]['force_big_header'] = 1;
items[0]['force_no_fold'] = 1;

function ddg_spice_espn_team_query(re) {
    var team = re.sports[0].leagues[0].teams[0];
    console.log(team);

    items[0]['a'] = '
'
                  + '
';
    items[0]['u'] = baseURL;
    items[0]['h'] = team.location + " " + team.name + " (Basketball)";
    nra(items);
}

function ddg_spice_espn(response) {

    var player = response.sports[0].leagues[0].athletes[0];
    var playerTeam = player.competitors[0].team;
    playerID = player.id;
    headshot = player.headshots.gamecast;
    teamID = playerTeam.id;
    teamCity = playerTeam.location;
    teamName = playerTeam.name;

    nrj("/js/spice/espn/basketball/nba/athletes/"
            + player.id + "/news/foo/ddg_spice_espn_news");
    nrj("/js/spice/espn/basketball/nba/teams/"
            + teamID + "/foo/bar/ddg_spice_espn_team");
    nrj("/js/spice/espn/basketball/nba/teams/"
            + teamID + "/events/dates/ddg_spice_espn_events");

    stats = player.stats;
    playerName = player.displayName;
    items[0]['u'] = baseURL + "/nba/player/_/id/" + playerID;
    items[0]['h'] = ''
                  + playerName
                  + ''
                  + ' (Basketball)';

    console.log(player);

    tabs = [ 'news', 'stats', 'gamelog' ];
    tabs = tabs.map(function(s, index, array) {
        return ''
            +  s.charAt(0).toUpperCase() + s.slice(1)
            +  '' + (index == array.length - 1 ? "" : " | ");
    }).join("");

    var playerStats = {
        //'assists'                : 'assists',
        //'athleteStatus'          : 'athleteStatus',
        //'height'                 : 'height',
        //'weight'                 : 'weight',
        //'blocks'                 : 'blocks',
        //'defensiveRebounds'      : 'defensiveRebounds',
        //'doubleDouble'           : 'doubleDouble',
        //'ejections'              : 'ejections',
        //'fieldGoalsMade'         : 'fieldGoalsMade',
        //'fieldGoalsAttempted'    : 'fieldGoalsAttempted',
        //'fouls'                  : 'fouls',
        //'freeThrowsMade'         : 'freeThrowsMade',
        //'freeThrowsAttempted'    : 'freeThrowsAttempted',
        //'gamesStarted'           : 'gamesStarted',
        //'minutes'                : 'minutes',
        //'offensiveRebounds'      : 'offensiveRebounds',
        //'rebounds'               : 'rebounds',
        //'steals'                 : 'steals',
        //'threePointersMade'      : 'threePointersMade',
        //'threePointersAttempted' : 'threePointersAttempted',
        //'tripleDouble'           : 'tripleDouble',
        //'turnovers'              : 'turnovers',
        'points'                 : 'Average Points Per Game',
        'threePointPercentage'   : '3-Point Field Goal Percentage (3P%)',
        'fieldGoalPercentage'    : 'Field Goal Percentage (FG%)',
        'freeThrowPercentage'    : 'Free Throw Percentage (FT%)',
    };

    function prepareStat(display, index, array) {
        stat = (player[display] ? player[display] : stats[display]) + '';
        if (display == 'points') stat = (stat / stats.gamesStarted).toFixed(1) + '';
        else if (display == 'threePointPercentage') stat = ((stat + 0) * 100) + '';
        if (display.indexOf('Percentage') != -1) {
            stat = (stat.split('.')[0].length == 1 ? '0' : '')
                    + (Math.round(stat*10)/10).toFixed(1) + '%';
        }
        display = '
' + playerStats[display] + ':	' + stat + '
';
        return display;
    }

    var statsHTML = Object.keys(playerStats).map(prepareStat).join('');
    var statsTimeFrame = "'" + ((stats.season.year + '').substr(2, 2) - 1)
                       + "-'" + (stats.season.year + '').substr(2, 2);

    stats  = '
'
           + '
'
           + playerName + ' '
           + statsTimeFrame + ' '
           + stats.season.description + ' season statistics:'
           + '
'
           + '
'
           + statsHTML
           + '
'
           + '
';
}

function ddg_spice_espn_events(response) {
    var events = response.sports[0].leagues[0].events;
    console.log(response);
    test = response;
    gamelog = '
'
            + '
The ' + teamCity + ' ' + teamName
            + ' have won ' + teamWinPercentage + '% of their season games.'
            + '

'
            + '	Home		Away	'
            + '
';
    var recentGamesFound = 0;
    for (var i = events.length - 1; i > 0 && recentGamesFound < 5; i--) {
        var date = new Date(events[i].date);
        if (date.getTime() > new Date().getTime() - 24*60*60*1000)
            continue;
        recentGamesFound++;
        var competitors = events[i].competitions[0].competitors;
        date.setMonth(date.getMonth()+1);
        var outcome = '';
        gamelog += '' + date.getUTCMonth() + '/' + date.getUTCDate() + '	';
        competitors.map(function(competitor, index, array) {
            teamDisplayName = competitor.team.location
                            + " " + competitor.team.name
            var espnTeamLink = teamDisplayName.replace(' ', '').substr(0.3)
                             + '/' + teamDisplayName.replace(' ', '-');
            gamelog += '' + teamDisplayName + '	'
                    +  (index == 0 ? ' vs ' : '	');
            if (index == 1) {
                outcome = competitor.score > array[0].score;
                var win = 'W ';
                var loss = 'L ';
                gamelog += ''
                        +  ''
                        +  (competitor.team.id == teamID ?
                                (outcome ? win : loss)
                                + competitor.score
                                + '-' + array[0].score
                            : (outcome ? loss : win)
                                + array[0].score + '-'
                                + competitor.score)
                        +  '	';
            }
        });
        gamelog += '
';
    }
    gamelog += '

';
    ddg_spice_espn_bind();

}

function ddg_spice_espn_news(response) {
    console.log(response);
    headlines = response.headlines;

    news = '
'
         + ''
         + '
'
         + playerName + ' is an American professional basketball player '
         + 'for the ' + teamCity  + ' ' + teamName + ' (NBA).'
         + '

';

    for (var i = 0; i < 3 && i < headlines.length; i++) {
        var article = headlines[i];
        news += '
' + article.headline + ''
             +  ' (' + article.source + ')
';
    }
    news += '
'
         +  '
';

    ddg_spice_espn_bind();
}

function ddg_spice_espn_team(response) {
    response = response.sports[0].leagues[0].teams[0];
    var record = response.record;
    var stats = response.stats;
    var roster = response.athletes;
    var logo = response.logos.large.href;
    var teamColor = response.color;
    var totalGames = record.wins + record.losses + record.ties;
    teamWinPercentage = Math.floor(record.wins / totalGames * 100);
    teamLossPercentage = Math.floor(record.losses / totalGames * 100);
    teamTiePercentage = 100 - teamWinPercentage - teamLossPercentage;
    console.log(response);

    ddg_spice_espn_bind();
}

function ddg_spice_espn_bind() {
    if (++callsMade != numberOfCalls) return;

    items[0]['a'] = tabs
                  + news
                  + team
                  + stats
                  + gamelog;

	nra(items);

    zci = document.getElementById("zero_click_abstract");
    YAHOO.util.Dom.setStyle(zci, "margin", "4px");
    YAHOO.util.Dom.removeClass(zci, "zero_click_snippet");

    ids = [ "espn_zci_gamelog_link",
            "espn_zci_stats_link",
            "espn_zci_news_link"
          ];

    var bgtabs = [];
    ids.map( function(id) {
        bgtabs.push(document.getElementById(id.replace("_link","")))
    });

    var current_link = document.getElementById("espn_zci_news_link");
    YAHOO.util.Dom.setStyle(current_link, "text-decoration", "underline");

    YAHOO.util.Event.addListener(ids, "click", function(e) {
        YAHOO.util.Dom.setStyle(current_link, "text-decoration", "none");
        current_link = this;
        YAHOO.util.Dom.setStyle(this, "text-decoration", "underline");
        var current_tab = this.id.replace("_link", "");
        bgtabs.map(function(i){i.style.display="none";});
        current_tab = document.getElementById(current_tab);
        current_tab.style.display = "block";

        moreAtLink = YAHOO.util.Dom.getElementsByClassName(
                        "zero_click_more_at_link", "a", zci
                     )[0];

        switch (current_tab.id) {
            case "espn_zci_gamelog":
                moreAtLink.href = baseURL + "/nba/player/gamelog/_/id/"
                                + playerID;
                break;
            case "espn_zci_stats":
                moreAtLink.href = baseURL + "/nba/player/stats/_/id/"
                                + playerID;
                break;
            default:
                moreAtLink.href = baseURL + "/nba/player/_/id/"
                                + playerID;
        }

        e.stopImmediatePropagation();
    });

    YAHOO.util.Event.addListener(ids, "mouseenter", function(e) {
        YAHOO.util.Dom.setStyle(this, 'text-decoration', 'underline');
    });

    YAHOO.util.Event.addListener(ids, "mouseleave", function(e) {
        if (this != current_link) {
            YAHOO.util.Dom.setStyle(this, 'text-decoration', 'none');
        }
    });
}
<|endoftext|>


<commit_before>/**
 * humaninput-speechrec.js - HumanInput Clapper Plugin: Adds support detecting clap events like "the clapper" (classic)
 * Copyright (c) 2016, Dan McDougall
 * @link https://github.com/liftoff/HumanInput
 * @license Apache-2.0
 */

(function() {
"use strict";

// Setup getUserMedia
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

// Add ourselves to the default listen events since we won't start listening for claps unless explicitly told to do so (won't be used otherwise)
HumanInput.defaultListenEvents.push('clapper');

var AudioContext = window.AudioContext || window.webkitAudioContext,
    throttleMS = 60, // Only process audio once every throttleMS milliseconds
    ClapperPlugin = function(HI) {
        var self = this;
        self.__name__ = 'ClapperPlugin';
        self.exports = {};
        self.startClapper = function() {
            var handleStream = function(stream) {
                var previous, detectedClap, detectedDoubleClap;
                self.stream = stream;
                self.scriptProcessor.connect(self.context.destination);
                self.analyser.smoothingTimeConstant = 0.4;
                self.analyser.fftSize = 128;
                self.streamSource = self.context.createMediaStreamSource(stream);
                self.streamSource.connect(self.analyser);
                self.analyser.connect(self.scriptProcessor);
                self.scriptProcessor.onaudioprocess = function() {
                    var elapsed, elapsedSinceClap, elapsedSinceDoubleClap, event,
                        now = Date.now();
                    if (!previous) {
                        previous = now;
                        detectedClap = now;
                    }
                    elapsed = now - previous;
                    elapsedSinceClap = now - detectedClap;
                    elapsedSinceDoubleClap = now - detectedDoubleClap;
                    if (elapsed > throttleMS) {
                        self.analyser.getByteFrequencyData(self.freqData);
                        if (elapsedSinceClap >= (throttleMS * 4) && self.freqData.filter(function(amplitude) { return amplitude >= HI.settings.clapThreshold }).length >= 15) {
                            event = 'clap';
                            if (elapsedSinceClap < (throttleMS * 8)) {
                                event = 'doubleclap';
                                detectedDoubleClap = now;
                                if (elapsedSinceDoubleClap < (throttleMS * 12)) {
                                    event = 'applause';
                                }
                            }
                            HI._addDown(event);
                            HI._handleDownEvents();
                            HI._handleSeqEvents();
                            HI._removeDown(event);
                            detectedClap = now;
                        }
                        previous = now;
                    }
                    self.freqData = new Uint8Array(self.analyser.frequencyBinCount);
                }
            };
            self.context = new AudioContext();
            self.scriptProcessor = self.context.createScriptProcessor(1024, 1, 1);
            self.analyser = self.context.createAnalyser();
            self.freqData = new Uint8Array(self.analyser.frequencyBinCount);
            self.log.debug(HI.l('Starting clap detection'));
            self._started = true;
            navigator.getUserMedia({ audio: true }, handleStream, function(e) {
                self.log.error(HI.l('Could not get audio stream'), e);
            });
        };
        self.stopClapper = function() {
            self.log.debug(HI.l('Stopping clap detection'));
            self.stream.getAudioTracks().forEach(function(track) {
                track.stop();
            });
            self.stream.getVideoTracks().forEach(function(track) {
                track.stop();
            });
            self.streamSource.disconnect(self.analyser);
            self.analyser.disconnect(self.scriptProcessor);
            self.scriptProcessor.disconnect(self.context.destination);
            self._started = false;
        };
        return self;
    };

ClapperPlugin.prototype.init = function(HI) {
    var self = this;
    self.log = new HI.logger(HI.settings.logLevel || 'INFO', '[HI Clapper]');
    self.log.debug(HI.l("Initializing Clapper Plugin"), self);
    HI.settings.autostartClapper = HI.settings.autostartClapper || false; // Don't autostart by default
    HI.settings.clapThreshold = HI.settings.clapThreshold || 120;
    HI.settings.autotoggleClapper = HI.settings.autotoggleClapper || true; // Should we stop automatically on page:hidden?
    if (HI.settings.listenEvents.indexOf('clapper') != -1) {
        if (AudioContext) {
            if (HI.settings.autostartClapper) {
                self.startClapper();
            }
            if (HI.settings.autotoggleClapper) {
                HI.on('document:hidden', function() {
                    if (self._started) {
                        self.stopClapper();
                    }
                });
                HI.on('document:visible', function() {
                    if (!self._started && HI.settings.autostartClapper) {
                        self.startClapper();
                    }
                });
            }
        } else { // Disable the clapper functions to ensure no weirdness with document:hidden
            self.startClapper = HI.noop;
            self.stopClapper = HI.noop;
        }
    }
    // Exports (these will be applied to the current instance of HumanInput)
    self.exports.startClapper = self.startClapper;
    self.exports.stopClapper = self.stopClapper;
    return self;
};

HumanInput.plugins.push(ClapperPlugin);

}).call(this);
<commit_msg>Clapper Plugin:  Should be *much* better at discriminating between claps and other (sudden, loud) sounds now thanks to some "magic ratios" I've developed by making my hands red.<commit_after>/**
 * humaninput-speechrec.js - HumanInput Clapper Plugin: Adds support detecting clap events like "the clapper" (classic)
 * Copyright (c) 2016, Dan McDougall
 * @link https://github.com/liftoff/HumanInput
 * @license Apache-2.0
 */

(function() {
"use strict";

// Setup getUserMedia
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

// Add ourselves to the default listen events since we won't start listening for claps unless explicitly told to do so (won't be used otherwise)
HumanInput.defaultListenEvents.push('clapper');

var AudioContext = window.AudioContext || window.webkitAudioContext,
    throttleMS = 60, // Only process audio once every throttleMS milliseconds
    historyLength = 50, // How many samples to keep in the history buffer (50 is about 3 seconds worth)
    sum = function(arr) {
        return arr.reduce(function(a, b) { return a + b; });
    },
    findPeaks = function(arr) {
        // returns the indexes of all the peaks in *arr*
        var indexes = [];
        for (var i = 1; i < arr.length - 1; ++i) {
            if (arr[i-1] < arr[i] && arr[i] > arr[i+1]) {
                indexes.push(i);
            }
        }
        return indexes;
    },
    ClapperPlugin = function(HI) {
        var self = this;
        self.__name__ = 'ClapperPlugin';
        self.exports = {};
        self.history = [];
        self.rollingAvg = [];
        self.calcHistoryAverage = function() {
            // Updates self.rollingAvg with the latest data from self.history so that each item in the array reflects the average amplitude for that chunk of the frequency spectrum
            var i, j, temp = 0;
            for (i=0; i < self.analyser.frequencyBinCount; i++) {
                if (self.history[i]) {
                    for (j=0; j < self.history.length; j++) {
                        temp += self.history[j][i];
                    }
                    self.rollingAvg[i] = temp/self.history.length;
                    temp = 0;
                }
            }
        };
        self.startClapper = function() {
            var handleStream = function(stream) {
                var previous, detectedClap, detectedDoubleClap;
                self.stream = stream;
                self.scriptProcessor.connect(self.context.destination);
                self.analyser.smoothingTimeConstant = 0.4;
                self.analyser.fftSize = 128;
                self.streamSource = self.context.createMediaStreamSource(stream);
                self.streamSource.connect(self.analyser);
                self.analyser.connect(self.scriptProcessor);
                self.scriptProcessor.onaudioprocess = function() {
                    var elapsed, elapsedSinceClap, elapsedSinceDoubleClap, event, peaks, highestPeak, highestPeakIndex, amplitudeIncrease, magicRatio1, magicRatio2,
                        now = Date.now();
                    if (!previous) {
                        previous = now;
                        detectedClap = now;
                    }
                    elapsed = now - previous;
                    elapsedSinceClap = now - detectedClap;
                    elapsedSinceDoubleClap = now - detectedDoubleClap;
                    if (elapsed > throttleMS) {
                        self.freqData = new Uint8Array(self.analyser.frequencyBinCount);
                        self.analyser.getByteFrequencyData(self.freqData);
                        peaks = findPeaks(self.freqData);
                        highestPeakIndex = self.freqData.indexOf(Math.max.apply(null, self.freqData));
                        highestPeak = self.freqData[highestPeakIndex];
                        // Measure the amplitude increase against the rolling average not the previous data set (which can include ramping-up data which messes up our calculations)
                        amplitudeIncrease = self.freqData[highestPeakIndex] - self.rollingAvg[highestPeakIndex];
                        if (elapsedSinceClap >= (throttleMS * 4)) {
                            // Highest peak is right near the beginning of the spectrum for (most) claps:
                            if (highestPeakIndex < 8 && amplitudeIncrease > HI.settings.clapThreshold) {
                                // Sudden large volume change.  Could be a clap...
                                magicRatio1 = sum(self.freqData.slice(0, 10))/sum(self.freqData.slice(10, 20)); // Check the magic ratio
                                magicRatio2 = sum(self.freqData.slice(0, 3))/sum(self.freqData.slice(3, 6)); // Check the 2nd magic ratio
                                // The peak check below is to prevent accidentally capturing computer-generated sounds which usually have a nice solid curve (few peaks if any)
                                if (magicRatio1 < 1.8 && magicRatio2 < 1.4 && peaks.length > 2) {
                                    // Now we're clapping!
                                    event = 'clap';
                                    if (elapsedSinceClap < (throttleMS * 8)) {
                                        event = 'doubleclap';
                                        detectedDoubleClap = now;
                                        if (elapsedSinceDoubleClap < (throttleMS * 12)) {
                                            event = 'applause';
                                        }
                                    }
                                    HI._addDown(event);
                                    HI._handleDownEvents();
                                    HI._handleSeqEvents();
                                    HI._removeDown(event);
                                    detectedClap = now;
                                }
                            }
                        }
                        previous = now;
                        // Only add this data set to this history if it wasn't a clap (so it doesn't poison our averages)
                        if (detectedClap != now) {
                            self.history.push(self.freqData);
                            if (self.history.length > historyLength) {
                                self.history.shift();
                            }
                            self.calcHistoryAverage();
                        }
                    }
                }
            };
            self.context = new AudioContext();
            self.scriptProcessor = self.context.createScriptProcessor(1024, 1, 1);
            self.analyser = self.context.createAnalyser();
            self.freqData = new Uint8Array(self.analyser.frequencyBinCount);
            self.log.debug(HI.l('Starting clap detection'));
            self._started = true;
            navigator.getUserMedia({ audio: true }, handleStream, function(e) {
                self.log.error(HI.l('Could not get audio stream'), e);
            });
        };
        self.stopClapper = function() {
            self.log.debug(HI.l('Stopping clap detection'));
            self.stream.getAudioTracks().forEach(function(track) {
                track.stop();
            });
            self.stream.getVideoTracks().forEach(function(track) {
                track.stop();
            });
            self.streamSource.disconnect(self.analyser);
            self.analyser.disconnect(self.scriptProcessor);
            self.scriptProcessor.disconnect(self.context.destination);
            self._started = false;
        };
        return self;
    };

ClapperPlugin.prototype.init = function(HI) {
    var self = this;
    self.log = new HI.logger(HI.settings.logLevel || 'INFO', '[HI Clapper]');
    self.log.debug(HI.l("Initializing Clapper Plugin"), self);
    HI.settings.autostartClapper = HI.settings.autostartClapper || false; // Don't autostart by default
    HI.settings.clapThreshold = HI.settings.clapThreshold || 130;
    HI.settings.autotoggleClapper = HI.settings.autotoggleClapper || true; // Should we stop automatically on page:hidden?
    if (HI.settings.listenEvents.indexOf('clapper') != -1) {
        if (AudioContext) {
            if (HI.settings.autostartClapper) {
                self.startClapper();
            }
            if (HI.settings.autotoggleClapper) {
                HI.on('document:hidden', function() {
                    if (self._started) {
                        self.stopClapper();
                    }
                });
                HI.on('document:visible', function() {
                    if (!self._started && HI.settings.autostartClapper) {
                        self.startClapper();
                    }
                });
            }
        } else { // Disable the clapper functions to ensure no weirdness with document:hidden
            self.startClapper = HI.noop;
            self.stopClapper = HI.noop;
        }
    }
    // Exports (these will be applied to the current instance of HumanInput)
    self.exports.startClapper = self.startClapper;
    self.exports.stopClapper = self.stopClapper;
    return self;
};

HumanInput.plugins.push(ClapperPlugin);

}).call(this);
<|endoftext|>


<commit_before>module.exports = jsFlowTracker

var debug = require('debug')('bittorrent-tracker:websocket-tracker')
var EventEmitter = require('events').EventEmitter
var hat = require('hat')
var inherits = require('inherits')
var jsFlow = require('./jsFlow')
var Peer = require('simple-peer')
//var Peer = require('jsflow-peer') // No changes yet.. :)

function jsFlowTracker (client, announceUrl, opts) {
  console.log('jsFlowTracker constructor is now running')
	var self=this
	EventEmitter.call(self)

  self.client=client
  self._opts = opts
  self._announceUrl = announceUrl
  self._peers = {} // peers (peer id -> peer)
  self._intervalMs = self.client._intervalMs // use client interval initially
  self._interval = null

  console.log(self);

  jsFlow.onRecievedUserId = function(userId) {
    console.log('userId', userId);
    self._peerID = userId;
  };

  // Starts jsFlow and handles the user ID
  jsFlow.run("31bc728296d8da7e14e132k",{sessionAuthURL: 'http://corslabs.com/jsflow',
                  debugMsg: true});

  jsFlow.addHandler('list', self._onData.bind(self)) // These messages are only sent by the TRACKER

  //Handlers for peer-2-peer WebRTC signalling using jsFlow
  jsFlow.addHandler('webrtc_offer', self._onWebRtcOffer.bind(self)) // only sent from other PEERS
  jsFlow.addHandler('webrtc_answer', self._onWebRtcAnswer.bind(self)) // only sent from other PEERS
  jsFlow.addHandler('webrtc_ice', self._onWebRtcIce.bind(self)) // only sent from other PEERS
}

jsFlowTracker.prototype.announce = function(opts){
  var self=this
  opts.info_hash = self.client._infoHash.toString('base64')
  opts.peer_id = self._peerId
  opts.trackerid = 'tracker'

  self._sendAnnounce(opts)
}

jsFlowTracker.prototype.setInterval= function (intervalMs) {
  var self = this
  clearInterval(self._interval)

  self._intervalMs = intervalMs
  if (intervalMs) {
    // HACK
    var update = self.announce.bind(self, self.client._defaultAnnounceOpts())
    self._interval = setInterval(update, self._intervalMs)
  }
}

jsFlowTracker.prototype._onData = function (payload, from) {
  console.log('Got Data from Tracker!!', payload, from);

  var self = this
  if (!(typeof payload === 'object' && payload !== null)) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  if (payload.info_hash !== self.client._infoHash.toString('base64')) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  var failure = payload['failure reason']
  if (failure) return self.client.emit('warning', new Error(failure))

  var warning = payload['warning message']
  if (warning) self.client.emit('warning', new Error(warning))

  var interval = payload.interval || payload['min interval']
  if (interval && !self._opts.interval && self._intervalMs !== 0) { //TODO: Fix so tracker can set interval (now defaults to 30 min)
  //if(interval) { // ALWAYS use the interval recommended by tracker
    self.setInterval(interval)
  }

  var trackerId = payload['tracker id']
  if (trackerId) {
    // If absent, do not discard previous trackerId value
    self._trackerId = trackerId
  }

  if (payload.complete) {
    self.client.emit('update', {
    announce: self._announceUrl,
    complete: payload.complete,
    incomplete: payload.incomplete
    })
  }

  // Handle received peers
  if (Array.isArray(payload.peers)) {
    payload.peers.forEach(function (peerInfo) { //For all peers we receive - Open a WebRTC peer connection
      var peerId = peerInfo.peerId;

      console.log('Will handle connection for peer: ', peerId);

      var peer = self._peers[peerId] = new Peer({
        initiator: true,
        trickle: true,
        config: self.client._rtcConfig,
        wrtc: self.client._wrtc
      })
      peer.id = peerId

      peer.on('signal', function (signalObject) {
        console.log('GOT SIGNAL, expecting offer/ice', signalObject);
        if(signalObject.candidate) { // The signalling is for ICE
          var params = {
            info_hash: self.client._infoHash.toString('base64'),
            peer_id: self._peerID,
            candidate: signalObject.candidate
          }

          jsFlow.messageUser(peerId, params, 'webrtc_ice');
        }
        else { // The signalling is for an OFFER
          offer = signalObject;
          var params = {
            info_hash: self.client._infoHash.toString('base64'),
            peer_id: self._peerID,
            offer: offer
          }

          jsFlow.messageUser(peerId, params, 'webrtc_offer');
        }
      })
    })
  };
}

jsFlowTracker.prototype._onWebRtcOffer = function (payload, from) {
  var self = this
  if(!self._peers[from]) { //Verify we haven't already received an offer from this user
    var peer = self._peers[from] = new Peer({
      trickle: true,
      config: self.client._rtcConfig,
      wrtc: self.client._wrtc
    })
    peer.id = from

    peer.on('signal', function (signalObject) {
        console.log('GOT SIGNAL, expecting answer/ice', signalObject);
      if(signalObject.candidate) { // The signalling is for ICE
        var params = {
          info_hash: self.client._infoHash.toString('base64'),
          peer_id: self._peerID,
          candidate: signalObject.candidate
        }

        jsFlow.messageUser(from, params, 'webrtc_ice');
      }
      else { // The signalling is for an ANSWER
        answer = signalObject;
        var params = {
          info_hash: self.client._infoHash.toString('base64'),
          peer_id: self._peerID,
          answer: answer
        }

        jsFlow.messageUser(from, params, 'webrtc_answer');
      }
    })

    peer.signal(payload.offer)

    self.client.emit('peer', peer)
  }
  else {
    console.error('Already have peer connection with user: ' + from);
  }
}

jsFlowTracker.prototype._onWebRtcAnswer = function (payload, from) {
  var self = this
  var peer = self._peers[from]
  if(peer) {
    peer.id = from
    peer.signal(payload.answer)
    self.client.emit('peer', peer)
  }
  else {
    console.error('Got answer on peer connection that does not exist, from user: ' + from);
  }
}

jsFlowTracker.prototype._onWebRtcIce = function (payload, from) {
  var self = this
  //TODO: Buffer ICE ?
  console.log('WILL ADD ICE CANDIDATE!!!');
  if(!self._peers[from]) {
    var peer = self._peers[from]

    if(payload.candidate) {
      peer.signal(payload.candidate)
    }
    else {
      console.error('Candidate did not exist as expected in payload', payload);
    }
  }
  else {
    console.error('Candidate refers to a peer not yet created. TODO: Buffer ICE!', payload);
  }
}

jsFlowTracker.prototype._sendAnnounce = function (params) {
  var self = this
  jsFlow.messageUser(params.trackerid, params, 'announce')
}
<commit_msg>Minor fix<commit_after>module.exports = jsFlowTracker

var debug = require('debug')('bittorrent-tracker:websocket-tracker')
var EventEmitter = require('events').EventEmitter
var hat = require('hat')
var inherits = require('inherits')
var jsFlow = require('./jsFlow')
var Peer = require('simple-peer')
//var Peer = require('jsflow-peer') // No changes yet.. :)

function jsFlowTracker (client, announceUrl, opts) {
  console.log('jsFlowTracker constructor is now running')
	var self=this
	EventEmitter.call(self)

  self.client=client
  self._opts = opts
  self._announceUrl = announceUrl
  self._peers = {} // peers (peer id -> peer)
  self._intervalMs = self.client._intervalMs // use client interval initially
  self._interval = null

  console.log(self);

  jsFlow.onRecievedUserId = function(userId) {
    console.log('userId', userId);
    self._peerID = userId;
  };

  // Starts jsFlow and handles the user ID
  jsFlow.run("31bc728296d8da7e14e132k",{sessionAuthURL: 'http://corslabs.com/jsflow',
                  debugMsg: true});

  jsFlow.addHandler('list', self._onData.bind(self)) // These messages are only sent by the TRACKER

  //Handlers for peer-2-peer WebRTC signalling using jsFlow
  jsFlow.addHandler('webrtc_offer', self._onWebRtcOffer.bind(self)) // only sent from other PEERS
  jsFlow.addHandler('webrtc_answer', self._onWebRtcAnswer.bind(self)) // only sent from other PEERS
  jsFlow.addHandler('webrtc_ice', self._onWebRtcIce.bind(self)) // only sent from other PEERS
}

jsFlowTracker.prototype.announce = function(opts){
  var self=this
  opts.info_hash = self.client._infoHash.toString('base64')
  opts.peer_id = self._peerId
  opts.trackerid = 'tracker'

  self._sendAnnounce(opts)
}

jsFlowTracker.prototype.setInterval= function (intervalMs) {
  var self = this
  clearInterval(self._interval)

  self._intervalMs = intervalMs
  if (intervalMs) {
    // HACK
    var update = self.announce.bind(self, self.client._defaultAnnounceOpts())
    self._interval = setInterval(update, self._intervalMs)
  }
}

jsFlowTracker.prototype._onData = function (payload, from) {
  console.log('Got Data from Tracker!!', payload, from);

  var self = this
  if (!(typeof payload === 'object' && payload !== null)) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  if (payload.info_hash !== self.client._infoHash.toString('base64')) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  var failure = payload['failure reason']
  if (failure) return self.client.emit('warning', new Error(failure))

  var warning = payload['warning message']
  if (warning) self.client.emit('warning', new Error(warning))

  var interval = payload.interval || payload['min interval']
  if (interval && !self._opts.interval && self._intervalMs !== 0) { //TODO: Fix so tracker can set interval (now defaults to 30 min)
  //if(interval) { // ALWAYS use the interval recommended by tracker
    self.setInterval(interval)
  }

  var trackerId = payload['tracker id']
  if (trackerId) {
    // If absent, do not discard previous trackerId value
    self._trackerId = trackerId
  }

  if (payload.complete) {
    self.client.emit('update', {
    announce: self._announceUrl,
    complete: payload.complete,
    incomplete: payload.incomplete
    })
  }

  // Handle received peers
  if (Array.isArray(payload.peers)) {
    payload.peers.forEach(function (peerInfo) { //For all peers we receive - Open a WebRTC peer connection
      var peerId = peerInfo.peerId;

      console.log('Will handle connection for peer: ', peerId);

      var peer = self._peers[peerId] = new Peer({
        initiator: true,
        trickle: true,
        config: self.client._rtcConfig,
        wrtc: self.client._wrtc
      })
      peer.id = peerId

      peer.on('signal', function (signalObject) {
        console.log('GOT SIGNAL, expecting offer/ice', signalObject);
        if(signalObject.candidate) { // The signalling is for ICE
          var params = {
            info_hash: self.client._infoHash.toString('base64'),
            peer_id: self._peerID,
            candidate: signalObject.candidate
          }

          jsFlow.messageUser(peerId, params, 'webrtc_ice');
        }
        else { // The signalling is for an OFFER
          offer = signalObject;
          var params = {
            info_hash: self.client._infoHash.toString('base64'),
            peer_id: self._peerID,
            offer: offer
          }

          jsFlow.messageUser(peerId, params, 'webrtc_offer');
        }
      })
    })
  };
}

jsFlowTracker.prototype._onWebRtcOffer = function (payload, from) {
  var self = this
  if(!self._peers[from]) { //Verify we haven't already received an offer from this user
    var peer = self._peers[from] = new Peer({
      trickle: true,
      config: self.client._rtcConfig,
      wrtc: self.client._wrtc
    })
    peer.id = from

    peer.on('signal', function (signalObject) {
        console.log('GOT SIGNAL, expecting answer/ice', signalObject);
      if(signalObject.candidate) { // The signalling is for ICE
        var params = {
          info_hash: self.client._infoHash.toString('base64'),
          peer_id: self._peerID,
          candidate: signalObject.candidate
        }

        jsFlow.messageUser(from, params, 'webrtc_ice');
      }
      else { // The signalling is for an ANSWER
        answer = signalObject;
        var params = {
          info_hash: self.client._infoHash.toString('base64'),
          peer_id: self._peerID,
          answer: answer
        }

        jsFlow.messageUser(from, params, 'webrtc_answer');
      }
    })

    peer.signal(payload.offer)

    self.client.emit('peer', peer)
  }
  else {
    console.error('Already have peer connection with user: ' + from);
  }
}

jsFlowTracker.prototype._onWebRtcAnswer = function (payload, from) {
  var self = this
  var peer = self._peers[from]
  if(peer) {
    peer.id = from
    peer.signal(payload.answer)
    self.client.emit('peer', peer)
  }
  else {
    console.error('Got answer on peer connection that does not exist, from user: ' + from);
  }
}

jsFlowTracker.prototype._onWebRtcIce = function (payload, from) {
  var self = this
  //TODO: Buffer ICE ?
  console.log('WILL ADD ICE CANDIDATE!!!');

  var peer = self._peers[from]
  if(peer) {

    if(payload.candidate) {
      peer.signal(payload.candidate)
    }
    else {
      console.error('Candidate did not exist as expected in payload', payload);
    }
  }
  else {
    console.error('Candidate refers to a peer not yet created. TODO: Buffer ICE!', payload);
  }
}

jsFlowTracker.prototype._sendAnnounce = function (params) {
  var self = this
  jsFlow.messageUser(params.trackerid, params, 'announce')
}
<|endoftext|>


<commit_before>$(document).on('ready', function() {

  $('nav a').on('click', function(event) {
    event.preventDefault();
    var targetURI = event.currentTarget.dataset.pagePartial;
    $.ajax({
      cache: false,
      url: targetURI
    }).done(function(response) {
      $('.main-container').html(response);
    });
  });

  $('.main-container').on('click', 'a.blog-link', function(event) {
    event.preventDefault();
    var targetURI = event.target.dataset.pagePartial;
    $.ajax({
      cache: false,
      url: targetURI
    }).done(function(response) {
      $('.main-container').html(response);
    });
  });

});<commit_msg>Update single-page script to handle new home page links<commit_after>$(document).on('ready', function() {

  $('nav a').on('click', function(event) {
    event.preventDefault();
    var targetURI = event.currentTarget.dataset.pagePartial;
    $.ajax({
      cache: false,
      url: targetURI
    }).done(function(response) {
      $('.main-container').html(response);
    });
  });

  $('.main-container').on('click', 'a.blog-link, a.home-link', function(event) {
    event.preventDefault();
    var targetURI = event.target.dataset.pagePartial;
    $.ajax({
      cache: false,
      url: targetURI
    }).done(function(response) {
      $('.main-container').html(response);
    });
  });

});<|endoftext|>


<commit_before>// Filename: views/tasks/tasksTab.js
define([
	'jquery',
	'underscore',
	'backbone',
	'toastr',
	'services/task',
	'views/collection/tasks',
	'i18n!nls/strings',
	'text!templates/tasks/tasksTab.html'
], function($, _, Backbone, toastr, TaskService, TasksView, strings, tasksTemplate) {

	var TasksTabView = Backbone.View.extend({

		template: _.template(tasksTemplate),

		events: {
		  'executeTask': 'onExecuteTask',
			'deleteTask': 'onDeleteTask'
		},

		initialize: function(options) {
			this.userId = options.userId;
			this.hubId = options.hubId;
		},

		remove: function() {
			if (this.tasksView) {
				this.tasksView.remove();
			}
			Backbone.View.prototype.remove.call(this);
		},

		render: function() {
			this.$el.html(this.template({
				strings: strings
			}));

			if (this.tasksView) {
				this.tasksView.remove();
			}

			TaskService.getTasks(this, function(ctx, model) {
				ctx.tasksView = new TasksView({model: model});
				ctx.$el.find('.tasks').html(
					ctx.tasksView.render().el
				);
			}, function(ctx, model) {
				toastr.error(strings.ErrorOccurred);
			});

			return this;
		},

    onExecuteTask: function(event, task) {
      if (confirm(strings.AreYouSureYouWantToManuallyExecute + ' \"' + task.get('name') + '\"?')) {
        TaskService.executeTask(this, task.get('@id'), function() {
          toastr.success(strings.TaskExecuteSuccess);
        }, function() {
          toastr.error(strings.TaskExecuteFailure);
        });
      }
    },

		onDeleteTask: function(event, task) {
			if (confirm(strings.AreYouSureYouWantToDelete + ' \"' + task.get('name') + '\"?')) {
				task.destroy({
					context: this,
					success: function(model, response, options) {
						toastr.success(strings.TaskDeleteSuccess);
						options.context.render();
					},
					error: function(model, response, options) {
						if (response.status === 202) {
							toastr.success(strings.TaskDeleteSuccess);
							options.context.render();
						} else {
							toastr.error(strings.TaskDeleteFailure);
						}
					}
				});
			}
		}

	});

	return TasksTabView;
});
<commit_msg>Manual execution of a task now fires a task execution event.<commit_after>// Filename: views/tasks/tasksTab.js
define([
	'jquery',
	'underscore',
	'backbone',
	'toastr',
	'services/task',
	'views/collection/tasks',
	'i18n!nls/strings',
	'text!templates/tasks/tasksTab.html'
], function($, _, Backbone, toastr, TaskService, TasksView, strings, tasksTemplate) {

	var TasksTabView = Backbone.View.extend({

		template: _.template(tasksTemplate),

		events: {
		  'executeTask': 'onExecuteTask',
			'deleteTask': 'onDeleteTask'
		},

		initialize: function(options) {
			this.userId = options.userId;
			this.hubId = options.hubId;
		},

		remove: function() {
			if (this.tasksView) {
				this.tasksView.remove();
			}
			Backbone.View.prototype.remove.call(this);
		},

		render: function() {
			this.$el.html(this.template({
				strings: strings
			}));

			if (this.tasksView) {
				this.tasksView.remove();
			}

			TaskService.getTasks(this, function(ctx, model) {
				ctx.tasksView = new TasksView({model: model});
				ctx.$el.find('.tasks').html(
					ctx.tasksView.render().el
				);
			}, function(ctx, model) {
				toastr.error(strings.ErrorOccurred);
			});

			return this;
		},

    onExecuteTask: function(event, task) {
      if (confirm(strings.AreYouSureYouWantToManuallyExecute + ' \"' + task.get('name') + '\"?')) {
        TaskService.executeTask(this, task.get('@id'), null, function() {
          toastr.error(strings.TaskExecuteFailure);
        });
      }
    },

		onDeleteTask: function(event, task) {
			if (confirm(strings.AreYouSureYouWantToDelete + ' \"' + task.get('name') + '\"?')) {
				task.destroy({
					context: this,
					success: function(model, response, options) {
						toastr.success(strings.TaskDeleteSuccess);
						options.context.render();
					},
					error: function(model, response, options) {
						if (response.status === 202) {
							toastr.success(strings.TaskDeleteSuccess);
							options.context.render();
						} else {
							toastr.error(strings.TaskDeleteFailure);
						}
					}
				});
			}
		}

	});

	return TasksTabView;
});
<|endoftext|>