<commit_before>CT.require("CT.all");
CT.require("core");

CT.onload(function() {
	core.util.buildPage([
		{
			name: "Architecture",
			content: CT.dom.img("/img/architecture.png", "w1")
		},
		{
			name: "Initialization",
			content: [
				CT.dom.node("Installing cantools", "div", "bigger bold pv10"),
				"Pop open a terminal and clone cantools:",
				CT.dom.node("~> git clone https://github.com/bubbleboy14/cantools.git", "div", "code"),
				"Install it:",
				CT.dom.node([
					"~> cd cantools",
					"~/cantools> sudo python setup.py install",
					"~/cantools> sudo python setup.py develop",
				], "div", "code"),
				CT.dom.node("Creating A Project", "div", "bigger bold pv10"),
				"Then navigate somewhere else and make up a name for your project:",
				CT.dom.node([
					"~/cantools> cd ..",
					"~> ctinit greatprojectname",
				], "div", "code"),
				CT.dom.node("Refreshing A Project", "div", "bigger bold pv10"),
				"Maybe you're jumping into someone else's project. That's fine. First, make sure cantools is installed (see above). If you already have it, it doesn't hurt to make sure it's up to date. In your terminal:",
				CT.dom.node("~> ctinit -u", "div", "code"),
				[
					CT.dom.node("That command pulls in the latest cantools, and also updates any managed plugins (more about that", "span"),
					CT.dom.pad(),
					CT.dom.link("here", function() {
						CT.dom.id("tlPlugins").trigger();
					}),
					CT.dom.node("). Now navigate to your project and refresh:", "span")
				],
				CT.dom.node([
					"~> cd someproject",
					"~/someproject> ctinit -r"
				], "div", "code"),
				"That command installs all necessary plugins and adds in all the symlinks that don't belong in a repository."
			]
		},
		{
			name: "Object Relational Mapper",
			content: [
				CT.dom.node("Choosing Your Backend", "div", "bigger bold pv10"),
				[
					CT.dom.node("The cantools abstraction layer is like a rodeo performer riding two horses simultaneously:", "span"),
					CT.dom.pad(),
					CT.dom.link("the GAE neopythonic cloud datastore", null,
						"https://cloud.google.com/appengine/docs/python/ndb/", null, null, null, true),
					CT.dom.node("; and the SQL database of your choice (our recommendation), via", "span"),
					CT.dom.pad(),
					CT.dom.link("sqlalchemy", null, "http://www.sqlalchemy.org/", null, null, null, true),
					CT.dom.node(".", "span")
				],
				CT.dom.node("Modeling Data", "div", "bigger bold pv10"),
				[
					CT.dom.node("Now that you've got a project to mess around with, check out model.py. It will be mostly empty. For a good example of the sorts of things you can type there, feast your eyes on the", "span"),
					CT.dom.pad(),
					CT.dom.link("ctuser", null, "/plugins.html#ctuser"),
					CT.dom.pad(),
					CT.dom.node("plugin's", "span"),
					CT.dom.pad(),
					CT.dom.link("model injections", null,
						"https://github.com/bubbleboy14/ctuser/blob/master/ctuser/model.py"),
					CT.dom.node(". Our sleek api is boilerplateless thanks to the", "span"),
					CT.dom.pad(),
					CT.dom.link("metaclass magic of the model module", null,
						"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/model.py")
				],
				CT.dom.node("Queries", "div", "bigger bold pv10"),
				[
					CT.dom.node("Access Your Data", "div", "big pv10"),
					[
						CT.dom.node("The cantools abstraction layer manages", "span"),
						CT.dom.pad(),
						CT.dom.link("database sessions", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/session.py",
							null, null, null, true),
						CT.dom.pad(),
						CT.dom.node("under the hood, allowing numerous incrementally alternating request -bound sessions, as well as any number of simultaneous long-running thread -bound sessions, to coexist, reading and writing data at will. The session manager is utilized by individual", "span"),
						CT.dom.pad(),
						CT.dom.link("Query", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/query.py",
							null, null, null, true),
						CT.dom.pad(),
						CT.dom.node("instances, which in turn are used by the", "span"),
						CT.dom.pad(),
						CT.dom.link("getters", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/getters.py",
							null, null, null, true),
						CT.dom.node(", which themselves instantiate Query objects with the query() function attached to each data model (as do the", "span"),
						CT.dom.pad(),
						CT.dom.link("setters", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/setters.py",
							null, null, null, true),
						CT.dom.node(").", "span")
					],
					CT.dom.node("Even From Javascript(!)", "div", "big pv10"),
					[
						CT.dom.node("Check out the", "span"),
						CT.dom.pad(),
						CT.dom.link("CT.db", null, "/docs#db.js"),
						CT.dom.pad(),
						CT.dom.node("module to learn all about querying and messing with your data from all the way over in the client. Really!", "span")
					]
				],
				CT.dom.node("Migration", "div", "bigger bold pv10"),
				[
					CT.dom.node("Wherever you choose to squirrel away your data, you'll eventually have to move it somewhere. Check out", "span"),
					CT.dom.pad(),
					CT.dom.link("ctmigrate", null, "/docs#migrate"),
					CT.dom.pad(),
					CT.dom.node("to learn more!", "span")
				]
			]
		},
		{
			name: "Routing",
			content: [
				CT.dom.node("The Basics", "div", "bigger bold pv10"),
				[
					CT.dom.node("All routing is handled in the app.yaml file,", "span"),
					CT.dom.pad(),
					CT.dom.link("YAML", null, "http://yaml.org/", null, null, null, true),
					CT.dom.node("-style (parsed", "span"),
					CT.dom.pad(),
					CT.dom.link("here", null,
						"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/routes.py",
						null, null, null, true),
					CT.dom.node("). Each rule consists of a url, which may be a regular expression, followed by either a script line or a static_dir line.", "span")
				],
				CT.dom.node("Static Directories", "div", "bigger bold pv10"),
				"A static rule looks like this:",
				CT.dom.node([
					"- url: /css",
					CT.dom.pad(2),
					CT.dom.node("static_dir: css", "span"),
				], "div", "code"),
				CT.dom.node("Web Handlers", "div", "bigger bold pv10"),
				"A dynamic rule looks like this:",
				CT.dom.node([
					"- url: /_db",
					CT.dom.pad(2),
					CT.dom.node("script: _db.py", "span"),
				], "div", "code"),
				CT.dom.node("What's That Stuff At The Bottom?", "div", "bigger bold pv10"),
				"At some point in your app.yaml file, you'll see the following line:",
				CT.dom.node("## MODE SWITCHING -- DON'T MESS WITH (unless you know what you're doing)!",
					"div", "code"),
				[
					CT.dom.node("The stuff after that is used by", "span"),
					CT.dom.pad(),
					CT.dom.link("the compiler", null, "/doc#deploy"),
					CT.dom.pad(),
					CT.dom.node("to switch between compilation modes. Now you know.", "span")
				]
			]
		},
		{
			name: "Request Handling",
			content: [
				CT.dom.node("The", "span"),
				CT.dom.pad(),
				CT.dom.link("dez", null, "https://github.com/bubbleboy14/dez", null, null, null, true),
				CT.dom.node("-backed cantools.web module is built around a", "span"),
				CT.dom.pad(),
				CT.dom.link("modified", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/controller.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.link("SocketController", null,
					"https://github.com/bubbleboy14/dez/blob/master/dez/network/controller.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.node("pulling the strings of", "span"),
				CT.dom.pad(),
				CT.dom.link("2 subclassed", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/daemons.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.link("HTTPApplication", null,
					"https://github.com/bubbleboy14/dez/blob/master/dez/http/application.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.node("instances (for regular HTTP and Admin Servers) and a", "span"),
				CT.dom.pad(),
				CT.dom.link("Cron Manager", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/cron.py",
					null, null, null, true),
				CT.dom.node(". The controller dynamically loads modules (as specified by app.yaml routing rules) to handle cron jobs and (", "span"),
				CT.dom.link("all manner of", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/response.py",
					null, null, null, true),
				CT.dom.node(") requests as they come up.", "span"),
				CT.dom.br(),
				CT.dom.node("At this point you're probably dying to see more, so sneak a peak at the", "span"),
				CT.dom.pad(),
				CT.dom.link("blog plugin", null, "/plugins.html#ctblog"),
				CT.dom.node("'s", "span"),
				CT.dom.pad(),
				CT.dom.link("request handler", null,
					"https://github.com/bubbleboy14/ctblog/blob/master/ctblog/_blog.py",
					null, null, null, true),
			]
		},
		{
			name: "Services",
			content: [
				CT.dom.node("Cron", "div", "bigger bold pv10"),
				"blah blah cron",
				CT.dom.node("Mail", "div", "bigger bold pv10"),
				"blah blah mail"
			]
		},
		{
			name: "Javascript",
			content: [
				CT.dom.node("Modules", "div", "bigger bold pv10"),
				"blah blah modules",
				CT.dom.node("Classes", "div", "bigger bold pv10"),
				"blah blah classes",
				CT.dom.node("Compilation Modes", "div", "big bold pv10"),
				"blah blah compilation modes"
			]
		},
		{
			name: "Configuration",
			content: [
				CT.dom.node("Client", "div", "bigger bold pv10"),
				"blah blah client",
				CT.dom.node("Server", "div", "bigger bold pv10"),
				"blah blah server"
			]
		},
		{
			name: "Logging",
			content: [
				CT.dom.node("Client", "div", "bigger bold pv10"),
				"blah blah client",
				CT.dom.node("Server", "div", "bigger bold pv10"),
				"blah blah server"
			]
		},
		{
			name: "Caching",
			content: [
				CT.dom.node("Client", "div", "bigger bold pv10"),
				"blah blah client",
				CT.dom.node("Server", "div", "bigger bold pv10"),
				"blah blah server"
			]
		},
		{
			name: "Plugins",
			content: [
				CT.dom.node("Using Plugins", "div", "bigger bold pv10"),
				"blah blah using",
				CT.dom.node("Building Plugins", "div", "bigger bold pv10"),
				"blah blah building"
			]
		},
		{
			name: "Admin Dashboard",
			content: [
				CT.dom.node("db", "div", "bigger bold pv10"),
				"blah blah db",
				CT.dom.node("memcache", "div", "bigger bold pv10"),
				"blah blah memcache",
				CT.dom.node("pubsub", "div", "bigger bold pv10"),
				"blah blah pubsub",
				CT.dom.node("logs", "div", "bigger bold pv10"),
				"blah blah logs"
			]
		}
	], "ctcontent3", "ctlist3 big");
});<commit_msg>docs: plugins<commit_after>CT.require("CT.all");
CT.require("core");

CT.onload(function() {
	core.util.buildPage([
		{
			name: "Architecture",
			content: CT.dom.img("/img/architecture.png", "w1")
		},
		{
			name: "Initialization",
			content: [
				CT.dom.node("Installing cantools", "div", "bigger bold pv10"),
				"Pop open a terminal and clone cantools:",
				CT.dom.node("~> git clone https://github.com/bubbleboy14/cantools.git", "div", "code"),
				"Install it:",
				CT.dom.node([
					"~> cd cantools",
					"~/cantools> sudo python setup.py install",
					"~/cantools> sudo python setup.py develop",
				], "div", "code"),
				CT.dom.node("Creating A Project", "div", "bigger bold pv10"),
				"Then navigate somewhere else and make up a name for your project:",
				CT.dom.node([
					"~/cantools> cd ..",
					"~> ctinit greatprojectname",
				], "div", "code"),
				CT.dom.node("Refreshing A Project", "div", "bigger bold pv10"),
				"Maybe you're jumping into someone else's project. That's fine. First, make sure cantools is installed (see above). If you already have it, it doesn't hurt to make sure it's up to date. In your terminal:",
				CT.dom.node("~> ctinit -u", "div", "code"),
				[
					CT.dom.node("That command pulls in the latest cantools, and also updates any managed plugins (more about that", "span"),
					CT.dom.pad(),
					CT.dom.link("here", function() {
						CT.dom.id("tlPlugins").trigger();
					}),
					CT.dom.node("). Now navigate to your project and refresh:", "span")
				],
				CT.dom.node([
					"~> cd someproject",
					"~/someproject> ctinit -r"
				], "div", "code"),
				"That command installs all necessary plugins and adds in all the symlinks that don't belong in a repository."
			]
		},
		{
			name: "Object Relational Mapper",
			content: [
				CT.dom.node("Choosing Your Backend", "div", "bigger bold pv10"),
				[
					CT.dom.node("The cantools abstraction layer is like a rodeo performer riding two horses simultaneously:", "span"),
					CT.dom.pad(),
					CT.dom.link("the GAE neopythonic cloud datastore", null,
						"https://cloud.google.com/appengine/docs/python/ndb/", null, null, null, true),
					CT.dom.node("; and the SQL database of your choice (our recommendation), via", "span"),
					CT.dom.pad(),
					CT.dom.link("sqlalchemy", null, "http://www.sqlalchemy.org/", null, null, null, true),
					CT.dom.node(".", "span")
				],
				CT.dom.node("Modeling Data", "div", "bigger bold pv10"),
				[
					CT.dom.node("Now that you've got a project to mess around with, check out model.py. It will be mostly empty. For a good example of the sorts of things you can type there, feast your eyes on the", "span"),
					CT.dom.pad(),
					CT.dom.link("ctuser", null, "/plugins.html#ctuser"),
					CT.dom.pad(),
					CT.dom.node("plugin's", "span"),
					CT.dom.pad(),
					CT.dom.link("model injections", null,
						"https://github.com/bubbleboy14/ctuser/blob/master/ctuser/model.py"),
					CT.dom.node(". Our sleek api is boilerplateless thanks to the", "span"),
					CT.dom.pad(),
					CT.dom.link("metaclass magic of the model module", null,
						"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/model.py")
				],
				CT.dom.node("Queries", "div", "bigger bold pv10"),
				[
					CT.dom.node("Access Your Data", "div", "big pv10"),
					[
						CT.dom.node("The cantools abstraction layer manages", "span"),
						CT.dom.pad(),
						CT.dom.link("database sessions", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/session.py",
							null, null, null, true),
						CT.dom.pad(),
						CT.dom.node("under the hood, allowing numerous incrementally alternating request -bound sessions, as well as any number of simultaneous long-running thread -bound sessions, to coexist, reading and writing data at will. The session manager is utilized by individual", "span"),
						CT.dom.pad(),
						CT.dom.link("Query", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/query.py",
							null, null, null, true),
						CT.dom.pad(),
						CT.dom.node("instances, which in turn are used by the", "span"),
						CT.dom.pad(),
						CT.dom.link("getters", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/getters.py",
							null, null, null, true),
						CT.dom.node(", which themselves instantiate Query objects with the query() function attached to each data model (as do the", "span"),
						CT.dom.pad(),
						CT.dom.link("setters", null,
							"https://github.com/bubbleboy14/cantools/blob/master/cantools/db/sql/setters.py",
							null, null, null, true),
						CT.dom.node(").", "span")
					],
					CT.dom.node("Even From Javascript(!)", "div", "big pv10"),
					[
						CT.dom.node("Check out the", "span"),
						CT.dom.pad(),
						CT.dom.link("CT.db", null, "/docs#db.js"),
						CT.dom.pad(),
						CT.dom.node("module to learn all about querying and messing with your data from all the way over in the client. Really!", "span")
					]
				],
				CT.dom.node("Migration", "div", "bigger bold pv10"),
				[
					CT.dom.node("Wherever you choose to squirrel away your data, you'll eventually have to move it somewhere. Check out", "span"),
					CT.dom.pad(),
					CT.dom.link("ctmigrate", null, "/docs#migrate"),
					CT.dom.pad(),
					CT.dom.node("to learn more!", "span")
				]
			]
		},
		{
			name: "Routing",
			content: [
				CT.dom.node("The Basics", "div", "bigger bold pv10"),
				[
					CT.dom.node("All routing is handled in the app.yaml file,", "span"),
					CT.dom.pad(),
					CT.dom.link("YAML", null, "http://yaml.org/", null, null, null, true),
					CT.dom.node("-style (parsed", "span"),
					CT.dom.pad(),
					CT.dom.link("here", null,
						"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/routes.py",
						null, null, null, true),
					CT.dom.node("). Each rule consists of a url, which may be a regular expression, followed by either a script line or a static_dir line.", "span")
				],
				CT.dom.node("Static Directories", "div", "bigger bold pv10"),
				"A static rule looks like this:",
				CT.dom.node([
					"- url: /css",
					CT.dom.pad(2),
					CT.dom.node("static_dir: css", "span"),
				], "div", "code"),
				CT.dom.node("Web Handlers", "div", "bigger bold pv10"),
				"A dynamic rule looks like this:",
				CT.dom.node([
					"- url: /_db",
					CT.dom.pad(2),
					CT.dom.node("script: _db.py", "span"),
				], "div", "code"),
				CT.dom.node("What's That Stuff At The Bottom?", "div", "bigger bold pv10"),
				"At some point in your app.yaml file, you'll see the following line:",
				CT.dom.node("## MODE SWITCHING -- DON'T MESS WITH (unless you know what you're doing)!",
					"div", "code"),
				[
					CT.dom.node("The stuff after that is used by", "span"),
					CT.dom.pad(),
					CT.dom.link("the compiler", null, "/doc#deploy"),
					CT.dom.pad(),
					CT.dom.node("to switch between compilation modes. Now you know.", "span")
				]
			]
		},
		{
			name: "Request Handling",
			content: [
				CT.dom.node("The", "span"),
				CT.dom.pad(),
				CT.dom.link("dez", null, "https://github.com/bubbleboy14/dez", null, null, null, true),
				CT.dom.node("-backed cantools.web module is built around a", "span"),
				CT.dom.pad(),
				CT.dom.link("modified", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/controller.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.link("SocketController", null,
					"https://github.com/bubbleboy14/dez/blob/master/dez/network/controller.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.node("pulling the strings of", "span"),
				CT.dom.pad(),
				CT.dom.link("2 subclassed", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/daemons.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.link("HTTPApplication", null,
					"https://github.com/bubbleboy14/dez/blob/master/dez/http/application.py",
					null, null, null, true),
				CT.dom.pad(),
				CT.dom.node("instances (for regular HTTP and Admin Servers) and a", "span"),
				CT.dom.pad(),
				CT.dom.link("Cron Manager", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/cron.py",
					null, null, null, true),
				CT.dom.node(". The controller dynamically loads modules (as specified by app.yaml routing rules) to handle cron jobs and (", "span"),
				CT.dom.link("all manner of", null,
					"https://github.com/bubbleboy14/cantools/blob/master/cantools/web/dez_server/response.py",
					null, null, null, true),
				CT.dom.node(") requests as they come up.", "span"),
				CT.dom.br(),
				CT.dom.node("At this point you're probably dying to see more, so sneak a peak at the", "span"),
				CT.dom.pad(),
				CT.dom.link("blog plugin", null, "/plugins.html#ctblog"),
				CT.dom.node("'s", "span"),
				CT.dom.pad(),
				CT.dom.link("request handler", null,
					"https://github.com/bubbleboy14/ctblog/blob/master/ctblog/_blog.py",
					null, null, null, true),
			]
		},
		{
			name: "Services",
			content: [
				CT.dom.node("Cron", "div", "bigger bold pv10"),
				"blah blah cron",
				CT.dom.node("Mail", "div", "bigger bold pv10"),
				"blah blah mail"
			]
		},
		{
			name: "Javascript",
			content: [
				CT.dom.node("Modules", "div", "bigger bold pv10"),
				"blah blah modules",
				CT.dom.node("Classes", "div", "bigger bold pv10"),
				"blah blah classes",
				CT.dom.node("Compilation Modes", "div", "big bold pv10"),
				"blah blah compilation modes"
			]
		},
		{
			name: "Configuration",
			content: [
				CT.dom.node("Client", "div", "bigger bold pv10"),
				"blah blah client",
				CT.dom.node("Server", "div", "bigger bold pv10"),
				"blah blah server"
			]
		},
		{
			name: "Logging",
			content: [
				CT.dom.node("Client", "div", "bigger bold pv10"),
				"blah blah client",
				CT.dom.node("Server", "div", "bigger bold pv10"),
				"blah blah server"
			]
		},
		{
			name: "Caching",
			content: [
				CT.dom.node("Client", "div", "bigger bold pv10"),
				"blah blah client",
				CT.dom.node("Server", "div", "bigger bold pv10"),
				"blah blah server"
			]
		},
		{
			name: "Plugins",
			content: [
				CT.dom.node("Using Plugins", "div", "bigger bold pv10"),
				[
					CT.dom.node("To initialize a fresh project with one or more plugins, use", "span"),
					CT.dom.pad(),
					CT.dom.link("ctinit", null, "/docs#init"),
					CT.dom.node("'s -p (--plugins) flag, like so:", "span")
				],
				CT.dom.node("~> ctinit mymusicdotcom -p ctunes", "div", "code"),
				"Child's play. But what about adding some new functionality fragment mid-project? No problem, just add the name of the plugin to the PLUGIN_MODULES line in your ct.cfg file and refresh:",
				CT.dom.node("~/myblogorsomething> ctinit -r", "div", "code"),
				"That's it.",
				CT.dom.node("Building Plugins", "div", "bigger bold pv10"),
				[
					CT.dom.node("Building a plugin is easy. You mainly just need one file, init.py. It tells",
						"span"),
					CT.dom.pad(),
					CT.dom.link("ctinit", null, "/docs#init"),
					CT.dom.pad(),
					CT.dom.node("how the plugin is supposed to relate to the application. A good example is", "span"),
					CT.dom.pad(),
					CT.dom.link("ctblog", null, "/plugins.html#ctblog"),
					CT.dom.node("'s", "span"),
					CT.dom.pad(),
					CT.dom.link("init config", null,
						"https://github.com/bubbleboy14/ctblog/blob/master/ctblog/init.py",
						null, null, null, true),
					CT.dom.node(". If your frontend requires configuration, simply include a config.js file (", "span"),
					CT.dom.link("ctuser", null, "/plugins.html#ctuser"),
					CT.dom.node("'s", "span"),
					CT.dom.pad(),
					CT.dom.link("configuration", null,
						"https://github.com/bubbleboy14/ctuser/blob/master/ctuser/js/config.js",
						null, null, null, true),
					CT.dom.pad(),
					CT.dom.node("is a great example), which", "span"),
					CT.dom.pad(),
					CT.dom.link("ctinit", null, "/docs#init"),
					CT.dom.pad(),
					CT.dom.node("compiles, along with objects for other plugins and general items like header{} and css[], into core.config.", "span")
				]
			]
		},
		{
			name: "Admin Dashboard",
			content: [
				CT.dom.node("db", "div", "bigger bold pv10"),
				"blah blah db",
				CT.dom.node("memcache", "div", "bigger bold pv10"),
				"blah blah memcache",
				CT.dom.node("pubsub", "div", "bigger bold pv10"),
				"blah blah pubsub",
				CT.dom.node("logs", "div", "bigger bold pv10"),
				"blah blah logs"
			]
		}
	], "ctcontent3", "ctlist3 big");
});<|endoftext|>


<commit_before>(function(){

var MAX_SCORE = Math.pow(10,50);

function scoreModifier( stateDepth ) {
	return ( stateDepth % 2 ) * 2 - 1  // odd levels are players state, even are opponent
}

function calculateTopLevel( workQueue ) {
	return workQueue[0] ? Math.max( workQueue[0].depth - 1 , 0 ) : 0
}

function prune( depth , workQueue ) {
	while( workQueue[0] && workQueue[0].depth > depth ) {
		workQueue.shift()
	}
	return calculateTopLevel(workQueue)
}

var maximizeLogic = {
	isPrune : function( score , parent ) { return score >= parent.beta },
	isUpdate : function( score , parent ) { return score > parent.alpha },
	doUpdate : function( score , parent ) { parent.alpha = score },
	getElseScore : function( parent ) { return parent.alpha }
}

var minimizeLogic = {
	isPrune : function( score , parent ) { return score <= parent.alpha },
	isUpdate : function( score , parent ) { return score < parent.beta },
	doUpdate : function( score , parent ) { parent.beta = score },
	getElseScore : function( parent ) { return parent.beta }
}

function updateAllParentsAlphaBetaBasedOnScore( workItem , workQueue ) {

	// update the previous minimax scores
	var topLevel = calculateTopLevel(workQueue)
	var score = workItem.score
	var parent = workItem.previous
	var prefer = workItem

	function updateParentAlphaBeta( score , parent ) {
		var logic = parent.depth % 2 == 0 ? maximizeLogic : minimizeLogic

		if ( logic.isPrune(score,parent) ) {
			topLevel = prune( parent.depth , workQueue )
		}
		if ( logic.isUpdate(score,parent) ) {
			logic.doUpdate(score,parent)
			parent.best = workItem
			parent.prefer = prefer
		} else {
			score = logic.getElseScore(parent)
			workItem = parent.best
		}
		return score
	}

	while( parent && parent.depth >= topLevel ) {
		score = updateParentAlphaBeta(score,parent)
		prefer = parent
		parent = parent.previous
	}

}

function expandWorkItem( generateMoves , workItem , workQueue ) {

	if ( workItem.previous ) {
		workItem.alpha = workItem.previous.alpha
		workItem.beta = workItem.previous.beta
	}

	var stateList = generateMoves( workItem.state )
	for ( var i = stateList.length - 1 ; i >= 0 ; i-- ) {
		var state = stateList[i]
		workQueue.unshift({
			state : state ,
			depth : workItem.depth + 1 ,
			previous : workItem ,
			alpha : workItem.alpha ,
			beta : workItem.beta ,
			best : workItem.best
		})
	}
	return stateList.length;

}

module.exports = function alphabeta( initialization ) {

	var scoreFunction = initialization.scoreFunction
	var generateMoves = initialization.generateMoves
	var checkWinConditions = initialization.checkWinConditions

	var workQueue = []
	var depth = 0
	var top = {}
	var start = {}

	function scoreWorkItem( workItem , callback ) {
		scoreFunction( workItem.state , function( score ) {
			workItem.score = score * scoreModifier( workItem.depth )
			workQueue.unshift(workItem)
			callback(true);
		})
	}

	return {
		setup : function setup( state , depthParameter , alpha , beta ) {
			start = state
			alpha = alpha == undefined ? Number.NEGATIVE_INFINITY : alpha
			beta  = beta  == undefined ? Number.POSITIVE_INFINITY : beta
			workQueue = [ { state : state , depth : 0 , alpha : alpha , beta : beta } ]
			depth = depthParameter ? depthParameter : 1
			top = workQueue[0]
		},

		prediction : function prediction() {
			return top.best || {}
		},

		best : function best() {
			if ( ! top.best || ! top.best.state ) { return false }
			if ( ! top.prefer || ! top.prefer.state ) { return false }
			return top.prefer.state;
		},

		alpha : function alpha() {
			return top.alpha
		},

		step : function step( callback ) {
			var workItem = workQueue.shift()
			if ( ! workItem ) { callback(false); return }

			if ( workItem.score != undefined ) {

				updateAllParentsAlphaBetaBasedOnScore( workItem , workQueue );
				callback(true); return

			} else if ( workItem.depth > 0 && checkWinConditions( workItem.state ) ) {

				workItem.score = MAX_SCORE * scoreModifier( workItem.depth )
				workQueue.unshift(workItem)
				callback(true); return

			} else if ( workItem.depth < depth ) {

				if ( expandWorkItem( generateMoves , workItem , workQueue) == 0 ) {
					scoreWorkItem( workItem , callback )
					return;
				} else {
					callback(true); return
				}

			} else if ( workItem.depth == depth ) {

				scoreWorkItem( workItem , callback )
				return;

			}
			callback(false)
		},

		allSteps : function allSteps( callback , count ) {
			count = count ? count : 0
			var that = this
			that.step( function( hasMore ) {
				if ( hasMore ) {
					if ( count > 20 ) {
						setTimeout( function() { that.allSteps(callback) } , 1 )
					} else {
						that.allSteps(callback,count+1)
					}
				} else {
					callback(that.best())
				}
			})
		}
	}
}

})();<commit_msg>renamed 'best' to 'prediction' and 'prefer' to 'best' for code clarity<commit_after>(function(){

var MAX_SCORE = Math.pow(10,50);

function scoreModifier( stateDepth ) {
	return ( stateDepth % 2 ) * 2 - 1  // odd levels are players state, even are opponent
}

function calculateTopLevel( workQueue ) {
	return workQueue[0] ? Math.max( workQueue[0].depth - 1 , 0 ) : 0
}

function prune( depth , workQueue ) {
	while( workQueue[0] && workQueue[0].depth > depth ) {
		workQueue.shift()
	}
	return calculateTopLevel(workQueue)
}

var maximizeLogic = {
	isPrune : function( score , parent ) { return score >= parent.beta },
	isUpdate : function( score , parent ) { return score > parent.alpha },
	doUpdate : function( score , parent ) { parent.alpha = score },
	getElseScore : function( parent ) { return parent.alpha }
}

var minimizeLogic = {
	isPrune : function( score , parent ) { return score <= parent.alpha },
	isUpdate : function( score , parent ) { return score < parent.beta },
	doUpdate : function( score , parent ) { parent.beta = score },
	getElseScore : function( parent ) { return parent.beta }
}

function updateAllParentsAlphaBetaBasedOnScore( workItem , workQueue ) {

	// update the previous minimax scores
	var topLevel = calculateTopLevel(workQueue)
	var score = workItem.score
	var parent = workItem.previous
	var best = workItem

	function updateParentAlphaBeta( score , parent ) {
		var logic = parent.depth % 2 == 0 ? maximizeLogic : minimizeLogic

		if ( logic.isPrune(score,parent) ) {
			topLevel = prune( parent.depth , workQueue )
		}
		if ( logic.isUpdate(score,parent) ) {
			logic.doUpdate(score,parent)
			parent.prediction = workItem
			parent.best = best
		} else {
			score = logic.getElseScore(parent)
			workItem = parent.prediction
		}
		return score
	}

	while( parent && parent.depth >= topLevel ) {
		score = updateParentAlphaBeta(score,parent)
		best = parent
		parent = parent.previous
	}

}

function expandWorkItem( generateMoves , workItem , workQueue ) {

	if ( workItem.previous ) {
		workItem.alpha = workItem.previous.alpha
		workItem.beta = workItem.previous.beta
	}

	var stateList = generateMoves( workItem.state )
	for ( var i = stateList.length - 1 ; i >= 0 ; i-- ) {
		var state = stateList[i]
		workQueue.unshift({
			state : state ,
			depth : workItem.depth + 1 ,
			previous : workItem ,
			alpha : workItem.alpha ,
			beta : workItem.beta ,
			prediction : workItem.prediction
		})
	}
	return stateList.length;

}

module.exports = function alphabeta( initialization ) {

	var scoreFunction = initialization.scoreFunction
	var generateMoves = initialization.generateMoves
	var checkWinConditions = initialization.checkWinConditions

	var workQueue = []
	var depth = 0
	var top = {}
	var start = {}

	function scoreWorkItem( workItem , callback ) {
		scoreFunction( workItem.state , function( score ) {
			workItem.score = score * scoreModifier( workItem.depth )
			workQueue.unshift(workItem)
			callback(true);
		})
	}

	return {
		setup : function setup( state , depthParameter , alpha , beta ) {
			start = state
			alpha = alpha == undefined ? Number.NEGATIVE_INFINITY : alpha
			beta  = beta  == undefined ? Number.POSITIVE_INFINITY : beta
			workQueue = [ { state : state , depth : 0 , alpha : alpha , beta : beta } ]
			depth = depthParameter ? depthParameter : 1
			top = workQueue[0]
		},

		prediction : function prediction() {
			return top.prediction || {}
		},

		best : function best() {
			if ( ! top.prediction || ! top.prediction.state ) { return false }
			if ( ! top.best || ! top.best.state ) { return false }
			return top.best.state;
		},

		alpha : function alpha() {
			return top.alpha
		},

		step : function step( callback ) {
			var workItem = workQueue.shift()
			if ( ! workItem ) { callback(false); return }

			if ( workItem.score != undefined ) {

				updateAllParentsAlphaBetaBasedOnScore( workItem , workQueue );
				callback(true); return

			} else if ( workItem.depth > 0 && checkWinConditions( workItem.state ) ) {

				workItem.score = MAX_SCORE * scoreModifier( workItem.depth )
				workQueue.unshift(workItem)
				callback(true); return

			} else if ( workItem.depth < depth ) {

				if ( expandWorkItem( generateMoves , workItem , workQueue) == 0 ) {
					scoreWorkItem( workItem , callback )
					return;
				} else {
					callback(true); return
				}

			} else if ( workItem.depth == depth ) {

				scoreWorkItem( workItem , callback )
				return;

			}
			callback(false)
		},

		allSteps : function allSteps( callback , count ) {
			count = count ? count : 0
			var that = this
			that.step( function( hasMore ) {
				if ( hasMore ) {
					if ( count > 20 ) {
						setTimeout( function() { that.allSteps(callback) } , 1 )
					} else {
						that.allSteps(callback,count+1)
					}
				} else {
					callback(that.best())
				}
			})
		}
	}
}

})();<|endoftext|>


<commit_before>var localStorageKey = location.pathname + "current-filter";

function selectedFilters() {
  var groups = [];

  var filters = document.querySelectorAll(".filter-group");
  for(var i = 0; i < filters.length; i++) {
    var selected = filters[i].querySelectorAll("li.selected");

    var terms = [];

    for(var j = 0; j < selected.length; j++) {
      var term = selected[j].dataset.value;
      if(term != 'all') terms.push(term);
    }

    groups.push(terms);
  }

  return groups;
}

function filterMatches(terms) {
  var selectors = [];
  for(var j = 0; j < terms.length; j++) selectors.push(":not([class*='" + terms[j] + "'])");

  if(selectors.length == 0) return;

  var matching = document.querySelectorAll(".match:not(.filter-no-match)" + selectors.join(""));
  for(var j = 0; j < matching.length; j++) matching[j].classList.add("filter-no-match");
}

function applyFilters(groups) {
  updateFilterNames(groups);

  var matches = document.querySelectorAll(".match");
  for(var i = 0; i < matches.length; i++) matches[i].classList.remove("filter-no-match");

  for(var i = 0; i < groups.length; i++) filterMatches(groups[i]);

  if(document.querySelectorAll(".match:not(#no-results):not(.filter-no-match)").length == 0) {
    document.getElementById("no-results").classList.remove("filter-no-match");
  }
  else {
    document.getElementById("no-results").classList.add("filter-no-match");
  }

  marshalFilters(groups);
}

function updateSelected(groups) {
  var selected = document.querySelectorAll(".filter-group .selected");
  for(var i = 0; i < selected.length; i++) selected[i].classList.remove("selected");

  var terms = [].concat.apply([], groups);

  for(var i = 0; i < terms.length; i++) {
    var select = document.querySelectorAll(".filter-group li[data-value=\"" + terms[i] + "\"]");

    for(var j = 0; j < select.length; j++) select[j].classList.add("selected");
  }
}

function selectFilter() {
  if(this.classList.contains("vods-link")) {
    vodLinks(this.dataset.type);
    return;
  }

  this.classList.toggle("selected");

  applyFilters(selectedFilters());
}

function triggerFilterList(event) {
  event.preventDefault();

  var selected = document.body.classList.add("open");

  closeFilters();

  if(!selected) {
    document.body.classList.add("settings-opened");
  }
}

function updateFilterNames(groups) {
  var content = [];

  var terms = [].concat.apply([], groups);
  for(var i = 0; i < terms.length; i++) content.push(terms[i].replace(/-/g, " "));

  var filter = document.querySelector("#current-filters");
  if(content.length > 0) {
    filter.textContent = content.join(", ");
  }
  else {
    filter.textContent = "No filters currently applied";
  }
}

function closeFilter(event) {
  event.preventDefault();

  closeFilters();
}

function closeFilters() {
  document.body.classList.remove("settings-opened");
}

function clearFilters(event) {
  event.preventDefault();

  applyFilters([]);
  updateSelected([]);
}

function unmarshalFilters(string) {
  var groups = JSON.parse(string);
  if(groups.length == 1 || groups.length == 3) vodLinks(groups.pop());
  applyFilters(groups);
  updateSelected(groups);
}

function marshalFilters(groups) {
  groups.push(document.body.classList.contains("surprise") ? "surprise" : "youtube");

  window.location.hash = "#" + JSON.stringify(groups);
  window.localStorage[localStorageKey] = JSON.stringify(groups);
}

function vodLinks(type) {
  if(document.body.classList.contains(type)) return;

  var buttons = document.querySelectorAll(".vods-link");
  for(var i = 0; i < buttons.length; i++) {
    var button = buttons[i];
    if(button.dataset.type == type) button.classList.add("selected");
    else button.classList.remove("selected");
  }

  document.body.classList.remove("youtube");
  document.body.classList.remove("surprise");
  document.body.classList.add(type);

  var vods = document.querySelectorAll("a.vod");
  for(var i = 0; i < vods.length; i++) {
    var vod = vods[i];
    vod.href = vod.dataset[type];
  }

  marshalFilters(selectedFilters());
}

document.addEventListener("DOMContentLoaded", function(event) {
  document.body.addEventListener("click", function(e) {
    if(e.target && e.target.matches("a#trigger")) triggerFilterList.call(e.target, e);
    if(e.target && e.target.matches("#settings-content ul.filter-list li")) selectFilter.call(e.target, e);
    if(e.target && e.target.matches("#settings-content a.close")) closeFilter.call(e.target, e);
    if(e.target && e.target.matches("#settings-content a.clear")) clearFilters.call(e.target, e);
  });

  if(window.location.hash.length > 1) unmarshalFilters(window.location.hash.substr(1));
  else if(window.localStorage[localStorageKey]) unmarshalFilters(window.localStorage[localStorageKey]);
  else updateFilterNames([]);
});<commit_msg>Apparently Location.hash is percent-encoded, so percent-decode it first<commit_after>var localStorageKey = location.pathname + "current-filter";

function selectedFilters() {
  var groups = [];

  var filters = document.querySelectorAll(".filter-group");
  for(var i = 0; i < filters.length; i++) {
    var selected = filters[i].querySelectorAll("li.selected");

    var terms = [];

    for(var j = 0; j < selected.length; j++) {
      var term = selected[j].dataset.value;
      if(term != 'all') terms.push(term);
    }

    groups.push(terms);
  }

  return groups;
}

function filterMatches(terms) {
  var selectors = [];
  for(var j = 0; j < terms.length; j++) selectors.push(":not([class*='" + terms[j] + "'])");

  if(selectors.length == 0) return;

  var matching = document.querySelectorAll(".match:not(.filter-no-match)" + selectors.join(""));
  for(var j = 0; j < matching.length; j++) matching[j].classList.add("filter-no-match");
}

function applyFilters(groups) {
  updateFilterNames(groups);

  var matches = document.querySelectorAll(".match");
  for(var i = 0; i < matches.length; i++) matches[i].classList.remove("filter-no-match");

  for(var i = 0; i < groups.length; i++) filterMatches(groups[i]);

  if(document.querySelectorAll(".match:not(#no-results):not(.filter-no-match)").length == 0) {
    document.getElementById("no-results").classList.remove("filter-no-match");
  }
  else {
    document.getElementById("no-results").classList.add("filter-no-match");
  }

  marshalFilters(groups);
}

function updateSelected(groups) {
  var selected = document.querySelectorAll(".filter-group .selected");
  for(var i = 0; i < selected.length; i++) selected[i].classList.remove("selected");

  var terms = [].concat.apply([], groups);

  for(var i = 0; i < terms.length; i++) {
    var select = document.querySelectorAll(".filter-group li[data-value=\"" + terms[i] + "\"]");

    for(var j = 0; j < select.length; j++) select[j].classList.add("selected");
  }
}

function selectFilter() {
  if(this.classList.contains("vods-link")) {
    vodLinks(this.dataset.type);
    return;
  }

  this.classList.toggle("selected");

  applyFilters(selectedFilters());
}

function triggerFilterList(event) {
  event.preventDefault();

  var selected = document.body.classList.add("open");

  closeFilters();

  if(!selected) {
    document.body.classList.add("settings-opened");
  }
}

function updateFilterNames(groups) {
  var content = [];

  var terms = [].concat.apply([], groups);
  for(var i = 0; i < terms.length; i++) content.push(terms[i].replace(/-/g, " "));

  var filter = document.querySelector("#current-filters");
  if(content.length > 0) {
    filter.textContent = content.join(", ");
  }
  else {
    filter.textContent = "No filters currently applied";
  }
}

function closeFilter(event) {
  event.preventDefault();

  closeFilters();
}

function closeFilters() {
  document.body.classList.remove("settings-opened");
}

function clearFilters(event) {
  event.preventDefault();

  applyFilters([]);
  updateSelected([]);
}

function unmarshalFilters(string) {
  var groups = JSON.parse(string);
  if(groups.length == 1 || groups.length == 3) vodLinks(groups.pop());
  applyFilters(groups);
  updateSelected(groups);
}

function marshalFilters(groups) {
  groups.push(document.body.classList.contains("surprise") ? "surprise" : "youtube");

  window.location.hash = "#" + JSON.stringify(groups);
  window.localStorage[localStorageKey] = JSON.stringify(groups);
}

function vodLinks(type) {
  if(document.body.classList.contains(type)) return;

  var buttons = document.querySelectorAll(".vods-link");
  for(var i = 0; i < buttons.length; i++) {
    var button = buttons[i];
    if(button.dataset.type == type) button.classList.add("selected");
    else button.classList.remove("selected");
  }

  document.body.classList.remove("youtube");
  document.body.classList.remove("surprise");
  document.body.classList.add(type);

  var vods = document.querySelectorAll("a.vod");
  for(var i = 0; i < vods.length; i++) {
    var vod = vods[i];
    vod.href = vod.dataset[type];
  }

  marshalFilters(selectedFilters());
}

document.addEventListener("DOMContentLoaded", function(event) {
  document.body.addEventListener("click", function(e) {
    if(e.target && e.target.matches("a#trigger")) triggerFilterList.call(e.target, e);
    if(e.target && e.target.matches("#settings-content ul.filter-list li")) selectFilter.call(e.target, e);
    if(e.target && e.target.matches("#settings-content a.close")) closeFilter.call(e.target, e);
    if(e.target && e.target.matches("#settings-content a.clear")) clearFilters.call(e.target, e);
  });

  if(window.location.hash.length > 1) unmarshalFilters(decodeURIComponent(window.location.hash.substr(1)));
  else if(window.localStorage[localStorageKey]) unmarshalFilters(window.localStorage[localStorageKey]);
  else updateFilterNames([]);
});<|endoftext|>


<commit_before>(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.yourprojectname = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';

var _yourprojectname = require('./src/yourprojectname.js');

var YOUR_PROJECTNAME = _interopRequireWildcard(_yourprojectname);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

// Same work.
// const YOUR_PROJECTNAME = require('./YOUR_PROJECTNAME');

// export default YOUR_PROJECTNAME; //???
module.exports = YOUR_PROJECTNAME;

},{"./src/yourprojectname.js":2}],2:[function(require,module,exports){
"use strict";

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// Given a _sharedData from instagram script, return a JSON.

var YourClass = function () {
  function YourClass(say) {
    _classCallCheck(this, YourClass);

    this.say = say;
  }

  _createClass(YourClass, [{
    key: "speak",
    value: function speak() {
      return this.say;
    }
  }]);

  return YourClass;
}();

function areYouHappy(bool) {
  if (bool == "ok") {
    return "I am happy!";
  } else {
    return "I want to be happy!";
  }
}

module.exports = {
  YourClass: YourClass,
  areYouHappy: areYouHappy
};

},{}]},{},[1])(1)
});<commit_msg>Delete build<commit_after><|endoftext|>


<commit_before>/**********************************************************************************
***********************************************************************************
**                         ____  __          __         __                       **
**                  ____ _/ / /_/ /   ____ _/ /_  ___  / /____                   **
**                 / __ `/ / __/ /   / __ `/ __ \/ _ \/ / ___/                   **
**                / /_/ / / /_/ /___/ /_/ / /_/ /  __/ (__  )                    **
**                \__,_/_/\__/_____/\__,_/_.___/\___/_/____/  v2.0.0             **
**                                                                               **
** ----------------------------------------------------------------------------- **
**  How To use:                                                                  **
**   Add the following to your common.js [[Special:MyPage/common.js]]:           **
**   importScript( 'User:Joern/altLabels.js' );                                  **
**                                                                               **
**  Links:                                                                       **
**    [[User:Joern/altLabels.js]]                                                **
**    [[https://github.com/joernhees/wikidata-altLabels]]                        **
**                                                                               **
**  About:                                                                       **
**    This tool will add the 3 most common labels used in other languages below  **
**    the label's edit box in your language. A simple click will approve the     **
**    selected label for the current item.                                       **
**    If the item already has a label in your language nothing is changed.       **
**                                                                               **
**  Bug Reports, Feature Requests, Development:                                  **
**    If you want to report a bug or even have a pull request, please visit      **
**    https://github.com/joernhees/wikidata-altLabels .                          **
**    For testing purposes you can also run the latest development version       **
**    directly from github (see above link).                                     **
**                                                                               **
**  Thanks to:                                                                   **
**    [[User:Jitrixis]] your [[User:Jitrixis/labelLister.js]] helped me a lot.   **
***********************************************************************************
**********************************************************************************/

( function ( mw, $ ) {
	'use strict';

	console.log('altLabels 2.0.0 loaded');

	/**
	 * Check if we're viewing an item
	 */
	var itemId = mw.config.get( 'wbEntityId' );
	if ( !itemId ) {
		return;
	}

	/**
	 * holds the DOM input element for the label
	 */
	var labelInput;
	var userLanguage;

	/**
	 * altLabels
	 */
	function altLabels() {
		/**
		 * Check for the label input box, its presence means we don't have a label
		 * If we have a label return, do nothing.
		 */
		labelInput = $('#wb-item-'+itemId+' h1.wikibase-entitytermsview-heading-label.wb-empty');
		if (labelInput.length < 1) {
			return;
		}

		/**
		 * get user's main language
		 */
		userLanguage = mw.config.get( 'wgUserLanguage' );
		if (userLanguage.length < 1) {
			return;
		}

		/**
		 * load json module
		 */
		mw.loader.load('json');

		/**
		 * get other labels
		 */
		var labels = JSON.parse(mw.config.get('wbEntity')).labels;

		/**
		 * get the most often used label across languages
		 */
		var label;
		var labelLangs = {};
		for (var labelLang in labels) {
			label = labels[labelLang].value;
			if ( ! (label in labelLangs)) {
				labelLangs[label] = [];
			}
			labelLangs[label].push(labelLang);
		}
		var topLabels = [];
		for (label in labelLangs) {
			topLabels.push([label, labelLangs[label].length]);
		}
		if (topLabels.length === 0) {
			// sad, we didn't find any other labels ;(
			return;
		}
		topLabels.sort(function(a,b) {
			// sort by counts desc, labels asc
			var c = [a[1],b[0]];
			var d = [b[1],a[0]];
			return c < d ? 1 : (c > d ? -1 : 0);
		});

		/**
		 * show (up to) top 3 alternative labels
		 */
		var altLabelsDOM = $('Approve label from other languages: ');
		var sep = '';
		for (var i = 0; i < Math.min(topLabels.length, 3); i++) {
			label = topLabels[i][0];
			var insertElem = sep+'' +
				''+
				label +
				' ('+topLabels[i][1]+'x)';
			sep = ', ';
			altLabelsDOM.append(insertElem);
		}
		// bind click handler to shown altlabels
		altLabelsDOM.find('.wb-item-altlabel').click(submitAltLabel);
		labelInput.after(altLabelsDOM);
	}

	/**
	 * submit clicked alt label
	 */
	function submitAltLabel(ev) {
		ev.preventDefault();
		var selectedLabel = $(ev.target).text();
		console.log("selected alt label: " + selectedLabel);

		/*
		 * the value in the following is really set via UI and submitted... can
		 * probably be improved and be done by API directly, but i didn't want
		 * to break anything
		 */
		var labels = {};
		labels[userLanguage] = {
			"language": userLanguage,
			"value": selectedLabel
		};
		setItem(JSON.stringify( {
			"labels": labels,
		} ), "["+userLanguage+"] " + selectedLabel + " (approved from other language)");
	}

	/**
	 * Send the input value on the edit menu
	 */
	function setItem( item, summary ) {
		$.ajax( {
			type: 'POST',
			url: mw.util.wikiScript( 'api' ),
			data: {
				format: 'json',
				action: 'wbeditentity',
				id: itemId,
				type: 'item',
				token: mw.user.tokens.get( 'editToken' ),
				data: item,
				summary: '[[User:Joern/altLabels.js|altLabels]] ' + summary,
				exclude: 'pageid|ns|title|lastrevid|touched|sitelinks'
			}
		} )
		.done( function ( data ) {
			if ( data.hasOwnProperty( "error" ) ) {
				mw.notify( 'API Error' + $.toJSON( data ), { title: 'altLabels.js :', tag: 'altLabels' } );
				$( '#green-box' ).empty();
				$( '#red-box' ).empty();
				$( '#red-box' ).append( data.error.info.replace( /\n/g, ' ' ) );
			} else {
				$( '#green-box' ).empty();
				$( '#green-box' ).append( summary );
				mw.notify('sent', { title: 'altLabels.js :', tag: 'altLabels' } );
				window.location.reload(true);
			}
		} )
		.fail( function () {
			mw.notify( 'API Error', { title: 'altLabels.js :', tag: 'altLabels' } );
			$( '#green-box' ).empty();
			$( '#red-box' ).empty();
			$( '#red-box' ).append( "API Error" );
		} );
	}

	$( document ).ready( altLabels );
} ( mediaWiki, jQuery ) );
<commit_msg>back to dev version<commit_after>/**********************************************************************************
***********************************************************************************
**                         ____  __          __         __                       **
**                  ____ _/ / /_/ /   ____ _/ /_  ___  / /____                   **
**                 / __ `/ / __/ /   / __ `/ __ \/ _ \/ / ___/                   **
**                / /_/ / / /_/ /___/ /_/ / /_/ /  __/ (__  )                    **
**                \__,_/_/\__/_____/\__,_/_.___/\___/_/____/  v2.0.1-dev         **
**                                                                               **
** ----------------------------------------------------------------------------- **
**  How To use:                                                                  **
**   Add the following to your common.js [[Special:MyPage/common.js]]:           **
**   importScript( 'User:Joern/altLabels.js' );                                  **
**                                                                               **
**  Links:                                                                       **
**    [[User:Joern/altLabels.js]]                                                **
**    [[https://github.com/joernhees/wikidata-altLabels]]                        **
**                                                                               **
**  About:                                                                       **
**    This tool will add the 3 most common labels used in other languages below  **
**    the label's edit box in your language. A simple click will approve the     **
**    selected label for the current item.                                       **
**    If the item already has a label in your language nothing is changed.       **
**                                                                               **
**  Bug Reports, Feature Requests, Development:                                  **
**    If you want to report a bug or even have a pull request, please visit      **
**    https://github.com/joernhees/wikidata-altLabels .                          **
**    For testing purposes you can also run the latest development version       **
**    directly from github (see above link).                                     **
**                                                                               **
**  Thanks to:                                                                   **
**    [[User:Jitrixis]] your [[User:Jitrixis/labelLister.js]] helped me a lot.   **
***********************************************************************************
**********************************************************************************/

( function ( mw, $ ) {
	'use strict';

	console.log('altLabels 2.0.1-dev loaded');

	/**
	 * Check if we're viewing an item
	 */
	var itemId = mw.config.get( 'wbEntityId' );
	if ( !itemId ) {
		return;
	}

	/**
	 * holds the DOM input element for the label
	 */
	var labelInput;
	var userLanguage;

	/**
	 * altLabels
	 */
	function altLabels() {
		/**
		 * Check for the label input box, its presence means we don't have a label
		 * If we have a label return, do nothing.
		 */
		labelInput = $('#wb-item-'+itemId+' h1.wikibase-entitytermsview-heading-label.wb-empty');
		if (labelInput.length < 1) {
			return;
		}

		/**
		 * get user's main language
		 */
		userLanguage = mw.config.get( 'wgUserLanguage' );
		if (userLanguage.length < 1) {
			return;
		}

		/**
		 * load json module
		 */
		mw.loader.load('json');

		/**
		 * get other labels
		 */
		var labels = JSON.parse(mw.config.get('wbEntity')).labels;

		/**
		 * get the most often used label across languages
		 */
		var label;
		var labelLangs = {};
		for (var labelLang in labels) {
			label = labels[labelLang].value;
			if ( ! (label in labelLangs)) {
				labelLangs[label] = [];
			}
			labelLangs[label].push(labelLang);
		}
		var topLabels = [];
		for (label in labelLangs) {
			topLabels.push([label, labelLangs[label].length]);
		}
		if (topLabels.length === 0) {
			// sad, we didn't find any other labels ;(
			return;
		}
		topLabels.sort(function(a,b) {
			// sort by counts desc, labels asc
			var c = [a[1],b[0]];
			var d = [b[1],a[0]];
			return c < d ? 1 : (c > d ? -1 : 0);
		});

		/**
		 * show (up to) top 3 alternative labels
		 */
		var altLabelsDOM = $('Approve label from other languages: ');
		var sep = '';
		for (var i = 0; i < Math.min(topLabels.length, 3); i++) {
			label = topLabels[i][0];
			var insertElem = sep+'' +
				''+
				label +
				' ('+topLabels[i][1]+'x)';
			sep = ', ';
			altLabelsDOM.append(insertElem);
		}
		// bind click handler to shown altlabels
		altLabelsDOM.find('.wb-item-altlabel').click(submitAltLabel);
		labelInput.after(altLabelsDOM);
	}

	/**
	 * submit clicked alt label
	 */
	function submitAltLabel(ev) {
		ev.preventDefault();
		var selectedLabel = $(ev.target).text();
		console.log("selected alt label: " + selectedLabel);

		/*
		 * the value in the following is really set via UI and submitted... can
		 * probably be improved and be done by API directly, but i didn't want
		 * to break anything
		 */
		var labels = {};
		labels[userLanguage] = {
			"language": userLanguage,
			"value": selectedLabel
		};
		setItem(JSON.stringify( {
			"labels": labels,
		} ), "["+userLanguage+"] " + selectedLabel + " (approved from other language)");
	}

	/**
	 * Send the input value on the edit menu
	 */
	function setItem( item, summary ) {
		$.ajax( {
			type: 'POST',
			url: mw.util.wikiScript( 'api' ),
			data: {
				format: 'json',
				action: 'wbeditentity',
				id: itemId,
				type: 'item',
				token: mw.user.tokens.get( 'editToken' ),
				data: item,
				summary: '[[User:Joern/altLabels.js|altLabels]] ' + summary,
				exclude: 'pageid|ns|title|lastrevid|touched|sitelinks'
			}
		} )
		.done( function ( data ) {
			if ( data.hasOwnProperty( "error" ) ) {
				mw.notify( 'API Error' + $.toJSON( data ), { title: 'altLabels.js :', tag: 'altLabels' } );
				$( '#green-box' ).empty();
				$( '#red-box' ).empty();
				$( '#red-box' ).append( data.error.info.replace( /\n/g, ' ' ) );
			} else {
				$( '#green-box' ).empty();
				$( '#green-box' ).append( summary );
				mw.notify('sent', { title: 'altLabels.js :', tag: 'altLabels' } );
				window.location.reload(true);
			}
		} )
		.fail( function () {
			mw.notify( 'API Error', { title: 'altLabels.js :', tag: 'altLabels' } );
			$( '#green-box' ).empty();
			$( '#red-box' ).empty();
			$( '#red-box' ).append( "API Error" );
		} );
	}

	$( document ).ready( altLabels );
} ( mediaWiki, jQuery ) );
<|endoftext|>


<commit_before>

    function IOMMarker(info, diameter, image, map) {
      this.latlng_ = new google.maps.LatLng(parseFloat(info.lat),parseFloat(info.lon));
      this.url = info.url;
      this.count = info.count;
      this.image = image;
    	this.map_ = map;
    	this.name = info.name;
    	this.diameter = diameter;

      this.offsetVertical_ = -(this.diameter/2);
      this.offsetHorizontal_ = -(this.diameter/2);
      this.height_ = this.diameter;
      this.width_ = this.diameter;

      this.setMap(map);
    }

    IOMMarker.prototype = new google.maps.OverlayView();

    IOMMarker.prototype.draw = function() {

      var me = this;
    	var num = 0;

      var div = this.div_;
      if (!div) {
        div = this.div_ = document.createElement('div');
        div.style.border = "none";
        div.style.position = "absolute";
    		div.style.width = this.diameter + 'px';
    		div.style.height = this.diameter + 'px';
    		div.style.zIndex = 1;
        div.style.cursor = "pointer";

    		//Marker image
        var marker_image = document.createElement('img');
        marker_image.style.position = "relative";
        marker_image.style.width = "100%";
        marker_image.style.height = "100%";
        marker_image.src = this.image;
        div.appendChild(marker_image);

        //Marker address
        if (map_type=="overview_map") {
          var count = document.createElement('p');
          count.style.position = "absolute";
          count.style.top = "50%";
          count.style.left = "50%";
          count.style.height = "15px";
          count.style.textAlign = "center";
          if (this.diameter==34) {
            count.style.margin ="-6px 0 0 0px";
            count.style.font = "normal 12px Arial";
          } else if (this.diameter==42) {
            count.style.margin ="-8px 0 0 0px";
            count.style.font = "normal 15px Arial";
          } else {
            count.style.margin ="-9px 0 0 0px";
            count.style.font = "normal 18px Arial";
          }
          count.style.color = "white";
          $(count).text(this.count);
          div.appendChild(count);

          var hidden_div = document.createElement('div');
          hidden_div.style.border = "none";
          hidden_div.style.position = "absolute";
          hidden_div.style.margin = "0px";
          hidden_div.style.padding = "0px";
          hidden_div.style.display = "none";
          hidden_div.style.bottom = this.diameter + 4 +"px";
          hidden_div.style.left = (this.diameter/2)-(175/2)+"px";
          hidden_div.style.width = '175px';

          var top_hidden = document.createElement('div');
          top_hidden.style.border = "none";
          top_hidden.style.position = "relative";
          top_hidden.style.float = "left";
          top_hidden.style.padding = "9px 15px 3px 11px";
          top_hidden.style.width = '149px';
          top_hidden.style.height = 'auto';
          top_hidden.style.background = "url('/images/sites/common/tooltips/body_tooltip.png') no-repeat center top";
          top_hidden.style.font = "normal 17px 'PT Sans Bold'";
          top_hidden.style.textAlign = "center";
          top_hidden.style.color = "white";
          $(top_hidden).html(this.name+'
'+this.count+ ((this.count>1)?' projects':'project')+'');
          hidden_div.appendChild(top_hidden);

          var bottom_hidden = document.createElement('div');
          bottom_hidden.style.border = "none";
          bottom_hidden.style.position = "relative";
          bottom_hidden.style.float = "left";
          bottom_hidden.style.background = "url('/images/sites/common/tooltips/bottom_tooltip.png') no-repeat 0 0";
          bottom_hidden.style.width = '175px';
          bottom_hidden.style.height = '14px';
          hidden_div.appendChild(bottom_hidden);

          div.appendChild(hidden_div);

          google.maps.event.addDomListener(div,'mouseover',function(ev){
            $(this).css('zIndex',global_index++);
            $(this).children('div').show();
          });

          google.maps.event.addDomListener(div,'mouseout',function(ev){
            $(this).children('div').hide();
          });
        } else {
          google.maps.event.addDomListener(div,'mouseover',function(ev){
            $(this).css('zIndex',global_index++);
          });
        }

        if (this.url!=undefined) {
          google.maps.event.addDomListener(div,'click',function(ev){
      	    try{
      				ev.stopPropagation();
      			}catch(e){
      				event.cancelBubble=true;
      			};
      			window.location.href=me.url;
      	  });
        }

    		google.maps.event.addDomListener(div,'mousedown',function(ev){
    	    try{
    				ev.stopPropagation();
    			}catch(e){
    				event.cancelBubble=true;
    			};
    	  });

        var panes = this.getPanes();
        panes.floatPane.appendChild(div);

        if (($(this.div_).children('p').width()+6)>this.width_) {
          $(this.div_).children('p').css('display','none');
        } else {
          $(this.div_).children('p').css('margin-left',-($(this.div_).children('p').width()/2) + "px");
        }

      }

    	var pixPosition = me.getProjection().fromLatLngToDivPixel(me.latlng_);
      if (pixPosition) {
    	  div.style.width = me.width_ + 'px';
    	  div.style.left = (pixPosition.x + me.offsetHorizontal_) + 'px';
    	  div.style.height = me.height_ + 'px';
    	  div.style.top = (pixPosition.y + me.offsetVertical_) + 'px';
      }

    };

    IOMMarker.prototype.remove = function() {
      if (this.div_) {
        this.div_.parentNode.removeChild(this.div_);
        this.div_ = null;
      }
    };

    IOMMarker.prototype.hide = function() {
      if (this.div_) {
        $(this.div_).find('div').fadeOut();
      }
    };
<commit_msg>iom marker bug fixed<commit_after>

    function IOMMarker(info, diameter, image, map) {
      this.latlng_ = new google.maps.LatLng(parseFloat(info.lat),parseFloat(info.lon));
      this.url = info.url;
      this.count = info.count;
      this.image = image;
    	this.map_ = map;
    	this.name = info.name;
    	this.diameter = diameter;

      this.offsetVertical_ = -(this.diameter/2);
      this.offsetHorizontal_ = -(this.diameter/2);
      this.height_ = this.diameter;
      this.width_ = this.diameter;

      this.setMap(map);
    }

    IOMMarker.prototype = new google.maps.OverlayView();

    IOMMarker.prototype.draw = function() {

      var me = this;
    	var num = 0;

      var div = this.div_;
      if (!div) {
        div = this.div_ = document.createElement('div');
        div.style.border = "none";
        div.style.position = "absolute";
    		div.style.width = this.diameter + 'px';
    		div.style.height = this.diameter + 'px';
    		div.style.zIndex = 1;
        div.style.cursor = "pointer";

    		//Marker image
        var marker_image = document.createElement('img');
        marker_image.style.position = "relative";
        marker_image.style.width = "100%";
        marker_image.style.height = "100%";
        marker_image.src = this.image;
        div.appendChild(marker_image);

        //Marker address
        if (map_type=="overview_map") {
          var count = document.createElement('p');
          count.style.position = "absolute";
          count.style.top = "50%";
          count.style.left = "50%";
          count.style.height = "15px";
          count.style.textAlign = "center";
          if (this.diameter==34) {
            count.style.margin ="-6px 0 0 0px";
            count.style.font = "normal 12px Arial";
          } else if (this.diameter==42) {
            count.style.margin ="-8px 0 0 0px";
            count.style.font = "normal 15px Arial";
          } else {
            count.style.margin ="-9px 0 0 0px";
            count.style.font = "normal 18px Arial";
          }
          count.style.color = "white";
          $(count).text(this.count);
          div.appendChild(count);

          var hidden_div = document.createElement('div');
          hidden_div.style.border = "none";
          hidden_div.style.position = "absolute";
          hidden_div.style.margin = "0px";
          hidden_div.style.padding = "0px";
          hidden_div.style.display = "none";
          hidden_div.style.bottom = this.diameter + 4 +"px";
          hidden_div.style.left = (this.diameter/2)-(175/2)+"px";
          hidden_div.style.width = '175px';

          var top_hidden = document.createElement('div');
          top_hidden.style.border = "none";
          top_hidden.style.position = "relative";
          top_hidden.style.float = "left";
          top_hidden.style.padding = "9px 15px 3px 11px";
          top_hidden.style.width = '149px';
          top_hidden.style.height = 'auto';
          top_hidden.style.background = "url('/images/sites/common/tooltips/body_tooltip.png') no-repeat center top";
          top_hidden.style.font = "normal 17px 'PT Sans Bold'";
          top_hidden.style.textAlign = "center";
          top_hidden.style.color = "white";
          $(top_hidden).html(this.name+'
'+this.count+ ((this.count>1)?' projects':' project')+'');
          hidden_div.appendChild(top_hidden);

          var bottom_hidden = document.createElement('div');
          bottom_hidden.style.border = "none";
          bottom_hidden.style.position = "relative";
          bottom_hidden.style.float = "left";
          bottom_hidden.style.background = "url('/images/sites/common/tooltips/bottom_tooltip.png') no-repeat 0 0";
          bottom_hidden.style.width = '175px';
          bottom_hidden.style.height = '14px';
          hidden_div.appendChild(bottom_hidden);

          div.appendChild(hidden_div);

          google.maps.event.addDomListener(div,'mouseover',function(ev){
            $(this).css('zIndex',global_index++);
            $(this).children('div').show();
          });

          google.maps.event.addDomListener(div,'mouseout',function(ev){
            $(this).children('div').hide();
          });
        } else {
          google.maps.event.addDomListener(div,'mouseover',function(ev){
            $(this).css('zIndex',global_index++);
          });
        }

        if (this.url!=undefined) {
          google.maps.event.addDomListener(div,'click',function(ev){
      	    try{
      				ev.stopPropagation();
      			}catch(e){
      				event.cancelBubble=true;
      			};
      			window.location.href=me.url;
      	  });
        }

    		google.maps.event.addDomListener(div,'mousedown',function(ev){
    	    try{
    				ev.stopPropagation();
    			}catch(e){
    				event.cancelBubble=true;
    			};
    	  });

        var panes = this.getPanes();
        panes.floatPane.appendChild(div);

        if (($(this.div_).children('p').width()+6)>this.width_) {
          $(this.div_).children('p').css('display','none');
        } else {
          $(this.div_).children('p').css('margin-left',-($(this.div_).children('p').width()/2) + "px");
        }

      }

    	var pixPosition = me.getProjection().fromLatLngToDivPixel(me.latlng_);
      if (pixPosition) {
    	  div.style.width = me.width_ + 'px';
    	  div.style.left = (pixPosition.x + me.offsetHorizontal_) + 'px';
    	  div.style.height = me.height_ + 'px';
    	  div.style.top = (pixPosition.y + me.offsetVertical_) + 'px';
      }

    };

    IOMMarker.prototype.remove = function() {
      if (this.div_) {
        this.div_.parentNode.removeChild(this.div_);
        this.div_ = null;
      }
    };

    IOMMarker.prototype.hide = function() {
      if (this.div_) {
        $(this.div_).find('div').fadeOut();
      }
    };
<|endoftext|>


<commit_before>const _ = require('lodash');

const {applyStyle, removeStyle} = require('../manage-style');

const dynamicScalingfactors = (zoom) => {
  const scalingFactor = (1 / zoom);
  const defaults = {
    fontSize: 40,
    outlineWidth: 4,
    arrowScale: 3,
    edgeWidth: 2,
  };

  const dynamicFontSize = Math.min(defaults.fontSize, Math.max(scalingFactor * 18, 18));
  const dynamicFontOutlineWidth = Math.min(defaults.outlineWidth, Math.max(scalingFactor * 3, 3));
  const dynamicArrowScale = Math.min(defaults.arrowScale, Math.max(scalingFactor * 2.5, 2.5));
  const dynamicEdgewidth = Math.min(defaults.edgeWidth, Math.max(scalingFactor * 2.5, 2.5));

  return {
    fontSize: dynamicFontSize,
    outlineWidth: dynamicFontOutlineWidth,
    arrowScale: dynamicArrowScale,
    edgeWidth: dynamicEdgewidth
  };
};

const scaledDimensions = (node, zoom) => {
  const nw = node.width();
  const nh = node.height();

  if (nw === 0 || nh === 0) { return { w: 0, h: 0 }; }

  const scaledVal = (1 / zoom) * 8;
  const aspectRatio = nw / nh;
  let xIncr = 0;
  let yIncr = 0;

  if (aspectRatio > 1) {
    xIncr = nw + scaledVal;
    yIncr = nh + (scaledVal / aspectRatio);
  } else {
    xIncr = nw + (scaledVal / aspectRatio);
    yIncr = nh + scaledVal;
  }

  return {
    w: xIncr,
    h: yIncr
  };
};

const baseNodeHoverStyle = {
  'background-color': 'blue',
  'opacity': 1,
  'z-compound-depth': 'top',
  'color': 'white',
  'text-outline-color': 'black'
};

const baseEdgeHoverStyle = {
  'line-color': 'orange',
  'opacity': 1
};

const bindHover = (cy, nodeStyle = baseNodeHoverStyle, edgeStyle = baseEdgeHoverStyle) => {
  cy.on('mouseover', 'node[class!="compartment"]', function (evt) {
    const node = evt.target;
    const currZoom = cy.zoom();

    if (node.isParent() && node.isExpanded()) { return; }

    const { fontSize, outlineWidth, arrowScale, edgeWidth } = dynamicScalingfactors(currZoom);

    node.neighborhood().nodes().union(node).forEach((node) => {
      const { w, h } = scaledDimensions(node, currZoom);

      const nodeHoverStyle = _.assign({}, nodeStyle, {
        'font-size': fontSize,
        'text-outline-width': outlineWidth,
        'width': w,
        'height': h
      });

      applyStyle(cy, node, nodeHoverStyle, '_hover-style-before');
    });

    const edgeHoverStyle = _.assign({}, edgeStyle, {
      'arrow-scale': arrowScale,
      'width': edgeWidth
    });

    applyStyle(cy, node.neighborhood().edges(), edgeHoverStyle, '_hover-style-before');
  });

  cy.on('mouseout', 'node[class!="compartment"]', function (evt) {
    const node = evt.target;
    const neighborhood = node.neighborhood();

    removeStyle(cy, neighborhood.nodes(), '_hover-style-before');
    removeStyle(cy, node, '_hover-style-before');
    removeStyle(cy, neighborhood.edges(), '_hover-style-before');
  });

  cy.on('mouseover', 'edge', function (evt) {
    const edge = evt.target;
    const currZoom = cy.zoom();

    const { fontSize, outlineWidth, arrowScale, edgeWidth } = dynamicScalingfactors(currZoom);

    const edgeHoverStyle = _.assign({}, edgeStyle, {
      'arrow-scale': arrowScale,
      'width': edgeWidth
    });
    applyStyle(cy, edge, edgeHoverStyle, '_hover-style-before');

    edge.source().union(edge.target()).forEach((node) => {
      const { w, h } = scaledDimensions(node, currZoom);
      const nodeHoverStyle = _.assign({}, nodeStyle, {
        'width': w,
        'height': h,
        'font-size': fontSize,
        'color': 'white',
        'text-outline-color': 'black',
        'text-outline-width': outlineWidth,
        'opacity': 1,
        'background-color': 'blue',
        'z-compound-depth': 'top'
      });
      applyStyle(cy, node, nodeHoverStyle, '_hover-style-before');
    });
  });

  cy.on('mouseout', 'edge', function (evt) {
    const edge = evt.target;

    removeStyle(cy, edge, '_hover-style-before');
    removeStyle(cy, edge.source(), '_hover-style-before');
    removeStyle(cy, edge.target(), '_hover-style-before');
  });

};

module.exports = bindHover;<commit_msg>Delay added to hover style, permanent hover style bug introduced.<commit_after>const _ = require('lodash');

const {applyStyle, removeStyle} = require('../manage-style');

const dynamicScalingfactors = (zoom) => {
  const scalingFactor = (1 / zoom);
  const defaults = {
    fontSize: 40,
    outlineWidth: 4,
    arrowScale: 3,
    edgeWidth: 2,
  };

  const dynamicFontSize = Math.min(defaults.fontSize, Math.max(scalingFactor * 18, 18));
  const dynamicFontOutlineWidth = Math.min(defaults.outlineWidth, Math.max(scalingFactor * 3, 3));
  const dynamicArrowScale = Math.min(defaults.arrowScale, Math.max(scalingFactor * 2.5, 2.5));
  const dynamicEdgewidth = Math.min(defaults.edgeWidth, Math.max(scalingFactor * 2.5, 2.5));

  return {
    fontSize: dynamicFontSize,
    outlineWidth: dynamicFontOutlineWidth,
    arrowScale: dynamicArrowScale,
    edgeWidth: dynamicEdgewidth
  };
};

const scaledDimensions = (node, zoom) => {
  const nw = node.width();
  const nh = node.height();

  if (nw === 0 || nh === 0) { return { w: 0, h: 0 }; }

  const scaledVal = (1 / zoom) * 8;
  const aspectRatio = nw / nh;
  let xIncr = 0;
  let yIncr = 0;

  if (aspectRatio > 1) {
    xIncr = nw + scaledVal;
    yIncr = nh + (scaledVal / aspectRatio);
  } else {
    xIncr = nw + (scaledVal / aspectRatio);
    yIncr = nh + scaledVal;
  }

  return {
    w: xIncr,
    h: yIncr
  };
};

const baseNodeHoverStyle = {
  'background-color': 'blue',
  'opacity': 1,
  'z-compound-depth': 'top',
  'color': 'white',
  'text-outline-color': 'black'
};

const baseEdgeHoverStyle = {
  'line-color': 'orange',
  'opacity': 1
};

const bindHover = (cy, nodeStyle = baseNodeHoverStyle, edgeStyle = baseEdgeHoverStyle) => {
  const hoverNode =  _.debounce(function (evt) {
    const node = evt.target;
    const currZoom = cy.zoom();

    if (node.isParent() && node.isExpanded()) { return; }

    const { fontSize, outlineWidth, arrowScale, edgeWidth } = dynamicScalingfactors(currZoom);

    node.neighborhood().nodes().union(node).forEach((node) => {
      const { w, h } = scaledDimensions(node, currZoom);

      const nodeHoverStyle = _.assign({}, nodeStyle, {
        'font-size': fontSize,
        'text-outline-width': outlineWidth,
        'width': w,
        'height': h
      });

      applyStyle(cy, node, nodeHoverStyle, '_hover-style-before');
    });

    const edgeHoverStyle = _.assign({}, edgeStyle, {
      'arrow-scale': arrowScale,
      'width': edgeWidth
    });
    applyStyle(cy, node.neighborhood().edges(), edgeHoverStyle, '_hover-style-before');
  },500);

  cy.on('mouseover', 'node[class!="compartment"]',hoverNode);

  cy.on('mouseout', 'node[class!="compartment"]', function (evt) {
    const node = evt.target;
    const neighborhood = node.neighborhood();

    removeStyle(cy, neighborhood.nodes(), '_hover-style-before');
    removeStyle(cy, node, '_hover-style-before');
    removeStyle(cy, neighborhood.edges(), '_hover-style-before');
  });

  const hoverEdge = _.debounce( function (evt) {
    const edge = evt.target;
    const currZoom = cy.zoom();

    const { fontSize, outlineWidth, arrowScale, edgeWidth } = dynamicScalingfactors(currZoom);

    const edgeHoverStyle = _.assign({}, edgeStyle, {
      'arrow-scale': arrowScale,
      'width': edgeWidth
    });
    applyStyle(cy, edge, edgeHoverStyle, '_hover-style-before');

    edge.source().union(edge.target()).forEach((node) => {
      const { w, h } = scaledDimensions(node, currZoom);
      const nodeHoverStyle = _.assign({}, nodeStyle, {
        'width': w,
        'height': h,
        'font-size': fontSize,
        'color': 'white',
        'text-outline-color': 'black',
        'text-outline-width': outlineWidth,
        'opacity': 1,
        'background-color': 'blue',
        'z-compound-depth': 'top'
      });
      applyStyle(cy, node, nodeHoverStyle, '_hover-style-before');
    });
  },500);

  cy.on('mouseover', 'edge',hoverEdge);

  cy.on('mouseout', 'edge', function (evt) {
    const edge = evt.target;

    removeStyle(cy, edge, '_hover-style-before');
    removeStyle(cy, edge.source(), '_hover-style-before');
    removeStyle(cy, edge.target(), '_hover-style-before');
  });

};

module.exports = bindHover;<|endoftext|>


<commit_before>"use strict";

/**
 * @constructor
 */
function Memory(buffer, memory_size)
{
    var int8array = new Uint8Array(buffer),
        int16array = new Uint16Array(buffer),
        int8sarray = new Int8Array(buffer),
        int32sarray = new Int32Array(buffer);

    this.mem8 = int8array;
    this.mem8s = int8sarray;
    this.mem32s = int32sarray;

    this.buffer = buffer;

    this.size = memory_size;

    // debug function called by all memory reads and writes

    function debug_write(addr, size, value)
    {
        if(!DEBUG)
        {
            return;
        }

        //dbg_assert(typeof value === "number" && !isNaN(value));
        debug_read(addr, size, true);
    }

    /** @param {boolean=} is_write */
    function debug_read(addr, size, is_write)
    {
        if(!DEBUG)
        {
            return;
        }

        dbg_assert(typeof addr === "number");
        dbg_assert(!isNaN(addr));
    };

    // this only supports a 32 bit address space
    var memory_map_registered = new Uint8Array(1 << (32 - MMAP_BLOCK_BITS)),
        memory_map_read = [],
        memory_map_write = [];

    // managed by IO() in io.js
    this.memory_map_registered = memory_map_registered;
    this.memory_map_read = memory_map_read;
    this.memory_map_write = memory_map_write;

    dbg_assert((memory_size & MMAP_BLOCK_SIZE - 1) === 0);

    function mmap_read8(addr)
    {
        return memory_map_read[addr >>> MMAP_BLOCK_BITS](addr);
    }

    function mmap_write8(addr, value)
    {
        memory_map_write[addr >>> MMAP_BLOCK_BITS](addr, value);
    }

    function mmap_read32(addr)
    {
        var aligned_addr = addr >>> MMAP_BLOCK_BITS,
            size = memory_map_registered[aligned_addr],
            fn = memory_map_read[aligned_addr];

        if(size & 4)
        {
            return fn(addr);
        }
        else
        {
            return fn(addr) | fn(addr + 1) << 8 |
                    fn(addr + 2) << 16 | fn(addr + 3) << 24;
        }
    }

    function mmap_write32(addr, value)
    {
        var aligned_addr = addr >>> MMAP_BLOCK_BITS,
            size = memory_map_registered[aligned_addr],
            fn = memory_map_write[aligned_addr];

        if(size & 4)
        {
            fn(addr, value);
        }
        else
        {
            fn(addr, value & 0xFF);
            fn(addr + 1, value >> 8 & 0xFF);
            fn(addr + 2, value >> 16 & 0xFF);
            fn(addr + 3, value >>> 24);
        }
    }

    /**
     * @param addr {number}
     */
    this.read8 = function(addr)
    {
        debug_read(addr, 1);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS])
        {
            return mmap_read8(addr);
        }
        else
        {
            return int8array[addr];
        }
    };

    /**
     * @param addr {number}
     */
    this.read16 = function(addr)
    {
        debug_read(addr, 2);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS])
        {
            return mmap_read8(addr) | mmap_read8(addr + 1) << 8;
        }
        else
        {
            return int8array[addr] | int8array[addr + 1] << 8;
        }
    };

    /**
     * @param addr {number}
     */
    this.read_aligned16 = function(addr)
    {
        debug_read(addr << 1, 2);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS - 1])
        {
            addr <<= 1;
            return mmap_read8(addr) | mmap_read8(addr + 1) << 8;
        }
        else
        {
            return int16array[addr];
        }
    };

    /**
     * @param addr {number}
     */
    this.read32s = function(addr)
    {
        debug_read(addr, 4);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS])
        {
            return mmap_read32(addr);
        }
        else
        {
            return int8array[addr] | int8array[addr + 1] << 8 |
                int8array[addr + 2] << 16 | int8array[addr + 3] << 24;
        }
    };

    /**
     * @param addr {number}
     */
    this.read_aligned32 = function(addr)
    {
        debug_read(addr << 2, 4);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS - 2])
        {
            return mmap_read32(addr << 2);
        }
        else
        {
            return int32sarray[addr];
        }
    };

    /**
     * @param addr {number}
     * @param value {number}
     */
    this.write8 = function(addr, value)
    {
        debug_write(addr, 1, value);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS])
        {
            mmap_write8(addr, value);
        }
        else
        {
            int8array[addr] = value;
        }
    };

    /**
     * @param addr {number}
     * @param value {number}
     */
    this.write16 = function(addr, value)
    {
        debug_write(addr, 2, value);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS])
        {
            mmap_write8(addr, value & 0xff);
            mmap_write8(addr + 1, value >> 8 & 0xff);
        }
        else
        {
            int8array[addr] = value;
            int8array[addr + 1] = value >> 8;
        }
    };

    /**
     * @param addr {number}
     * @param value {number}
     */
    this.write_aligned16 = function(addr, value)
    {
        debug_write(addr << 1, 2, value);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS - 1])
        {
            addr <<= 1;
            mmap_write8(addr, value & 0xff);
            mmap_write8(addr + 1, value >> 8 & 0xff);
        }
        else
        {
            int16array[addr] = value;
        }
    };

    /**
     * @param addr {number}
     * @param value {number}
     */
    this.write32 = function(addr, value)
    {
        debug_write(addr, 4, value);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS])
        {
            mmap_write32(addr, value);
        }
        else
        {
            int8array[addr] = value;
            int8array[addr + 1] = value >> 8;
            int8array[addr + 2] = value >> 16;
            int8array[addr + 3] = value >> 24;
        }
    };

    this.write_aligned32 = function(addr, value)
    {
        debug_write(addr << 2, 4, value);

        if(memory_map_registered[addr >>> MMAP_BLOCK_BITS - 2])
        {
            mmap_write32(addr << 2, value);
        }
        else
        {
            int32sarray[addr] = value;
        }
    };

    /**
     * @param offset {number}
     * @param blob {Array.<number>}
     */
    this.write_blob = function(blob, offset)
    {
        dbg_assert(blob && blob.length);
        int8array.set(blob, offset);
    };

    /**
     * zero byte terminated string
     */
    this.read_string = function(addr)
    {
        var str = "",
            data_byte;

        while(data_byte = this.read8(addr))
        {
            str += String.fromCharCode(data_byte);
            addr++;
        }

        return str;
    };

    this.write_string = function(str, addr)
    {
        for(var i = 0; i < str.length; i++)
        {
            this.write8(addr + i, str.charCodeAt(i));
        }
    };
}
<commit_msg>Remove Closure from memory<commit_after>"use strict";

