<commit_before>var Triple = require("./RDFNode.js").Triple;
var IndexedGraph = require("./IndexedGraph.js").IndexedGraph;
var RDFEnvironment = require("./RDFEnvironment.js").RDFEnvironment;
var RDFNodeEquals = require('./RDFNode.js').RDFNodeEquals;
var BlankNode = require("./RDFNode.js").BlankNode;

function _(v) { return { writable:false, configurable:false, enumerable:false, value:v } }
function _getter(v) { return { configurable:false, enumerable:false, get:v } }
function prop(p,l) {
	if(p == 'a') return 'rdf:type';
	p = p.replace('$',':');
	if(p.indexOf(':') == -1) p = env.resolve(p,l)||p;
	return p;
};

var env = exports.environment = String.prototype.profile = new RDFEnvironment;
require('./Default.js').loadDefaultPrefixMap(env);

// N-Triples encoder
function encodeString(s) {
	var out = "";
	var skip = false;
	var _g1 = 0, _g = s.length;
	while(_g1 < _g) {
		var i = _g1++;
		if(!skip) {
			var code = s.charCodeAt(i);
			if(55296 <= code && code <= 56319) {
				var low = s.charCodeAt(i + 1);
				code = (code - 55296) * 1024 + (low - 56320) + 65536;
				skip = true
			}
			if(code > 1114111) { throw new Error("Char out of range"); }
			var hex = "00000000".concat((new Number(code)).toString(16).toUpperCase());
			if(code >= 65536) {
				out += "\\U" + hex.slice(-8)
			} else {
				if(code >= 127 || code <= 31) {
					switch(code) {
						case 9:	out += "\\t"; break;
						case 10: out += "\\n"; break;
						case 13: out += "\\r"; break;
						default: out += "\\u" + hex.slice(-4); break
					}
				} else {
					switch(code) {
						case 34: out += '\\"'; break;
						case 92: out += "\\\\"; break;
						default: out += s.charAt(i); break
					}
				}
			}
		} else {
			skip = !skip
		}
	}
	return out
};

// All
var ObjectProperties = {
	equals: _(RDFNodeEquals),
	ref: _( function(id) {
		var ref = arguments.callee;
		Object.defineProperties(this, {
			id: _( id ? id.resolve() : (new BlankNode).valueOf() ),
			n3: _( function(a) {
				var outs = [], o = this, map = o.aliasmap || a;
				Object.keys(this).forEach(function(p) {
					if(typeof o[p] == 'function') return;
					if(o[p].id && o[p].id.nodeType() == 'IRI') return outs.push( prop(p,map) + ' ' + o[p].id.n3() );
					if(!o[p].nodeType && !o[p].id) ref.call(o[p]);
					outs.push( prop(p, map) + ' ' + o[p].n3(map) );
				});
				outs = outs.join(";\n	");
				return id ? this.id.n3() + ' ' + outs + ' .' : '[ ' + outs + ' ]';
			}),
			toNT: _( function(a) {
				return this.graphify(a).toArray().join("\n");
			}),
			graphify: _( function(a) {
				var graph = new IndexedGraph;
				var o = this
				var map = o.aliasmap || a;
				function graphify(s1,p1,o1) {
					if(typeof(o1)=='function' || typeof(o1)=='undefined') return;
					if(!o1.nodeType && !o1.id && typeof(o1)!="string") ref.call(o1); // If the Object doesn't have a bnode, give it one
					if(o1.id) {
						// o1 is an Object, add triple and child triples
						graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), o1.id.resolve() ) );
						graph.merge( o1.graphify() );
					} else if(typeof(o1)=="string") {
						// o1 is a URI
						graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), o1.resolve() ) );
					} else if(!Array.isArray(o1)) {
						// o1 is a literal
						graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), o1 ) );
					} else if(Array.isArray(o1)) {
						// o1 is a Collection or a multi-valued property
						if(!o1.list) {
							// o1 is a multi-valued property
							o1.forEach( function(i) { graphify(s1.resolve(), p1.resolve(), i) });
						} else {
							// o1 is an rdf:Collection
							if(o1.length == 0) {
								graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), env.resolve("rdf:nil") ) );
							} else {
								var b = ref.call({}); // Generate bnode
								graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), b.id.resolve() ) );
								o1.forEach( function(i,x) {
									graphify(b.id, env.resolve('rdf:first'), i );
									var n = ref.call({});
									graph.add( new Triple(b.id.resolve(), 'rdf:rest'.resolve(), (x == o1.length-1) ? env.resolve('rdf:nil') : n.id.resolve() ) );
									b = n;
								});
							}
						}
					}
				}
				if(typeof(id)=="object") throw new Error("Not an object: "+require('util').inspect(this));
				Object.keys(this).forEach(function(p) { graphify(o.id, p, o[p]) });
				return graph;
			}),
			using: _( function() {
				Object.defineProperty(this,'aliasmap',_(Array.prototype.slice.call(arguments)));
				return this;
			})
		});
		return this;
	}),
};
exports.setObjectProperties = function(o){
	Object.defineProperties(o, ObjectProperties);
}

// String
var StringProperties = {
	tl: _( function(t) {
		return env.createLiteral(this.toString(), null, t);
	}),
	l: _( function(l) {
		return env.createLiteral(this.toString(), l, null);
	}),
	resolve: _( function() {
		if(this.indexOf(':')<0 || this.indexOf("//")>=0 ) return this.toString();
		return env.resolve(this)||this.toString();
	}),
	value: _getter(function(){return this.toString();}),
	nodeType: _( function() {
		//if(this.type) return 'TypedLiteral';
		//if(this.language || this.indexOf(' ') >= 0 || this.indexOf(':') == -1 ) return 'PlainLiteral';
		if(this.substr(0,2) == '_:') return 'BlankNode';
		return 'IRI';
	}),
	n3: _( function() {
		switch(this.nodeType()) {
			case 'PlainLiteral': return ('"' + encodeString(this) + '"' + ( this.language ? '@' + this.language : '')).toString();
			case 'IRI':
				var resolved = this.resolve();
				return (resolved == this) ? "<" + encodeString(resolved) + ">" : this.toString();
			case 'BlankNode': return this.toString();
			case 'TypedLiteral':
				if(this.type.resolve() == env.resolve("rdf:PlainLiteral")) return '"' + encodeString(this) + '"';
				return '"' + encodeString(this) + '"^^' + this.type.n3();
		}
	}),
	toNT: _( function() {
		switch(this.nodeType()) {
			case 'PlainLiteral': return ('"' + encodeString(this) + '"' + ( this.language ? '@' + this.language : '')).toString();
			case 'IRI': return "<" + encodeString(this.resolve()) + ">";
			case 'BlankNode': return this.toString();
			case 'TypedLiteral':
				if(this.type.resolve() == env.resolve("rdf:PlainLiteral")) return '"' + encodeString(this) + '"';
				return '"' + encodeString(this) + '"^^' + this.type.n3();
		}
	}),
	toCanonical: _( function() { return this.n3() } )
};
exports.setStringProperties = function(o){
	Object.defineProperties(o, StringProperties);
}
exports.setStringProperties(String.prototype);

// Array
var ArrayProperties = {
	list: _(false),
	toList: _(function() {
		this.list = true;
		return this;
	}),
	nodeType: _("Collection"),
	n3: _( function(a) {
		var outs = [];
		this.forEach( function(i) {
			if(typeof i == 'function') return;
			if(i.id && i.id.nodeType() == 'IRI') return outs.push( i.id.n3() );
			if(!i.nodeType) exports.setObjectProperties(i);
			outs.push(i.n3(a))
		});
		return this.list ? "( " + outs.join(" ") + " )" : outs.join(", ");
	})
};

exports.setArrayProperties = function(o){
	Object.defineProperties(o, ArrayProperties);
}

// Boolean
var BooleanProperties = {
	datatype: _( env.resolve("xsd:boolean") ),
	value: _getter(function(){return this;}),
	nodeType: _( function() { return "TypedLiteral"} ),
	n3: _( function() { return this.valueOf() } ),
	toNT: _( function() { return '"' + this.valueOf() + '"' + "^^<" + this.type + '>' } ),
	toCanonical: _( function() { return this.toNT() } )
};
exports.setBooleanProperties = function(o){
	Object.defineProperties(o, BooleanProperties);
}

// Date
var DateProperties = {
	datatype: _( env.resolve("xsd:dateTime") ),
	value: _getter(function(){return this;}),
	nodeType: _( function() { return "TypedLiteral"} ),
	n3: _( function() {
		return '"' + this.getUTCFullYear()+'-' + pad(this.getUTCMonth()+1)+'-' + pad(this.getUTCDate())+'T'
		+ pad(this.getUTCHours())+':' + pad(this.getUTCMinutes())+':' + pad(this.getUTCSeconds())+'Z"^^<' + this.type + '>';
	}),
	toNT: _( function() { return this.n3() } ),
	toCanonical: _( function() { return this.n3() } )
}
exports.setDateProperties = function(o){
	Object.defineProperties(Date.prototype, o);
}

// Number
var INTEGER = new RegExp("^(-|\\+)?[0-9]+$", "");
var DOUBLE = new RegExp("^(-|\\+)?(([0-9]+\\.[0-9]*[eE]{1}(-|\\+)?[0-9]+)|(\\.[0-9]+[eE]{1}(-|\\+)?[0-9]+)|([0-9]+[eE]{1}(-|\\+)?[0-9]+))$", "");
var DECIMAL = new RegExp("^(-|\\+)?[0-9]*\\.[0-9]+?$", "");
var NumberProperties = {
	datatype: {
		configurable : false, enumerable: false,
		get: function() {
			if(this == Number.POSITIVE_INFINITY) return env.resolve('xsd:double');
			if(this == Number.NEGATIVE_INFINITY) return env.resolve('xsd:double');
			if(isNaN(this)) return env.resolve('xsd:double');
			var n = this.toString();
			if(INTEGER.test(n)) return env.resolve('xsd:integer');
			if(DECIMAL.test(n)) return env.resolve('xsd:decimal');
			if(DOUBLE.test(n)) return env.resolve('xsd:double');
		}
	},
	value: 	 _getter(function(){return this;}),
	nodeType: _( function() { return "TypedLiteral" } ),
	n3: _( function() {
		if(this == Number.POSITIVE_INFINITY) return '"INF"^^<' + env.resolve('xsd:double') + '>';
		if(this == Number.NEGATIVE_INFINITY) return '"-INF"^^<' + env.resolve('xsd:double') + '>';
		if(isNaN(this)) return '"NaN"^^<' + 'xsd:double'.resolve() + '>';
		return this.toString();
	}),
	toNT: _( function() {
		if(this == Number.POSITIVE_INFINITY) return '"INF"^^<' + env.resolve('xsd:double') + '>';
		if(this == Number.NEGATIVE_INFINITY) return '"-INF"^^<' + env.resolve('xsd:double') + '>';
		if(isNaN(this)) return '"NaN"^^<' + env.resolve('xsd:double') + '>';
		return '"' + this.toString() + '"' + "^^<" + this.type + '>';
	}),
	toCanonical: _( function() { return this.nt() } ),
	toTL: _( function() { return this.nt() } )
}
exports.setNumberProperties = function(o){
	Object.defineProperties(o, NumberProperties);
}