/**
 * @constructor
 */
function Memory(buffer, memory_size)
{
    var mem8 = new Uint8Array(buffer),
        mem16 = new Uint16Array(buffer),
        mem8s = new Int8Array(buffer),
        mem32s = new Int32Array(buffer);

    this.mem8 = mem8;
    this.mem16 = mem16;
    this.mem8s = mem8s;
    this.mem32s = mem32s;

    this.buffer = buffer;

    this.size = memory_size;

    // this only supports a 32 bit address space
    var memory_map_registered = new Uint8Array(1 << (32 - MMAP_BLOCK_BITS)),
        memory_map_read = [],
        memory_map_write = [];

    // managed by IO() in io.js
    this.memory_map_registered = memory_map_registered;
    this.memory_map_read = memory_map_read;
    this.memory_map_write = memory_map_write;

    dbg_assert((memory_size & MMAP_BLOCK_SIZE - 1) === 0);
}

// called by all memory reads and writes
Memory.prototype.debug_write = function(addr, size, value)
{
    if(!DEBUG)
    {
        return;
    }

    //dbg_assert(typeof value === "number" && !isNaN(value));
    this.debug_read(addr, size, true);
}

/** @param {boolean=} is_write */
Memory.prototype.debug_read = function(addr, size, is_write)
{
    if(!DEBUG)
    {
        return;
    }

    dbg_assert(typeof addr === "number");
    dbg_assert(!isNaN(addr));
};

Memory.prototype.mmap_read8 = function(addr)
{
    return this.memory_map_read[addr >>> MMAP_BLOCK_BITS](addr);
}

Memory.prototype.mmap_write8 = function(addr, value)
{
    this.memory_map_write[addr >>> MMAP_BLOCK_BITS](addr, value);
}

Memory.prototype.mmap_read32 = function(addr)
{
    var aligned_addr = addr >>> MMAP_BLOCK_BITS,
        size = this.memory_map_registered[aligned_addr],
        fn = this.memory_map_read[aligned_addr];

    if(size & 4)
    {
        return fn(addr);
    }
    else
    {
        return fn(addr) | fn(addr + 1) << 8 |
                fn(addr + 2) << 16 | fn(addr + 3) << 24;
    }
}

Memory.prototype.mmap_write32 = function(addr, value)
{
    var aligned_addr = addr >>> MMAP_BLOCK_BITS,
        size = this.memory_map_registered[aligned_addr],
        fn = this.memory_map_write[aligned_addr];

    if(size & 4)
    {
        fn(addr, value);
    }
    else
    {
        fn(addr, value & 0xFF);
        fn(addr + 1, value >> 8 & 0xFF);
        fn(addr + 2, value >> 16 & 0xFF);
        fn(addr + 3, value >>> 24);
    }
}