exports.toStruct = function(o){
	var r;
	if(typeof o=='string'||o instanceof String){
		r = new String(o);
		api.setStringProperties(r);
	}else if(o instanceof Array){
		r = new Array(o);
		api.setArrayProperties(r);
	}else if(typeof o=='boolean'||o instanceof Boolean){
		r = new Boolean(o);
		api.setBooleanProperties(r);
	}else if(o instanceof Date){
		r = new Date(o);
		api.setNumberProperties(r);
	}else if(typeof o=='number'||o instanceof Number){
		r = new Number(o);
		api.setNumberProperties(r);
	}else{
		r = new Object(o);
	}
	api.setObjectProperties(r);
	return r;
}

// Sometimes the standard API context isn't global, and an Object in one context isn't an Object in another.
// For these cases, you'll need to call these functions by hand.
exports.setBuiltins = function setBuiltins(){
	exports.setObjectProperties(Object.prototype);
	exports.setStringProperties(String.prototype);
	exports.setArrayProperties(Array.prototype);
	exports.setBooleanProperties(Boolean.prototype);
	exports.setDateProperties(Date.prototype);
	exports.setNumberProperties(Number.prototype);
}
<commit_msg>Patch some Date Builtins bugs<commit_after>var Triple = require("./RDFNode.js").Triple;
var IndexedGraph = require("./IndexedGraph.js").IndexedGraph;
var RDFEnvironment = require("./RDFEnvironment.js").RDFEnvironment;
var RDFNodeEquals = require('./RDFNode.js').RDFNodeEquals;
var BlankNode = require("./RDFNode.js").BlankNode;

function _(v) { return { writable:false, configurable:false, enumerable:false, value:v } }
function _getter(v) { return { configurable:false, enumerable:false, get:v } }
function prop(p,l) {
	if(p == 'a') return 'rdf:type';
	p = p.replace('$',':');
	if(p.indexOf(':') == -1) p = env.resolve(p,l)||p;
	return p;
};
function pad(v,l){
	return ('0000'+v).substr(-(l||2));
}

var env = exports.environment = String.prototype.profile = new RDFEnvironment;
require('./Default.js').loadDefaultPrefixMap(env);

// N-Triples encoder
function encodeString(s) {
	var out = "";
	var skip = false;
	var _g1 = 0, _g = s.length;
	while(_g1 < _g) {
		var i = _g1++;
		if(!skip) {
			var code = s.charCodeAt(i);
			if(55296 <= code && code <= 56319) {
				var low = s.charCodeAt(i + 1);
				code = (code - 55296) * 1024 + (low - 56320) + 65536;
				skip = true
			}
			if(code > 1114111) { throw new Error("Char out of range"); }
			var hex = "00000000".concat((new Number(code)).toString(16).toUpperCase());
			if(code >= 65536) {
				out += "\\U" + hex.slice(-8)
			} else {
				if(code >= 127 || code <= 31) {
					switch(code) {
						case 9:	out += "\\t"; break;
						case 10: out += "\\n"; break;
						case 13: out += "\\r"; break;
						default: out += "\\u" + hex.slice(-4); break
					}
				} else {
					switch(code) {
						case 34: out += '\\"'; break;
						case 92: out += "\\\\"; break;
						default: out += s.charAt(i); break
					}
				}
			}
		} else {
			skip = !skip
		}
	}
	return out
};

// All
var ObjectProperties = {
	equals: _(RDFNodeEquals),
	ref: _( function(id) {
		var ref = arguments.callee;
		Object.defineProperties(this, {
			id: _( id ? id.resolve() : (new BlankNode).valueOf() ),
			n3: _( function(a) {
				var outs = [], o = this, map = o.aliasmap || a;
				Object.keys(this).forEach(function(p) {
					if(typeof o[p] == 'function') return;
					if(o[p].id && o[p].id.nodeType() == 'IRI') return outs.push( prop(p,map) + ' ' + o[p].id.n3() );
					if(!o[p].nodeType && !o[p].id) ref.call(o[p]);
					outs.push( prop(p, map) + ' ' + o[p].n3(map) );
				});
				outs = outs.join(";\n	");
				return id ? this.id.n3() + ' ' + outs + ' .' : '[ ' + outs + ' ]';
			}),
			toNT: _( function(a) {
				return this.graphify(a).toArray().join("\n");
			}),
			graphify: _( function(a) {
				var graph = new IndexedGraph;
				var o = this
				var map = o.aliasmap || a;
				function graphify(s1,p1,o1) {
					if(typeof(o1)=='function' || typeof(o1)=='undefined') return;
					if(!o1.nodeType && !o1.id && typeof(o1)!="string") ref.call(o1); // If the Object doesn't have a bnode, give it one
					if(o1.id) {
						// o1 is an Object, add triple and child triples
						graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), o1.id.resolve() ) );
						graph.merge( o1.graphify() );
					} else if(typeof(o1)=="string") {
						// o1 is a URI
						graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), o1.resolve() ) );
					} else if(!Array.isArray(o1)) {
						// o1 is a literal
						graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), o1 ) );
					} else if(Array.isArray(o1)) {
						// o1 is a Collection or a multi-valued property
						if(!o1.list) {
							// o1 is a multi-valued property
							o1.forEach( function(i) { graphify(s1.resolve(), p1.resolve(), i) });
						} else {
							// o1 is an rdf:Collection
							if(o1.length == 0) {
								graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), env.resolve("rdf:nil") ) );
							} else {
								var b = ref.call({}); // Generate bnode
								graph.add( new Triple(s1.resolve(), prop(p1,map).resolve(), b.id.resolve() ) );
								o1.forEach( function(i,x) {
									graphify(b.id, env.resolve('rdf:first'), i );
									var n = ref.call({});
									graph.add( new Triple(b.id.resolve(), 'rdf:rest'.resolve(), (x == o1.length-1) ? env.resolve('rdf:nil') : n.id.resolve() ) );
									b = n;
								});
							}
						}
					}
				}
				if(typeof(id)=="object") throw new Error("Not an object: "+require('util').inspect(this));
				Object.keys(this).forEach(function(p) { graphify(o.id, p, o[p]) });
				return graph;
			}),
			using: _( function() {
				Object.defineProperty(this,'aliasmap',_(Array.prototype.slice.call(arguments)));
				return this;
			})
		});
		return this;
	}),
};
exports.setObjectProperties = function(o){
	Object.defineProperties(o, ObjectProperties);
}

// String
var StringProperties = {
	tl: _( function(t) {
		return env.createLiteral(this.toString(), null, t);
	}),
	l: _( function(l) {
		return env.createLiteral(this.toString(), l, null);
	}),
	resolve: _( function() {
		if(this.indexOf(':')<0 || this.indexOf("//")>=0 ) return this.toString();
		return env.resolve(this)||this.toString();
	}),
	value: _getter(function(){return this.toString();}),
	nodeType: _( function() {
		//if(this.type) return 'TypedLiteral';
		//if(this.language || this.indexOf(' ') >= 0 || this.indexOf(':') == -1 ) return 'PlainLiteral';
		if(this.substr(0,2) == '_:') return 'BlankNode';
		return 'IRI';
	}),
	n3: _( function() {
		switch(this.nodeType()) {
			case 'PlainLiteral': return ('"' + encodeString(this) + '"' + ( this.language ? '@' + this.language : '')).toString();
			case 'IRI':
				var resolved = this.resolve();
				return (resolved == this) ? "<" + encodeString(resolved) + ">" : this.toString();
			case 'BlankNode': return this.toString();
			case 'TypedLiteral':
				if(this.type.resolve() == env.resolve("rdf:PlainLiteral")) return '"' + encodeString(this) + '"';
				return '"' + encodeString(this) + '"^^' + this.type.n3();
		}
	}),
	toNT: _( function() {
		switch(this.nodeType()) {
			case 'PlainLiteral': return ('"' + encodeString(this) + '"' + ( this.language ? '@' + this.language : '')).toString();
			case 'IRI': return "<" + encodeString(this.resolve()) + ">";
			case 'BlankNode': return this.toString();
			case 'TypedLiteral':
				if(this.type.resolve() == env.resolve("rdf:PlainLiteral")) return '"' + encodeString(this) + '"';
				return '"' + encodeString(this) + '"^^' + this.type.n3();
		}
	}),
	toCanonical: _( function() { return this.n3() } )
};
exports.setStringProperties = function(o){
	Object.defineProperties(o, StringProperties);
}

// Array
var ArrayProperties = {
	list: _(false),
	toList: _(function() {
		this.list = true;
		return this;
	}),
	nodeType: _("Collection"),
	n3: _( function(a) {
		var outs = [];
		this.forEach( function(i) {
			if(typeof i == 'function') return;
			if(i.id && i.id.nodeType() == 'IRI') return outs.push( i.id.n3() );
			if(!i.nodeType) exports.setObjectProperties(i);
			outs.push(i.n3(a))
		});
		return this.list ? "( " + outs.join(" ") + " )" : outs.join(", ");
	})
};

exports.setArrayProperties = function(o){
	Object.defineProperties(o, ArrayProperties);
}

// Boolean
var BooleanProperties = {
	datatype: _( env.resolve("xsd:boolean") ),
	value: _getter(function(){return this;}),
	nodeType: _( function() { return "TypedLiteral"} ),
	n3: _( function() { return this.valueOf() } ),
	toNT: _( function() { return '"' + this.valueOf() + '"' + "^^<" + this.type + '>' } ),
	toCanonical: _( function() { return this.toNT() } )
};
exports.setBooleanProperties = function(o){
	Object.defineProperties(o, BooleanProperties);
}

// Date
var DateProperties = {
	datatype: _( env.resolve("xsd:dateTime") ),
	value: _getter(function(){return this;}),
	nodeType: _( function() { return "TypedLiteral"} ),
	n3: _( function() {
		return '"' + this.getUTCFullYear()+'-' + pad(this.getUTCMonth()+1)+'-' + pad(this.getUTCDate())+'T'
		+ pad(this.getUTCHours())+':' + pad(this.getUTCMinutes())+':' + pad(this.getUTCSeconds())+'Z"^^<' + this.type + '>';
	}),
	toNT: _( function() { return this.n3() } ),
	toCanonical: _( function() { return this.n3() } )
}
exports.setDateProperties = function(o){
	Object.defineProperties(o, DateProperties);
}

// Number
var INTEGER = new RegExp("^(-|\\+)?[0-9]+$", "");
var DOUBLE = new RegExp("^(-|\\+)?(([0-9]+\\.[0-9]*[eE]{1}(-|\\+)?[0-9]+)|(\\.[0-9]+[eE]{1}(-|\\+)?[0-9]+)|([0-9]+[eE]{1}(-|\\+)?[0-9]+))$", "");
var DECIMAL = new RegExp("^(-|\\+)?[0-9]*\\.[0-9]+?$", "");
var NumberProperties = {
	datatype: {
		configurable : false, enumerable: false,
		get: function() {
			if(this == Number.POSITIVE_INFINITY) return env.resolve('xsd:double');
			if(this == Number.NEGATIVE_INFINITY) return env.resolve('xsd:double');
			if(isNaN(this)) return env.resolve('xsd:double');
			var n = this.toString();
			if(INTEGER.test(n)) return env.resolve('xsd:integer');
			if(DECIMAL.test(n)) return env.resolve('xsd:decimal');
			if(DOUBLE.test(n)) return env.resolve('xsd:double');
		}
	},
	value: 	 _getter(function(){return this;}),
	nodeType: _( function() { return "TypedLiteral" } ),
	n3: _( function() {
		if(this == Number.POSITIVE_INFINITY) return '"INF"^^<' + env.resolve('xsd:double') + '>';
		if(this == Number.NEGATIVE_INFINITY) return '"-INF"^^<' + env.resolve('xsd:double') + '>';
		if(isNaN(this)) return '"NaN"^^<' + 'xsd:double'.resolve() + '>';
		return this.toString();
	}),
	toNT: _( function() {
		if(this == Number.POSITIVE_INFINITY) return '"INF"^^<' + env.resolve('xsd:double') + '>';
		if(this == Number.NEGATIVE_INFINITY) return '"-INF"^^<' + env.resolve('xsd:double') + '>';
		if(isNaN(this)) return '"NaN"^^<' + env.resolve('xsd:double') + '>';
		return '"' + this.toString() + '"' + "^^<" + this.type + '>';
	}),
	toCanonical: _( function() { return this.nt() } ),
	toTL: _( function() { return this.nt() } )
}
exports.setNumberProperties = function(o){
	Object.defineProperties(o, NumberProperties);
}

exports.toStruct = function(o){
	var r;
	if(typeof o=='string'||o instanceof String){
		r = new String(o);
		api.setStringProperties(r);
	}else if(o instanceof Array){
		r = new Array(o);
		api.setArrayProperties(r);
	}else if(typeof o=='boolean'||o instanceof Boolean){
		r = new Boolean(o);
		api.setBooleanProperties(r);
	}else if(o instanceof Date){
		r = new Date(o);
		api.setNumberProperties(r);
	}else if(typeof o=='number'||o instanceof Number){
		r = new Number(o);
		api.setNumberProperties(r);
	}else{
		r = new Object(o);
	}
	api.setObjectProperties(r);
	return r;
}

// Sometimes the standard API context isn't global, and an Object in one context isn't an Object in another.
// For these cases, you'll need to call these functions by hand.
exports.setBuiltins = function setBuiltins(){
	exports.setObjectProperties(Object.prototype);
	exports.setStringProperties(String.prototype);
	exports.setArrayProperties(Array.prototype);
	exports.setBooleanProperties(Boolean.prototype);
	exports.setDateProperties(Date.prototype);
	exports.setNumberProperties(Number.prototype);
}
<|endoftext|>


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

/**
 * @fileoverview Math blocks for Blockly.
 * @author fraser@google.com (Neil Fraser)
 * Due to the frequency of long strings, the 80-column wrap rule need not apply
 * to language files.
 */

if (!Blockly.Language) {
  Blockly.Language = {};
}

Blockly.Language.math_number = {
  // Numeric value.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Number',
  init: function() {
    this.setColour(230);
    this.addTitle(new Blockly.FieldTextInput('0', function(text) {
      // Ensure that only a number may be entered.
      // TODO: Handle cases like 'o', 'ten', '1,234', '3,14', etc.
      var n = window.parseFloat(text || 0);
      return window.isNaN(n) ? null : String(n);
    }));
    this.setOutput(true);
    this.setTooltip('A number.');
  }
};

Blockly.Language.math_arithmetic = {
  // Basic arithmetic operator.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Arithmetic',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    this.addInput('', '', Blockly.INPUT_VALUE);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [
          thisBlock.MSG_ADD,
          thisBlock.MSG_MINUS,
          thisBlock.MSG_MULTIPLY,
          thisBlock.MSG_DIVIDE,
          thisBlock.MSG_POW
        ];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setInputsInline(true);
    this.setTooltip(function() {
      switch (thisBlock.getValueLabel(1)) {
        case thisBlock.MSG_ADD:
          return 'Return the sum of the two numbers.';
        case thisBlock.MSG_MINUS:
          return 'Return the difference of the two numbers.';
        case thisBlock.MSG_MULTIPLY:
          return 'Return the product of the two numbers.';
        case thisBlock.MSG_DIVIDE:
          return 'Return the quotient of the two numbers.';
        case thisBlock.MSG_POW:
          return 'Return the first number raised to\nthe power of the second number.';
      }
      return '';
    });
  },
  MSG_ADD: '+',
  MSG_MINUS: '-',
  MSG_MULTIPLY: '\u00D7',
  MSG_DIVIDE: '\u00F7',
  MSG_POW: '^'
};

Blockly.Language.math_change = {
  // Add to a variable in place.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Negation',
  init: function() {
    this.setColour(230);
    this.addTitle('change');
    this.addTitle(new Blockly.FieldDropdown(
        Blockly.Variables.dropdownCreate, Blockly.Variables.dropdownChange))
        .setText('item');
    this.addInput('by', '', Blockly.INPUT_VALUE);
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    // Assign 'this' to a variable for use in the tooltip closure below.
    var thisBlock = this;
    this.setTooltip(function() {
      return 'Add a number to variable "' + thisBlock.getTitleText(1) + '".';
    });
  },
  getVars: function() {
    return [this.getTitleText(1)];
  },
  renameVar: function(oldName, newName) {
    if (Blockly.Variables.nameEquals(oldName, this.getTitleText(1))) {
      this.setTitleText(newName, 1);
    }
  }
};

Blockly.Language.math_single = {
  // Advanced math operators with single operand.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Square_root',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_ROOT,
              thisBlock.MSG_ABS,
              thisBlock.MSG_NEG,
              thisBlock.MSG_LN,
              thisBlock.MSG_LOG10,
              thisBlock.MSG_EXP,
              thisBlock.MSG_10POW];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setTooltip(function() {
      switch (thisBlock.getValueLabel(0)) {
        case thisBlock.MSG_ROOT:
          return 'Return the square root of a number.';
        case thisBlock.MSG_ABS:
          return 'Return the absolute value of a number.';
        case thisBlock.MSG_NEG:
          return 'Return the negation of a number.';
        case thisBlock.MSG_LN:
          return 'Return the natural logarithm of a number.';
        case thisBlock.MSG_LOG10:
          return 'Return the base 10 logarithm of a number.';
        case thisBlock.MSG_EXP:
          return 'Return e to the power of a number.';
        case thisBlock.MSG_10POW:
          return 'Return 10 to the power of a number.';
      }
      return '';
    });
  },
  MSG_ROOT: 'square root',
  MSG_ABS: 'absolute',
  MSG_NEG: '-',
  MSG_LN: 'ln',
  MSG_LOG10: 'log10',
  MSG_EXP: 'e^',
  MSG_10POW: '10^'
};

Blockly.Language.math_round = {
  // Rounding functions.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Rounding',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_ROUND,
              thisBlock.MSG_ROUNDUP,
              thisBlock.MSG_ROUNDDOWN];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setTooltip('Round a number up or down.');
  },
  MSG_ROUND: 'round',
  MSG_ROUNDUP: 'round up',
  MSG_ROUNDDOWN: 'round down'
};

Blockly.Language.math_trig = {
  // Trigonometry operators.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Square_root',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_SIN,
              thisBlock.MSG_COS,
              thisBlock.MSG_TAN,
              thisBlock.MSG_ASIN,
              thisBlock.MSG_ACOS,
              thisBlock.MSG_ATAN];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setTooltip(function() {
      switch (thisBlock.getValueLabel(0)) {
        case thisBlock.MSG_SIN:
          return 'Return the sine of a degree.';
        case thisBlock.MSG_COS:
          return 'Return the cosine of a degree.';
        case thisBlock.MSG_TAN:
          return 'Return the tangent of a degree.';
        case thisBlock.MSG_ASIN:
          return 'Return the arcsine of a number.';
        case thisBlock.MSG_ACOS:
          return 'Return the arccosine of a number.';
        case thisBlock.MSG_ATAN:
          return 'Return the arctangent of a number.';
      }
      return '';
    });
  },
  MSG_SIN: 'sin',
  MSG_COS: 'cos',
  MSG_TAN: 'tan',
  MSG_ASIN: 'asin',
  MSG_ACOS: 'acos',
  MSG_ATAN: 'atan'
};

Blockly.Language.math_on_list = {
  // Evaluate a list of numbers to return sum, average, min, max, etc.
  // Some functions also work on text (min, max, mode, median).
  category: 'Math',
  helpUrl: '',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_SUM,
              thisBlock.MSG_MIN,
              thisBlock.MSG_MAX,
              thisBlock.MSG_AVERAGE,
              thisBlock.MSG_MEDIAN,
              thisBlock.MSG_MODE,
              thisBlock.MSG_STD_DEV,
              thisBlock.MSG_RANDOM_ITEM
              ];
    });
    this.addTitle(dropdown);
    this.addInput('of list', '', Blockly.INPUT_VALUE);
    this.setTooltip('Evaluate a list of numbers and return a member,\nor an aggregated result.');
  },
  MSG_SUM: 'sum',
  MSG_MIN: 'min',
  MSG_MAX: 'max',
  MSG_AVERAGE: 'average',
  MSG_MEDIAN: 'median',
  MSG_MODE: 'mode',
  MSG_STD_DEV: 'standard deviation',
  MSG_RANDOM_ITEM: 'random item'
};

Blockly.Language.math_modulo = {
  // Remainder of a division.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Modulo_operation',
  init: function() {
    this.setColour(230);
    this.setOutput(true);
    this.addInput('remainder of', '', Blockly.INPUT_VALUE);
    this.addInput('\u00F7', '', Blockly.INPUT_VALUE);
    this.setInputsInline(true);
    this.setTooltip('Return the remainder of dividing both numbers.');
  }
};

Blockly.Language.math_random_int = {
  // Random integer between [X] and [Y].
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Random_number_generation',
  init: function() {
    this.setColour(230);
    this.setOutput(true);
    this.addTitle('random integer');
    this.addInput('from', '', Blockly.INPUT_VALUE);
    this.addInput('to', '', Blockly.INPUT_VALUE);
    // TODO: Ensure that only number blocks may used to set range.
    this.setInputsInline(true);
    this.setTooltip('Return a random integer between the two\n specified limits, inclusive.');
  }
};

Blockly.Language.math_random_float = {
  // Random fraction between 0 and 1.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Random_number_generation',
  init: function() {
    this.setColour(230);
    this.setOutput(true);
    this.addTitle('random fraction');
    this.setTooltip('Return a random fraction between\n0.0 (inclusive) and 1.0 (exclusive).');
  }
};
<commit_msg>fix merge conflict<commit_after>/**
 * Visual Blocks Language
 *
 * Copyright 2012 Google Inc.
 * http://code.google.com/p/google-blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Math blocks for Blockly.
 * @author fraser@google.com (Neil Fraser)
 * Due to the frequency of long strings, the 80-column wrap rule need not apply
 * to language files.
 */

if (!Blockly.Language) {
  Blockly.Language = {};
}

Blockly.Language.math_number = {
  // Numeric value.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Number',
  init: function() {
    this.setColour(230);
    this.addTitle(new Blockly.FieldTextInput('0.0', function(text) {
      // Ensure that only a number may be entered.
      // TODO: Handle cases like 'o', 'ten', '1,234', '3,14', etc.
      var n = window.parseFloat(text || 0);
      return window.isNaN(n) ? null : String(n);
    }));
    this.setOutput(true);
    this.setTooltip('A number.');
  }
};

Blockly.Language.math_integer = {
  // Numeric value.
  category: 'Math',
  semantics: { type : "integer" },
  helpUrl: 'http://en.wikipedia.org/wiki/Integer',
  init: function() {
    this.setColour('baby');
    this.addTitle(new Blockly.FieldTextInput('0', function(text) {
      // Ensure that only a number may be entered.
      // TODO: Handle cases like 'o', 'ten', '1,234', '3,14', etc.
      var n = window.parseInt(text || 0, 10);
      return window.isNaN(n) ? null : String(n);
    }));
    this.setOutput(true);
    this.setTooltip('A number.');
  }
};