/**
 * @param addr {number}
 */
Memory.prototype.read8 = function(addr)
{
    this.debug_read(addr, 1);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read8(addr);
    }
    else
    {
        return this.mem8[addr];
    }
};

/**
 * @param addr {number}
 */
Memory.prototype.read16 = function(addr)
{
    this.debug_read(addr, 2);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read8(addr) | this.mmap_read8(addr + 1) << 8;
    }
    else
    {
        return this.mem8[addr] | this.mem8[addr + 1] << 8;
    }
};

/**
 * @param addr {number}
 */
Memory.prototype.read_aligned16 = function(addr)
{
    this.debug_read(addr << 1, 2);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 1])
    {
        addr <<= 1;
        return this.mmap_read8(addr) | this.mmap_read8(addr + 1) << 8;
    }
    else
    {
        return this.mem16[addr];
    }
};

/**
 * @param addr {number}
 */
Memory.prototype.read32s = function(addr)
{
    this.debug_read(addr, 4);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read32(addr);
    }
    else
    {
        return this.mem8[addr] | this.mem8[addr + 1] << 8 |
            this.mem8[addr + 2] << 16 | this.mem8[addr + 3] << 24;
    }
};

/**
 * @param addr {number}
 */
Memory.prototype.read_aligned32 = function(addr)
{
    this.debug_read(addr << 2, 4);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 2])
    {
        return this.mmap_read32(addr << 2);
    }
    else
    {
        return this.mem32s[addr];
    }
};