Blockly.Language.math_arithmetic = {
  // Basic arithmetic operator.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Arithmetic',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    this.addInput('', '', Blockly.INPUT_VALUE);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [
          thisBlock.MSG_ADD,
          thisBlock.MSG_MINUS,
          thisBlock.MSG_MULTIPLY,
          thisBlock.MSG_DIVIDE,
          thisBlock.MSG_POW
        ];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setInputsInline(true);
    this.setTooltip(function() {
      switch (thisBlock.getValueLabel(1)) {
        case thisBlock.MSG_ADD:
          return 'Return the sum of the two numbers.';
        case thisBlock.MSG_MINUS:
          return 'Return the difference of the two numbers.';
        case thisBlock.MSG_MULTIPLY:
          return 'Return the product of the two numbers.';
        case thisBlock.MSG_DIVIDE:
          return 'Return the quotient of the two numbers.';
        case thisBlock.MSG_POW:
          return 'Return the first number raised to\nthe power of the second number.';
      }
      return '';
    });
  },
  MSG_ADD: '+',
  MSG_MINUS: '-',
  MSG_MULTIPLY: '\u00D7',
  MSG_DIVIDE: '\u00F7',
  MSG_POW: '^'
};

Blockly.Language.math_change = {
  // Add to a variable in place.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Negation',
  init: function() {
    this.setColour(230);
    this.addTitle('change');
    this.addTitle(new Blockly.FieldDropdown(
        Blockly.Variables.dropdownCreate, Blockly.Variables.dropdownChange))
        .setText('item');
    this.addInput('by', '', Blockly.INPUT_VALUE);
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    // Assign 'this' to a variable for use in the tooltip closure below.
    var thisBlock = this;
    this.setTooltip(function() {
      return 'Add a number to variable "' + thisBlock.getTitleText(1) + '".';
    });
  },
  getVars: function() {
    return [this.getTitleText(1)];
  },
  renameVar: function(oldName, newName) {
    if (Blockly.Variables.nameEquals(oldName, this.getTitleText(1))) {
      this.setTitleText(newName, 1);
    }
  }
};

Blockly.Language.math_single = {
  // Advanced math operators with single operand.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Square_root',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_ROOT,
              thisBlock.MSG_ABS,
              thisBlock.MSG_NEG,
              thisBlock.MSG_LN,
              thisBlock.MSG_LOG10,
              thisBlock.MSG_EXP,
              thisBlock.MSG_10POW];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setTooltip(function() {
      switch (thisBlock.getValueLabel(0)) {
        case thisBlock.MSG_ROOT:
          return 'Return the square root of a number.';
        case thisBlock.MSG_ABS:
          return 'Return the absolute value of a number.';
        case thisBlock.MSG_NEG:
          return 'Return the negation of a number.';
        case thisBlock.MSG_LN:
          return 'Return the natural logarithm of a number.';
        case thisBlock.MSG_LOG10:
          return 'Return the base 10 logarithm of a number.';
        case thisBlock.MSG_EXP:
          return 'Return e to the power of a number.';
        case thisBlock.MSG_10POW:
          return 'Return 10 to the power of a number.';
      }
      return '';
    });
  },
  MSG_ROOT: 'square root',
  MSG_ABS: 'absolute',
  MSG_NEG: '-',
  MSG_LN: 'ln',
  MSG_LOG10: 'log10',
  MSG_EXP: 'e^',
  MSG_10POW: '10^'
};

Blockly.Language.math_round = {
  // Rounding functions.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Rounding',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_ROUND,
              thisBlock.MSG_ROUNDUP,
              thisBlock.MSG_ROUNDDOWN];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setTooltip('Round a number up or down.');
  },
  MSG_ROUND: 'round',
  MSG_ROUNDUP: 'round up',
  MSG_ROUNDDOWN: 'round down'
};

Blockly.Language.math_trig = {
  // Trigonometry operators.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Square_root',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_SIN,
              thisBlock.MSG_COS,
              thisBlock.MSG_TAN,
              thisBlock.MSG_ASIN,
              thisBlock.MSG_ACOS,
              thisBlock.MSG_ATAN];
    });
    this.addInput(dropdown, '', Blockly.INPUT_VALUE);
    this.setTooltip(function() {
      switch (thisBlock.getValueLabel(0)) {
        case thisBlock.MSG_SIN:
          return 'Return the sine of a degree.';
        case thisBlock.MSG_COS:
          return 'Return the cosine of a degree.';
        case thisBlock.MSG_TAN:
          return 'Return the tangent of a degree.';
        case thisBlock.MSG_ASIN:
          return 'Return the arcsine of a number.';
        case thisBlock.MSG_ACOS:
          return 'Return the arccosine of a number.';
        case thisBlock.MSG_ATAN:
          return 'Return the arctangent of a number.';
      }
      return '';
    });
  },
  MSG_SIN: 'sin',
  MSG_COS: 'cos',
  MSG_TAN: 'tan',
  MSG_ASIN: 'asin',
  MSG_ACOS: 'acos',
  MSG_ATAN: 'atan'
};

Blockly.Language.math_on_list = {
  // Evaluate a list of numbers to return sum, average, min, max, etc.
  // Some functions also work on text (min, max, mode, median).
  category: 'Math',
  helpUrl: '',
  init: function() {
    // Assign 'this' to a variable for use in the closures below.
    var thisBlock = this;
    this.setColour(230);
    this.setOutput(true);
    var dropdown = new Blockly.FieldDropdown(function() {
      return [thisBlock.MSG_SUM,
              thisBlock.MSG_MIN,
              thisBlock.MSG_MAX,
              thisBlock.MSG_AVERAGE,
              thisBlock.MSG_MEDIAN,
              thisBlock.MSG_MODE,
              thisBlock.MSG_STD_DEV,
              thisBlock.MSG_RANDOM_ITEM
              ];
    });
    this.addTitle(dropdown);
    this.addInput('of list', '', Blockly.INPUT_VALUE);
    this.setTooltip('Evaluate a list of numbers and return a member,\nor an aggregated result.');
  },
  MSG_SUM: 'sum',
  MSG_MIN: 'min',
  MSG_MAX: 'max',
  MSG_AVERAGE: 'average',
  MSG_MEDIAN: 'median',
  MSG_MODE: 'mode',
  MSG_STD_DEV: 'standard deviation',
  MSG_RANDOM_ITEM: 'random item'
};

Blockly.Language.math_modulo = {
  // Remainder of a division.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Modulo_operation',
  init: function() {
    this.setColour(230);
    this.setOutput(true);
    this.addInput('remainder of', '', Blockly.INPUT_VALUE);
    this.addInput('\u00F7', '', Blockly.INPUT_VALUE);
    this.setInputsInline(true);
    this.setTooltip('Return the remainder of dividing both numbers.');
  }
};

Blockly.Language.math_random_int = {
  // Random integer between [X] and [Y].
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Random_number_generation',
  init: function() {
    this.setColour(230);
    this.setOutput(true);
    this.addTitle('random integer');
    this.addInput('from', '', Blockly.INPUT_VALUE);
    this.addInput('to', '', Blockly.INPUT_VALUE);
    // TODO: Ensure that only number blocks may used to set range.
    this.setInputsInline(true);
    this.setTooltip('Return a random integer between the two\n specified limits, inclusive.');
  }
};

Blockly.Language.math_random_float = {
  // Random fraction between 0 and 1.
  category: 'Math',
  helpUrl: 'http://en.wikipedia.org/wiki/Random_number_generation',
  init: function() {
    this.setColour(230);
    this.setOutput(true);
    this.addTitle('random fraction');
    this.setTooltip('Return a random fraction between\n0.0 (inclusive) and 1.0 (exclusive).');
  }
};
<|endoftext|>


<commit_before>/*-
 * --BEGIN_LICENSE--
 * Competency and Skills System
 * -----
 * Copyright (C) 2015 - 2018 Eduworks Corporation and other contributing parties.
 * -----
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * --END_LICENSE--
 */
var $ = null;
var document = null;
var window = {};
var localStorage = {};

var setTimeout = function (f, time) {
    if (f != null)
        f();
}

console = {
    log: function (s) {
        debug(s);
    },

    error: function (s) {
        debug("error:" + s);
    }
};

load("classpath:stjs.js");
load("classpath:blobHelper.js");
load("classpath:formdata.js");
load("classpath:random.js");
load("classpath:ec.base.js");
load("classpath:forge/forge.min.js");
load("classpath:ec.crypto.js");
load("classpath:org.json-ld.js");
load("classpath:org.cassproject.schema.general.js");
load("classpath:org.schema.js");
load("classpath:org.w3.skos.js");
load("classpath:org.cassproject.schema.ebac.js");
load("classpath:org.cassproject.schema.cass.js");
load("classpath:ebac.identity.js");
load("classpath:ebac.repository.js");
load("classpath:cass.competency.js");
load("classpath:cass.rollup.js");

EcRepository.caching = true;
EcRemote.async = false;
EcIdentityManager.async = false;

var repo = new EcRepository();
repo.selectedServer = "http://localhost:8080/api/";

if (java.lang.System.getenv("CASS_LOOPBACK") != null)
    repo.selectedServer = java.lang.System.getenv("CASS_LOOPBACK")

if (java.lang.System.getenv("ELASTICSEARCH_ENDPOINT") != null)
    elasticEndpoint = java.lang.System.getenv("ELASTICSEARCH_ENDPOINT");

thisEndpoint = function () {
    return repo.selectedServer;
}
repoEndpoint = function () {
    return repo.selectedServer;
}

var keyFor = function (filename) {
    if (fileExists(filename + ".pem"))
        return fileToString(fileLoad(filename + ".pem", false, true));
    if (fileExists("etc/" + filename + ".pem"))
        return fileToString(fileLoad("etc/" + filename + ".pem", false, true));
    if (!fileExists("etc"))
        createDirectory("etc");
    fileSave(EcPpk.generateKey().toPem(), "etc/" + filename + ".pem");
    return fileToString(fileLoad("etc/" + filename + ".pem", false, true));
}

function repoAutoDetect() {
    if (java.lang.System.getenv("CASS_LOOPBACK") != null)
        repo.selectedServer = java.lang.System.getenv("CASS_LOOPBACK");
    else
        repo.autoDetectRepository();

    if (java.lang.System.getenv("ELASTICSEARCH_ENDPOINT") != null)
        elasticEndpoint = java.lang.System.getenv("ELASTICSEARCH_ENDPOINT");

    console.log("Loopback: " + repo.selectedServer);
    console.log("Elasticsearch Endpoint: " + elasticEndpoint);
    console.log("Text Encoding: " + java.lang.System.getProperty("file.encoding"));
    console.log("Text Encoding: " + java.nio.charset.Charset.defaultCharset().toString());
}<commit_msg>Can get keys from environment variables.<commit_after>/*-
 * --BEGIN_LICENSE--
 * Competency and Skills System
 * -----
 * Copyright (C) 2015 - 2018 Eduworks Corporation and other contributing parties.
 * -----
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * --END_LICENSE--
 */
var $ = null;
var document = null;
var window = {};
var localStorage = {};

var setTimeout = function (f, time) {
    if (f != null)
        f();
}

console = {
    log: function (s) {
        debug(s);
    },

    error: function (s) {
        debug("error:" + s);
    }
};

load("classpath:stjs.js");
load("classpath:blobHelper.js");
load("classpath:formdata.js");
load("classpath:random.js");
load("classpath:ec.base.js");
load("classpath:forge/forge.min.js");
load("classpath:ec.crypto.js");
load("classpath:org.json-ld.js");
load("classpath:org.cassproject.schema.general.js");
load("classpath:org.schema.js");
load("classpath:org.w3.skos.js");
load("classpath:org.cassproject.schema.ebac.js");
load("classpath:org.cassproject.schema.cass.js");
load("classpath:ebac.identity.js");
load("classpath:ebac.repository.js");
load("classpath:cass.competency.js");
load("classpath:cass.rollup.js");

EcRepository.caching = true;
EcRemote.async = false;
EcIdentityManager.async = false;

var repo = new EcRepository();
repo.selectedServer = "http://localhost:8080/api/";

if (java.lang.System.getenv("CASS_LOOPBACK") != null)
    repo.selectedServer = java.lang.System.getenv("CASS_LOOPBACK")

if (java.lang.System.getenv("ELASTICSEARCH_ENDPOINT") != null)
    elasticEndpoint = java.lang.System.getenv("ELASTICSEARCH_ENDPOINT");

thisEndpoint = function () {
    return repo.selectedServer;
}
repoEndpoint = function () {
    return repo.selectedServer;
}

var keyFor = function (filename) {
    if (java.lang.System.getenv(filename) != null)
        return java.lang.System.getenv(filename);
    if (fileExists(filename + ".pem"))
        return fileToString(fileLoad(filename + ".pem", false, true));
    if (fileExists("etc/" + filename + ".pem"))
        return fileToString(fileLoad("etc/" + filename + ".pem", false, true));
    if (!fileExists("etc"))
        createDirectory("etc");
    fileSave(EcPpk.generateKey().toPem(), "etc/" + filename + ".pem");
    return fileToString(fileLoad("etc/" + filename + ".pem", false, true));
}

function repoAutoDetect() {
    if (java.lang.System.getenv("CASS_LOOPBACK") != null)
        repo.selectedServer = java.lang.System.getenv("CASS_LOOPBACK");
    else
        repo.autoDetectRepository();

    if (java.lang.System.getenv("ELASTICSEARCH_ENDPOINT") != null)
        elasticEndpoint = java.lang.System.getenv("ELASTICSEARCH_ENDPOINT");

    console.log("Loopback: " + repo.selectedServer);
    console.log("Elasticsearch Endpoint: " + elasticEndpoint);
    console.log("Text Encoding: " + java.lang.System.getProperty("file.encoding"));
    console.log("Text Encoding: " + java.nio.charset.Charset.defaultCharset().toString());
}<|endoftext|>


<commit_before>(function($) {
	$.jqplot.Dragable = function(options) {
	    this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false});
	    this.shapeRenderer = new $.jqplot.ShapeRenderer();
	    this.isDragging = false;
	    this._ctx;
	    this._elem;
	    this._point;
	    this._gridData;
	    this.color;
	    this.contstrainTo = 'none';  // 'x', 'y', or 'none';

	    $.extend(true, this, options);
	};

	// called with scope of plot
	$.jqplot.Dragable.init = function (target, data, options){
	    // add a dragable attribute to the plot
	    this.dragable = new $.jqplot.Dragable(options.dragable);
	};

	// called within scope of series
	$.jqplot.Dragable.parseOptions = function (defaults, options) {
	    this.isDragable = true;
	};

	// called within context of plot
	// create a copy of the overlay canvas which we can draw on.
	// insert it before the overlay, so the overlay will still capture events.
	$.jqplot.Dragable.postPlotDraw = function() {
	    this.dragable._elem = this.overlayCanvas._elem.clone();
	    this.dragable._elem.insertBefore(this.overlayCanvas._elem);
	    this.dragable._ctx = this.dragable._elem.get(0).getContext("2d");
	};

	$.jqplot.preInitHooks.push($.jqplot.Dragable.init);
	$.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Dragable.parseOptions);
	$.jqplot.postDrawHooks.push($.jqplot.Dragable.postPlotDraw);
	$.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
	$.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleDown]);
	$.jqplot.eventListenerHooks.push(['jqplotMouseUp', handleUp]);

    function initDragPoint(plot, neighbor) {
        var drag = plot.dragable;
        var ds = drag._series;
        var s = plot.series[neighbor.seriesIndex];

        // first, init the mark renderer for the dragged point
        var smr = s.markerRenderer;
        var mr = drag.markerRenderer;
        mr.style = smr.style;
        mr.lineWidth = smr.lineWidth + 2.5;
        mr.size = smr.size + 5;
        var rgba = $.jqplot.getColorComponents(smr.color);
        var alpha = rgba[3] - 0.4;
        var color = 'rgba('+rgba[0]+','+rgba[1]+','+rgba[2]+','+alpha+')';
        drag.color = color;
        mr.color = color;
        mr.init();

        var start = (neighbor.pointIndex > 0) ? neighbor.pointIndex - 1 : 0;
        var end = neighbor.pointIndex+2;
        drag._gridData = s.gridData.slice(start, end);
    };

	function handleMove(ev, gridpos, datapos, neighbor, plot) {
	    if (plot.dragable.isDragging) {
	        var drag = plot.dragable;
	        var dp = drag._point;
	        var gd = plot.series[dp.seriesIndex].gridData;

	        // compute the new grid position with any constraints.
	        var x = (drag.constrainTo == 'y') ? dp.gridData[0] : gridpos.x;
	        var y = (drag.constrainTo == 'x') ? dp.gridData[1] : gridpos.y;

	        // clear the canvas then redraw effect at new position.
	        var ctx = drag._ctx;
	        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

	        // adjust our gridData for the new mouse position
	        if (dp.pointIndex > 0) {
	            drag._gridData[1] = [x, y];
	        }
	        else {
	            drag._gridData[0] = [x, y];
	        }
	        plot.series[dp.seriesIndex].draw(drag._ctx, {gridData:drag._gridData, shadow:false});
	    }
	};

	function handleDown(ev, gridpos, datapos, neighbor, plot) {
	    var drag = plot.dragable;
	    if (neighbor != null) {
	        var s = plot.series[neighbor.seriesIndex];
	        if (s.isDragable && !drag.isDragging) {
	            drag._point = neighbor;
    	        drag.isDragging = true;
    	        initDragPoint(plot, neighbor);
    	        drag.markerRenderer.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], drag._ctx);
            }
	    }
	    // Just in case of a hickup, we'll clear the drag canvas and reset.
	    else {
	       var ctx = plot.dragable._ctx;
	       ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
	       plot.dragable.isDragging = false;
	    }
	};

	function handleUp(ev, gridpos, datapos, neighbor, plot) {
	    if (plot.dragable.isDragging) {
	        // clear the canvas
	        var ctx = plot.dragable._ctx;
	        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
	        plot.dragable.isDragging = false;
	        // redraw the series canvas at the new point.
	        var drag = plot.dragable;
	        var dp = drag._point;
	        var s = plot.series[dp.seriesIndex];
	        // compute the new grid position with any constraints.
	        var x = (drag.constrainTo == 'y') ? dp.data[0] : datapos[s.xaxis];
	        var y = (drag.constrainTo == 'x') ? dp.data[1] : datapos[s.yaxis];
            // var x = datapos[s.xaxis];
            // var y = datapos[s.yaxis];
            s.data[dp.pointIndex] = [x,y];
            plot.drawSeries(plot.seriesCanvas._ctx);
	        plot.dragable._point = null;
	    }
	};

})(jQuery);<commit_msg>Refactored so that dragable is per series.  Can set constraints or other options per series now.<commit_after>(function($) {
	$.jqplot.Dragable = function(options) {
	    this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false});
	    this.shapeRenderer = new $.jqplot.ShapeRenderer();
	    this.isDragging = false;
	    this._ctx;
	    this._elem;
	    this._point;
	    this._gridData;
	    this.color;
	    this.contstrainTo = 'none';  // 'x', 'y', or 'none';

	    $.extend(true, this, options);
	};

	function DragCanvas() {
	    this.isDragging = false;
	    this._ctx;
	    this._elem;
	    this._neighbor;
	}

    // // called with scope of plot
    // $.jqplot.Dragable.init = function (target, data, options){
    //     // add a dragable attribute to the plot
    //     this.dragable = new $.jqplot.Dragable(options.dragable);
    // };

	// called within scope of series
	$.jqplot.Dragable.parseOptions = function (defaults, options) {
	    this.dragable = new $.jqplot.Dragable(options.dragable);
	    this.isDragable = true;
	};

	// called within context of plot
	// create a copy of the overlay canvas which we can draw on.
	// insert it before the overlay, so the overlay will still capture events.
	$.jqplot.Dragable.postPlotDraw = function() {
	    this.dragCanvas = new DragCanvas();
	    this.dragCanvas._elem = this.overlayCanvas._elem.clone();
	    this.dragCanvas._elem.insertBefore(this.overlayCanvas._elem);
	    this.dragCanvas._ctx = this.dragCanvas._elem.get(0).getContext("2d");
	};

	//$.jqplot.preInitHooks.push($.jqplot.Dragable.init);
	$.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Dragable.parseOptions);
	$.jqplot.postDrawHooks.push($.jqplot.Dragable.postPlotDraw);
	$.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
	$.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleDown]);
	$.jqplot.eventListenerHooks.push(['jqplotMouseUp', handleUp]);

    function initDragPoint(plot, neighbor) {
        var s = plot.series[neighbor.seriesIndex];
        var drag = s.dragable;

        // first, init the mark renderer for the dragged point
        var smr = s.markerRenderer;
        var mr = drag.markerRenderer;
        mr.style = smr.style;
        mr.lineWidth = smr.lineWidth + 2.5;
        mr.size = smr.size + 5;
        var rgba = $.jqplot.getColorComponents(smr.color);
        var alpha = rgba[3] - 0.4;
        var color = 'rgba('+rgba[0]+','+rgba[1]+','+rgba[2]+','+alpha+')';
        drag.color = color;
        mr.color = color;
        mr.init();

        var start = (neighbor.pointIndex > 0) ? neighbor.pointIndex - 1 : 0;
        var end = neighbor.pointIndex+2;
        drag._gridData = s.gridData.slice(start, end);
    };

	function handleMove(ev, gridpos, datapos, neighbor, plot) {
	    if (plot.dragCanvas.isDragging) {
	        var dc = plot.dragCanvas;
	        var dp = dc._neighbor;
	        var drag = plot.series[dp.seriesIndex].dragable;
	        var gd = plot.series[dp.seriesIndex].gridData;

	        // compute the new grid position with any constraints.
	        var x = (drag.constrainTo == 'y') ? dp.gridData[0] : gridpos.x;
	        var y = (drag.constrainTo == 'x') ? dp.gridData[1] : gridpos.y;

	        // clear the canvas then redraw effect at new position.
	        var ctx = dc._ctx;
	        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

	        // adjust our gridData for the new mouse position
	        if (dp.pointIndex > 0) {
	            drag._gridData[1] = [x, y];
	        }
	        else {
	            drag._gridData[0] = [x, y];
	        }
	        plot.series[dp.seriesIndex].draw(dc._ctx, {gridData:drag._gridData, shadow:false});
	    }
	};

	function handleDown(ev, gridpos, datapos, neighbor, plot) {
	    var dc = plot.dragCanvas;
	    if (neighbor != null) {
	        var s = plot.series[neighbor.seriesIndex];
	        var drag = s.dragable;
	        if (s.isDragable && !dc.isDragging) {
	            dc._neighbor = neighbor;
    	        dc.isDragging = true;
    	        initDragPoint(plot, neighbor);
    	        drag.markerRenderer.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], dc._ctx);
            }
	    }
	    // Just in case of a hickup, we'll clear the drag canvas and reset.
	    else {
	       var ctx = dc._ctx;
	       ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
	       dc.isDragging = false;
	    }
	};

	function handleUp(ev, gridpos, datapos, neighbor, plot) {
	    if (plot.dragCanvas.isDragging) {
	        var dc = plot.dragCanvas;
	        // clear the canvas
	        var ctx = dc._ctx;
	        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
	        dc.isDragging = false;
	        // redraw the series canvas at the new point.
	        var dp = dc._neighbor;
	        var s = plot.series[dp.seriesIndex];
	        var drag = s.dragable;
	        // compute the new grid position with any constraints.
	        var x = (drag.constrainTo == 'y') ? dp.data[0] : datapos[s.xaxis];
	        var y = (drag.constrainTo == 'x') ? dp.data[1] : datapos[s.yaxis];
            // var x = datapos[s.xaxis];
            // var y = datapos[s.yaxis];
            s.data[dp.pointIndex] = [x,y];
            plot.drawSeries(plot.seriesCanvas._ctx);
	        dc._neighbor = null;
	    }
	};

})(jQuery);<|endoftext|>