/**
 * @param addr {number}
 * @param value {number}
 */
Memory.prototype.write8 = function(addr, value)
{
    this.debug_write(addr, 1, value);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        this.mmap_write8(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
    }
};

/**
 * @param addr {number}
 * @param value {number}
 */
Memory.prototype.write16 = function(addr, value)
{
    this.debug_write(addr, 2, value);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        this.mmap_write8(addr, value & 0xff);
        this.mmap_write8(addr + 1, value >> 8 & 0xff);
    }
    else
    {
        this.mem8[addr] = value;
        this.mem8[addr + 1] = value >> 8;
    }
};

/**
 * @param addr {number}
 * @param value {number}
 */
Memory.prototype.write_aligned16 = function(addr, value)
{
    this.debug_write(addr << 1, 2, value);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 1])
    {
        addr <<= 1;
        this.mmap_write8(addr, value & 0xff);
        this.mmap_write8(addr + 1, value >> 8 & 0xff);
    }
    else
    {
        this.mem16[addr] = value;
    }
};

/**
 * @param addr {number}
 * @param value {number}
 */
Memory.prototype.write32 = function(addr, value)
{
    this.debug_write(addr, 4, value);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        this.mmap_write32(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
        this.mem8[addr + 1] = value >> 8;
        this.mem8[addr + 2] = value >> 16;
        this.mem8[addr + 3] = value >> 24;
    }
};

Memory.prototype.write_aligned32 = function(addr, value)
{
    this.debug_write(addr << 2, 4, value);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 2])
    {
        this.mmap_write32(addr << 2, value);
    }
    else
    {
        this.mem32s[addr] = value;
    }
};

/**
 * @param offset {number}
 * @param blob {Array.<number>}
 */
Memory.prototype.write_blob = function(blob, offset)
{
    dbg_assert(blob && blob.length);
    this.mem8.set(blob, offset);
};

/**
 * zero byte terminated string
 */
Memory.prototype.read_string = function(addr)
{
    var str = "",
        data_byte;

    while(data_byte = this.read8(addr))
    {
        str += String.fromCharCode(data_byte);
        addr++;
    }

    return str;
};

Memory.prototype.write_string = function(str, addr)
{
    for(var i = 0; i < str.length; i++)
    {
        this.write8(addr + i, str.charCodeAt(i));
    }
};
<|endoftext|>