<commit_before>const fs = require('fs-extra');
const elasticlunr = require('elasticlunr');
const Schema = require('./schema');
const Site = require('./site');
const path = require('path');
const apiSubDir = 'api/v1';
const AWS = require('aws-sdk');
const algoliasearch = require('algoliasearch');

class Search {

  constructor(site, config) {
    this.sitesDir = config.get('sitesDir');
    this.siteDir = path.join(this.sitesDir, site);
    this.schemasDir = config.get('schemasDir');
    this.siteInfo = new Site(site, config);
    this.schemaName = this.siteInfo.getConfigItem('schema');
    this.schema = new Schema(this.schemaName, config);
    this.searchConfig = this.siteInfo.getConfigItem('search');
    this.apiDir = path.join(config.get('buildDir'), site, apiSubDir);
  }

  init(callback) {
    callback();
  }

  prepareSearchFields(doc, toString) {
    const prepped = {};
    this.searchConfig.fields.forEach((field) => {
      if (toString) {
      prepped[field] = stringify(doc[field]);
      } else {
        prepped[field] = doc[field];
      }
    });
    prepped.identifier = doc.identifier;
    prepped.interra = doc.interra;
    prepped.modified = doc.modified;
    return prepped;
  }

  push(callback) {
    callback();
  }

  insertOne(callback) {
    callback();
  }

  insertMany() {}

  update() {}

  delete() {}
}

class algoliaSearch extends Search {

  init(callback) {
    this.algolia = this.siteInfo.getConfigItem('algolia');
    const client = algoliasearch(this.algolia.applicationId, this.algolia.apiKey);
    this.index = client.initIndex(this.algolia.index);
    this.index.clearIndex((err, content) => {
      callback(err, !err);
    });
  }

  insertOne(item, callback) {
    let doc = this.prepareSearchFields(item, false);
    doc.objectID = doc.interra.id;
    console.log("indexing " + doc.title);
    this.index.addObject(doc, (err, content) => {
      callback(err, !err);
    });

  }
}

class elasticSearch extends Search {

  init(callback) {
    this.private = this.siteInfo.getConfigItem('private');
    this.aws = this.private.aws;
    const accessKeyId = this.aws.accessKeyId;
    const secretAccessKey = this.aws.secretAccessKey;
    const region = this.aws.region;
    const esEndpoint = this.aws.es.endpoint;
    AWS.config.update({
      credentials: new AWS.Credentials(accessKeyId, secretAccessKey),
      region
    });

    this.Client = require('elasticsearch').Client({
      hosts: [ esEndpoint ],
      connectionClass: require('http-aws-es')
    });
    const that = this;

    this.Client.ping({
      requestTimeout: 30000,
    }, function (error) {
      if (error) {
        callback(error);
      } else {
        that.Client.indices.delete({
          index: that.aws.es.index
        }, (err, res) => {
          if (err) {
            callback(err.msg);
          } else {
            that.Client.indices.create({
              index: that.aws.es.index
            }, (createErr, res) => {
              callback(createErr, !createErr);
            });
          }
        });
      }
    });
  }

  insertOne(item, callback) {
    const doc = this.prepareSearchFields(item, false);
    this.Client.create({
      index: this.aws.es.index,
      type: this.schema.getConfigItem('primaryCollection'),
      id: doc.identifier,
      body: doc
    }, function (error, response) {
      callback(error, !error);
    });
  }

}

class simpleSearch extends Search {

  init(callback) {
    this.idx = [];
    callback();
  }

  insertOne(item, callback) {
    const doc = this.prepareSearchFields(item, false);
    const exp = {
      doc,
      ref: doc.interra.id,
    }
    this.idx.push(exp);
    return callback(null);
  }

  push(callback) {
    const file = path.join(this.apiDir, 'search-index.json');
    fs.outputFile(file, JSON.stringify(this.idx), (err) => {
      callback(err, !err);
    });
  }
}

class elasticLunr extends Search {

  init(callback) {
    this.idx = elasticlunr(() => {});
    // TODO: get the map for this.
    this.idx.setRef('identifier');
    this.searchConfig.fields.forEach((field) => {
      this.idx.addField(field);
    });
    callback();
  }

  insertOne(item, callback) {
    const doc = this.prepareSearchFields(item, false);
    this.idx.addDoc(doc);
    return callback(null);
  }

  push(callback) {
    const file = path.join(this.apiDir, 'search-index.json');
    fs.outputFile(file, JSON.stringify(this.idx), (err) => {
      callback(err, !err);
    });
  }
}

function type(obj) {
  return Object.prototype.toString.call(obj).match(/.* (.*)\]/)[  1]
}

function stringify(obj) {
  if (type(obj) === 'Function') {
    return null
  }
  if (type(obj) === 'Undefined') {
    return null
  }
  if (type(obj) === 'Null') {
    return 'null'
  }
  if (type(obj) === 'Number') {
    return obj
  }
  if (type(obj) === 'String') {
    return obj
  }
  if (type(obj) === 'Object' || type(obj) === 'Array') {
    var result = ''
    Object.keys(obj).forEach(function(key) {
      var val = stringify(obj[key])
      if (val !== null) {
      result = result.trim() + ' ' + val
      }
    })
    return result
  }
}

module.exports = {
  elasticLunr,
  simpleSearch,
  algoliaSearch,
  elasticSearch,
};
<commit_msg>Updates search.js<commit_after>const fs = require('fs-extra');
const elasticlunr = require('elasticlunr');
const Schema = require('./schema');
const Site = require('./site');
const path = require('path');
const apiSubDir = 'api/v1';
const AWS = require('aws-sdk');
const algoliasearch = require('algoliasearch');

class Search {

  constructor(site, config) {
    this.sitesDir = config.get('sitesDir');
    this.siteDir = path.join(this.sitesDir, site);
    this.schemasDir = config.get('schemasDir');
    this.siteInfo = new Site(site, config);
    this.schemaName = this.siteInfo.getConfigItem('schema');
    this.schema = new Schema(this.schemaName, config);
    this.searchConfig = this.siteInfo.getConfigItem('search');
    this.apiDir = path.join(config.get('buildDir'), site, apiSubDir);
  }

  init(callback) {
    callback();
  }

  prepareSearchFields(doc, toString) {
    const prepped = {};
    this.searchConfig.fields.forEach((field) => {
      if (toString) {
        prepped[field] = stringify(doc[field]);
      } else {
        prepped[field] = doc[field];
      }
    });
    prepped.identifier = doc.identifier;
    prepped.interra = doc.interra;
    prepped.modified = doc.modified;
    return prepped;
  }

  push(callback) {
    callback();
  }

  insertOne(callback) {
    callback();
  }

  insertMany() {}

  update() {}

  delete() {}
}

class algoliaSearch extends Search {

  init(callback) {
    this.algolia = this.siteInfo.getConfigItem('algolia');
    const client = algoliasearch(this.algolia.applicationId, this.algolia.apiKey);
    this.index = client.initIndex(this.algolia.index);
    this.index.clearIndex((err, content) => {
      callback(err, !err);
    });
  }

  insertOne(item, callback) {
    let doc = this.prepareSearchFields(item, false);
    doc.objectID = doc.interra.id;
    console.log("indexing " + doc.title);
    this.index.addObject(doc, (err, content) => {
      callback(err, !err);
    });

  }
}

class elasticSearch extends Search {

  init(callback) {
    this.private = this.siteInfo.getConfigItem('private');
    this.aws = this.private.aws;
    const accessKeyId = this.aws.accessKeyId;
    const secretAccessKey = this.aws.secretAccessKey;
    const region = this.aws.region;
    const esEndpoint = this.aws.es.endpoint;
    AWS.config.update({
      credentials: new AWS.Credentials(accessKeyId, secretAccessKey),
      region
    });

    this.Client = require('elasticsearch').Client({
      hosts: [ esEndpoint ],
      connectionClass: require('http-aws-es')
    });
    const that = this;

    this.Client.ping({
      requestTimeout: 30000,
    }, function (error) {
      if (error) {
        callback(error);
      } else {
        that.Client.indices.delete({
          index: that.aws.es.index
        }, (err, res) => {
          if (err) {
            callback(err.msg);
          } else {
            that.Client.indices.create({
              index: that.aws.es.index
            }, (createErr, res) => {
              callback(createErr, !createErr);
            });
          }
        });
      }
    });
  }

  insertOne(item, callback) {
    const doc = this.prepareSearchFields(item, false);
    this.Client.create({
      index: this.aws.es.index,
      type: this.schema.getConfigItem('primaryCollection'),
      id: doc.identifier,
      body: doc,
    }, function (error, response) {
      callback(error, !error);
    });
  }

}

class simpleSearch extends Search {

  init(callback) {
    this.idx = [];
    callback();
  }

  insertOne(item, callback) {
    const doc = this.prepareSearchFields(item, false);
    const exp = {
      doc,
      ref: doc.interra.id,
    }
    this.idx.push(exp);
    return callback(null);
  }

  push(callback) {
    const file = path.join(this.apiDir, 'search-index.json');
    fs.outputFile(file, JSON.stringify(this.idx), (err) => {
      callback(err, !err);
    });
  }
}

class elasticLunr extends Search {

  init(callback) {
    this.idx = elasticlunr(() => {});
    // TODO: get the map for this.
    this.idx.setRef('identifier');
    this.searchConfig.fields.forEach((field) => {
      this.idx.addField(field);
    });
    callback();
  }

  insertOne(item, callback) {
    const doc = this.prepareSearchFields(item, false);
    this.idx.addDoc(doc);
    return callback(null);
  }

  push(callback) {
    const file = path.join(this.apiDir, 'search-index.json');
    fs.outputFile(file, JSON.stringify(this.idx), (err) => {
      callback(err, !err);
    });
  }
}

function type(obj) {
  return Object.prototype.toString.call(obj).match(/.* (.*)\]/)[  1]
}

function stringify(obj) {
  if (type(obj) === 'Function') {
    return null
  }
  if (type(obj) === 'Undefined') {
    return null
  }
  if (type(obj) === 'Null') {
    return 'null'
  }
  if (type(obj) === 'Number') {
    return obj
  }
  if (type(obj) === 'String') {
    return obj
  }
  if (type(obj) === 'Object' || type(obj) === 'Array') {
    var result = ''
    Object.keys(obj).forEach(function(key) {
      var val = stringify(obj[key])
      if (val !== null) {
      result = result.trim() + ' ' + val
      }
    })
    return result
  }
}

module.exports = {
  elasticLunr,
  simpleSearch,
  algoliaSearch,
  elasticSearch,
};
<|endoftext|>


<commit_before>function getAttendees(peopleInvited, responses){

  for(i = 0; i < responses.length; i++) {
  	if (responses[i].response === 'declined') {
  		var peopleIndex = peopleInvited.indexOf(responses[i].name);
  		peopleInvited.splice(peopleIndex, 1)
  	}
  }
  return peopleInvited;

}

// test
var people = ['Easter Bunny', 'Tooth Fairy', 'Frosty the Snowman',
              'Jack Frost', 'Cupid', 'Father Time'];
var responses = [
     {name: 'Easter Bunny', response: 'declined'},
     {name: 'Jack Frost', response: 'declined'},
     {name: 'Tooth Fairy', response: 'accepted'}
   ]

console.log(getAttendees(people, responses) == ['Tooth Fairy', 'Frosty the Snowman', 'Cupid', 'Father Time'])

<commit_msg>delete testing because the '===' operand will return false for not referencing the same object although the arrays contain the same elements<commit_after>function getAttendees(peopleInvited, responses){

  for(i = 0; i < responses.length; i++) {
  	if (responses[i].response === 'declined') {
  		var peopleIndex = peopleInvited.indexOf(responses[i].name);
  		peopleInvited.splice(peopleIndex, 1)
  	}
  }
  return peopleInvited;

}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016,  nwillc@gmail.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

define(["gapi", "jquery-ui", "jquery", "graphql"], function (gapi, ui, $, graphql) {
    return {
        App: function () {
            "use strict";
            var _this = this;

            // Instance variables and initialization
            $("#tabs").tabs();
            this.categories = $("#browseCategories");
            this.snippetCategories = $("#snippetCategories");
            this.moveCategories = $("#moveCategories");
            this.category = $("#category");
            this.titles = $("#titles");
            this.title = $("#title");
            this.body = $("#body");
            this.bodyInput = $("#bodyInput");
            this.query = $("#query");

            this.searchDialog = $("#searchCategoryDialog");
            $(this.searchDialog).dialog({ width: 500 });
            $(this.searchDialog).dialog("close");

            this.moveSnippetDialog = $("#moveSnippetDialog");
            $(this.moveSnippetDialog).dialog({ width: 500 });
            $(this.moveSnippetDialog).dialog("close");

            this.buildInfoDialog = $("#buildInfoDialog");
            $(this.buildInfoDialog).dialog({ height: 300, width: 500 });
            $(this.buildInfoDialog).dialog("close");

            this.fileImportDialog = $("#fileImportDialog");
            $(this.fileImportDialog).dialog({ height: 100, width: 450 });
            $(this.fileImportDialog).dialog("close");

            var graphqlUrl = "v1/graphql";
            this.categoryGQL = new graphql.Graphql(graphqlUrl, "{ categories { key name }}");
            this.categorySnippetsGQL = new graphql.Graphql(graphqlUrl, "query($category: String!){ snippets ( category: $category ) { key title }}");
            this.categoryCreateGQL = new graphql.Graphql(graphqlUrl, "mutation($name: String!){ category(name: $name){ key }}");
            this.snippetBodyGQL = new graphql.Graphql(graphqlUrl, "query($snippet: String!){ snippet ( key: $snippet) { body }}");
            this.snippetCreateGQL = new graphql.Graphql(graphqlUrl, "mutation($category: String! $title: String! $body: String!){ snippet ( category: $category title: $title body: $body ){ key }}");
            this.snippetUpdateGQL = new graphql.Graphql(graphqlUrl, "mutation($key: String! $category: String! $title: String! $body: String!){ snippet ( key: $key category: $category title: $title body: $body ){ key }}");
            this.deleteSnippetGQL = new graphql.Graphql(graphqlUrl, "mutation($snippet: String!) { deleteSnippet ( key: $snippet ) }");
            this.deleteCategoryGQL = new graphql.Graphql(graphqlUrl, "mutation($category: String!) { deleteCategory ( key: $category ) }");
            this.searchCategoryGQL = new graphql.Graphql(graphqlUrl, "query($category: String! $match: String!){ snippets( category: $category match: $match ){ key title }}");
            this.datastoreGQL = new graphql.Graphql(graphqlUrl, "{ datastore { categories { key name }  snippets { key category title body } }}");

            // Functions
            this.loadCategories = function () {
                console.log("loadCategories");
                _this.categoryGQL.execute(function (response) {
                    var list = response.data.categories.sort(function (a, b) {
                        return a.name.localeCompare(b.name);
                    });
                    $(_this.categories).empty();
                    $(_this.snippetCategories).empty();
                    $(_this.moveCategories).empty();
                    list.forEach(function (element) {
                        _this.categories.append($("<option></option>").attr("value", element.key).text(element.name));
                        _this.snippetCategories.append($("<option></option>").attr("value", element.key).text(element.name));
                        _this.moveCategories.append($("<option></option>").attr("value", element.key).text(element.name));
                    });

                    window.setTimeout(function () {
                        $(_this.categories).change();
                    }, 1);
                });
            };

            this.loadAllTitles = function () {
                _this.categorySnippetsGQL.variables["category"] = $(_this.categories).val();
                console.log("Snippets for Category");
                _this.categorySnippetsGQL.execute(function (response) { _this.loadTitles(response.data.snippets) });
            };

            this.loadTitles = function (list) {
                console.log("loadTitles");
                $("option", _this.titles).remove();
                $(_this.body).val("");
                list.sort(function (a, b) {
                    return a.title.localeCompare(b.title);
                }).forEach(function (element) {
                    _this.titles.append($("<option></option>").attr("value", element.key).text(element.title))
                });
            };

            this.loadBody = function () {
                _this.snippetBodyGQL.variables["snippet"] = $(_this.titles).val();
                console.log("Requesting snippet");
                _this.snippetBodyGQL.execute(function (response) { $(_this.body).val(response.data.snippet.body); });
            };

            this.saveCategory = function () {
                console.log("Create Category");
                _this.categoryCreateGQL.variables["name"] = $(_this.category).val();
                _this.categoryCreateGQL.execute(function () {
                    _this.loadCategories();
                    $("#category").val("");
                });
            };

            this.saveSnippet = function () {
                console.log("Create Snippet");
                _this.snippetCreateGQL.variables["category"] = $(_this.snippetCategories).val();
                _this.snippetCreateGQL.variables["title"] = $(_this.title).val();
                _this.snippetCreateGQL.variables["body"] = $(_this.bodyInput).val();
                _this.snippetCreateGQL.execute(function () {
                    _this.loadCategories();
                    $(_this.title).val("");
                    $(_this.bodyInput).val("");
                });
            };

            this.deleteSnippet = function () {
                _this.deleteSnippetGQL.variables["snippet"] = $(titles).find("option:selected").val();
                console.log("Delete Snippet");
                _this.deleteSnippetGQL.execute(function () { _this.loadCategories(); });
            };

            this.moveSnippet = function () {
                var selected = $(titles).find("option:selected");
                console.log("Move Snippet: " + $(selected).val());
                _this.snippetUpdateGQL.variables["key"] = selected.val();
                _this.snippetUpdateGQL.variables["category"] = $(_this.moveCategories).val();
                _this.snippetUpdateGQL.variables["title"] = selected.text();
                _this.snippetUpdateGQL.variables["body"] = $(_this.body).val();
                _this.snippetUpdateGQL.execute(function () {
                    _this.loadAllTitles();
                    $(_this.moveSnippetDialog).dialog("close");
                });
            };

            this.deleteCategory = function () {
                _this.deleteCategoryGQL.variables["category"] = $(_this.categories).val();
                console.log("Delete Category");
                _this.deleteCategoryGQL.execute(function () { _this.loadCategories(); });
            };

            this.performSearch = function (event) {
                if (event.keyCode === 13) {
                    _this.searchCategoryGQL.variables["category"] = $(_this.categories).val();
                    _this.searchCategoryGQL.variables["match"] = $(_this.query).val();
                    console.log("Search Category");
                    _this.searchCategoryGQL.execute(function (response) {
                        _this.loadTitles(response.data.snippets);
                        $(_this.searchDialog).dialog("close");
                    });
                }
            };

            this.updateSnippet = function () {
                console.log("Update Snippet");
                _this.snippetUpdateGQL.variables["key"] = $(_this.titles).val();
                _this.snippetUpdateGQL.variables["category"] = $(_this.categories).val();
                _this.snippetUpdateGQL.variables["title"] = $(_this.titles).children(":selected").text();
                _this.snippetUpdateGQL.variables["body"] = $(_this.body).val();
                _this.snippetUpdateGQL.execute(function () {
                    _this.loadAllTitles();
                });
            };

            this.logout = function () {
                console.log("logout");
                $.ajax({
                    url: "v1/auth",
                    method: "DELETE",
                    success: function () { window.location.replace("/login.html"); }
                });
                var auth2 = gapi.auth2.getAuthInstance();
                auth2.signOut().then(function () {
                    console.log("User signed out of Google.");
                });
            };

            this.buildInfo = function () {
                console.log("build info");
                $.get("properties", function (data) {
                    $(_this.buildInfoDialog).dialog("open");
                    $("#buildInfo").html(data);
                });
            };

            this.export = function () {
                var filename = "export.json";
                console.log("export: " + filename);
                _this.datastoreGQL.execute(function (response) {
                    var blob = new Blob([JSON.stringify(response.data.datastore)], { type: 'application/json' });
                    if (window.navigator.msSaveOrOpenBlob) {
                        window.navigator.msSaveBlob(blob, filename);
                    } else {
                        var elem = window.document.createElement('a');
                        elem.href = window.URL.createObjectURL(blob);
                        elem.download = filename;
                        document.body.appendChild(elem);
                        elem.click();
                        document.body.removeChild(elem);
                    }
                });
            };

            this.import = function (evt) {
                var files = evt.target.files;
                for (var i = 0, f; f = files[i]; i++) {
                    console.log("File " + f);
                    var reader = new FileReader();
                    reader.onloadend = function(result) {
                          if (result.target.readyState == FileReader.DONE) {
                            var data = JSON.parse(result.target.result);
                            console.log(result.target.result);
                            // Save categories
                            // Save snippets
                          }
                        };
                     var blob = f.slice(0, f.size);
                     reader.readAsBinaryString(blob);
                }
                $(_this.fileImportDialog).dialog("close");
            };

            this.openSearch = function () {
                $(_this.searchDialog).dialog("open");
            };

            this.openMoveSnippet = function () {
                $(_this.moveSnippetDialog).dialog("open");
            };

            this.moveDialog = function () {
                _this.moveSnippet();
            };

            this.openFileImport = function () {
                $(_this.fileImportDialog).dialog("open");
            };

            // Bindings
            $(this.categories).change(this.loadAllTitles);
            $(this.titles).change(this.loadBody);
            $("#saveSnippetButton").click(this.saveSnippet);
            $("#deleteButton").click(this.deleteSnippet);
            $("#saveCategoryButton").click(this.saveCategory);
            $("#deleteCategoryButton").click(this.deleteCategory);
            $("#searchButton").click(this.openSearch);
            $(this.query).keyup(this.performSearch);
            $("#buildInfoButton").click(this.buildInfo);
            $("#updateButton").click(this.updateSnippet);
            $("#moveButton").click(this.openMoveSnippet);
            $("#logoutButton").click(this.logout);
            $("#performMove").click(this.moveSnippet);
            $("#exportButton").click(this.export);
            $("#fileImportButton").click(this.openFileImport);
            $("#filename").change(this.import);

            // GO!
            this.loadCategories();
            $("#page").show();
            $("#loading").hide();
        }
    }
});

<commit_msg>debugging<commit_after>/*
 * Copyright (c) 2016,  nwillc@gmail.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

define(["gapi", "jquery-ui", "jquery", "graphql"], function (gapi, ui, $, graphql) {
    return {
        App: function () {
            "use strict";
            var _this = this;

            // Instance variables and initialization
            $("#tabs").tabs();
            this.categories = $("#browseCategories");
            this.snippetCategories = $("#snippetCategories");
            this.moveCategories = $("#moveCategories");
            this.category = $("#category");
            this.titles = $("#titles");
            this.title = $("#title");
            this.body = $("#body");
            this.bodyInput = $("#bodyInput");
            this.query = $("#query");

            this.searchDialog = $("#searchCategoryDialog");
            $(this.searchDialog).dialog({ width: 500 });
            $(this.searchDialog).dialog("close");

            this.moveSnippetDialog = $("#moveSnippetDialog");
            $(this.moveSnippetDialog).dialog({ width: 500 });
            $(this.moveSnippetDialog).dialog("close");

            this.buildInfoDialog = $("#buildInfoDialog");
            $(this.buildInfoDialog).dialog({ height: 300, width: 500 });
            $(this.buildInfoDialog).dialog("close");

            this.fileImportDialog = $("#fileImportDialog");
            $(this.fileImportDialog).dialog({ height: 100, width: 450 });
            $(this.fileImportDialog).dialog("close");

            var graphqlUrl = "v1/graphql";
            this.categoryGQL = new graphql.Graphql(graphqlUrl, "{ categories { key name }}");
            this.categorySnippetsGQL = new graphql.Graphql(graphqlUrl, "query($category: String!){ snippets ( category: $category ) { key title }}");
            this.categoryCreateGQL = new graphql.Graphql(graphqlUrl, "mutation($name: String!){ category(name: $name){ key }}");
            this.snippetBodyGQL = new graphql.Graphql(graphqlUrl, "query($snippet: String!){ snippet ( key: $snippet) { body }}");
            this.snippetCreateGQL = new graphql.Graphql(graphqlUrl, "mutation($category: String! $title: String! $body: String!){ snippet ( category: $category title: $title body: $body ){ key }}");
            this.snippetUpdateGQL = new graphql.Graphql(graphqlUrl, "mutation($key: String! $category: String! $title: String! $body: String!){ snippet ( key: $key category: $category title: $title body: $body ){ key }}");
            this.deleteSnippetGQL = new graphql.Graphql(graphqlUrl, "mutation($snippet: String!) { deleteSnippet ( key: $snippet ) }");
            this.deleteCategoryGQL = new graphql.Graphql(graphqlUrl, "mutation($category: String!) { deleteCategory ( key: $category ) }");
            this.searchCategoryGQL = new graphql.Graphql(graphqlUrl, "query($category: String! $match: String!){ snippets( category: $category match: $match ){ key title }}");
            this.datastoreGQL = new graphql.Graphql(graphqlUrl, "{ datastore { categories { key name }  snippets { key category title body } }}");

            // Functions
            this.loadCategories = function () {
                console.log("loadCategories");
                _this.categoryGQL.execute(function (response) {
                    var list = response.data.categories.sort(function (a, b) {
                        return a.name.localeCompare(b.name);
                    });
                    $(_this.categories).empty();
                    $(_this.snippetCategories).empty();
                    $(_this.moveCategories).empty();
                    list.forEach(function (element) {
                        _this.categories.append($("<option></option>").attr("value", element.key).text(element.name));
                        _this.snippetCategories.append($("<option></option>").attr("value", element.key).text(element.name));
                        _this.moveCategories.append($("<option></option>").attr("value", element.key).text(element.name));
                    });

                    window.setTimeout(function () {
                        $(_this.categories).change();
                    }, 1);
                });
            };

            this.loadAllTitles = function () {
                _this.categorySnippetsGQL.variables["category"] = $(_this.categories).val();
                console.log("Snippets for Category");
                _this.categorySnippetsGQL.execute(function (response) {
                    console.log("Response: " + JSON.stringify(response));
                    _this.loadTitles(response.data.snippets);
                });
            };

            this.loadTitles = function (list) {
                console.log("loadTitles");
                $("option", _this.titles).remove();
                $(_this.body).val("");
                list.sort(function (a, b) {
                    return a.title.localeCompare(b.title);
                }).forEach(function (element) {
                    _this.titles.append($("<option></option>").attr("value", element.key).text(element.title))
                });
            };

            this.loadBody = function () {
                _this.snippetBodyGQL.variables["snippet"] = $(_this.titles).val();
                console.log("Requesting snippet");
                _this.snippetBodyGQL.execute(function (response) { $(_this.body).val(response.data.snippet.body); });
            };

            this.saveCategory = function () {
                console.log("Create Category");
                _this.categoryCreateGQL.variables["name"] = $(_this.category).val();
                _this.categoryCreateGQL.execute(function () {
                    _this.loadCategories();
                    $("#category").val("");
                });
            };

            this.saveSnippet = function () {
                console.log("Create Snippet");
                _this.snippetCreateGQL.variables["category"] = $(_this.snippetCategories).val();
                _this.snippetCreateGQL.variables["title"] = $(_this.title).val();
                _this.snippetCreateGQL.variables["body"] = $(_this.bodyInput).val();
                _this.snippetCreateGQL.execute(function () {
                    _this.loadCategories();
                    $(_this.title).val("");
                    $(_this.bodyInput).val("");
                });
            };

            this.deleteSnippet = function () {
                _this.deleteSnippetGQL.variables["snippet"] = $(titles).find("option:selected").val();
                console.log("Delete Snippet");
                _this.deleteSnippetGQL.execute(function () { _this.loadCategories(); });
            };

            this.moveSnippet = function () {
                var selected = $(titles).find("option:selected");
                console.log("Move Snippet: " + $(selected).val());
                _this.snippetUpdateGQL.variables["key"] = selected.val();
                _this.snippetUpdateGQL.variables["category"] = $(_this.moveCategories).val();
                _this.snippetUpdateGQL.variables["title"] = selected.text();
                _this.snippetUpdateGQL.variables["body"] = $(_this.body).val();
                _this.snippetUpdateGQL.execute(function () {
                    _this.loadAllTitles();
                    $(_this.moveSnippetDialog).dialog("close");
                });
            };

            this.deleteCategory = function () {
                _this.deleteCategoryGQL.variables["category"] = $(_this.categories).val();
                console.log("Delete Category");
                _this.deleteCategoryGQL.execute(function () { _this.loadCategories(); });
            };

            this.performSearch = function (event) {
                if (event.keyCode === 13) {
                    _this.searchCategoryGQL.variables["category"] = $(_this.categories).val();
                    _this.searchCategoryGQL.variables["match"] = $(_this.query).val();
                    console.log("Search Category");
                    _this.searchCategoryGQL.execute(function (response) {
                        _this.loadTitles(response.data.snippets);
                        $(_this.searchDialog).dialog("close");
                    });
                }
            };

            this.updateSnippet = function () {
                console.log("Update Snippet");
                _this.snippetUpdateGQL.variables["key"] = $(_this.titles).val();
                _this.snippetUpdateGQL.variables["category"] = $(_this.categories).val();
                _this.snippetUpdateGQL.variables["title"] = $(_this.titles).children(":selected").text();
                _this.snippetUpdateGQL.variables["body"] = $(_this.body).val();
                _this.snippetUpdateGQL.execute(function () {
                    _this.loadAllTitles();
                });
            };

            this.logout = function () {
                console.log("logout");
                $.ajax({
                    url: "v1/auth",
                    method: "DELETE",
                    success: function () { window.location.replace("/login.html"); }
                });
                var auth2 = gapi.auth2.getAuthInstance();
                auth2.signOut().then(function () {
                    console.log("User signed out of Google.");
                });
            };

            this.buildInfo = function () {
                console.log("build info");
                $.get("properties", function (data) {
                    $(_this.buildInfoDialog).dialog("open");
                    $("#buildInfo").html(data);
                });
            };

            this.export = function () {
                var filename = "export.json";
                console.log("export: " + filename);
                _this.datastoreGQL.execute(function (response) {
                    var blob = new Blob([JSON.stringify(response.data.datastore)], { type: 'application/json' });
                    if (window.navigator.msSaveOrOpenBlob) {
                        window.navigator.msSaveBlob(blob, filename);
                    } else {
                        var elem = window.document.createElement('a');
                        elem.href = window.URL.createObjectURL(blob);
                        elem.download = filename;
                        document.body.appendChild(elem);
                        elem.click();
                        document.body.removeChild(elem);
                    }
                });
            };

            this.import = function (evt) {
                var files = evt.target.files;
                for (var i = 0, f; f = files[i]; i++) {
                    console.log("File " + f);
                    var reader = new FileReader();
                    reader.onloadend = function(result) {
                          if (result.target.readyState == FileReader.DONE) {
                            var data = JSON.parse(result.target.result);
                            console.log(result.target.result);
                            // Save categories
                            data.categories.forEach(function(category) {
                                console.log("Category: " + JSON.stringify(category));
                            });
                            // Save snippets
                          }
                        };
                     var blob = f.slice(0, f.size);
                     reader.readAsBinaryString(blob);
                }
                $(_this.fileImportDialog).dialog("close");
            };

            this.openSearch = function () {
                $(_this.searchDialog).dialog("open");
            };

            this.openMoveSnippet = function () {
                $(_this.moveSnippetDialog).dialog("open");
            };

            this.moveDialog = function () {
                _this.moveSnippet();
            };

            this.openFileImport = function () {
                $(_this.fileImportDialog).dialog("open");
            };

            // Bindings
            $(this.categories).change(this.loadAllTitles);
            $(this.titles).change(this.loadBody);
            $("#saveSnippetButton").click(this.saveSnippet);
            $("#deleteButton").click(this.deleteSnippet);
            $("#saveCategoryButton").click(this.saveCategory);
            $("#deleteCategoryButton").click(this.deleteCategory);
            $("#searchButton").click(this.openSearch);
            $(this.query).keyup(this.performSearch);
            $("#buildInfoButton").click(this.buildInfo);
            $("#updateButton").click(this.updateSnippet);
            $("#moveButton").click(this.openMoveSnippet);
            $("#logoutButton").click(this.logout);
            $("#performMove").click(this.moveSnippet);
            $("#exportButton").click(this.export);
            $("#fileImportButton").click(this.openFileImport);
            $("#filename").change(this.import);

            // GO!
            this.loadCategories();
            $("#page").show();
            $("#loading").hide();
        }
    }
});

<|endoftext|>