<commit_before>/*
 * formality.js
 *
 * @author Nikola Stamatovic Stamat
 * @copyright IVARTECH < http://ivartech.com >
 * @since May 2013
 */

//data types: null, boolean, integer, number, string, array (, file)

//elements-basic: text, textarea, checkbox, select, multiple-select, button, file

//elements-advanced: items-list/tags(array), date-picker(string), color-picker(string), number-spinner(number),  multiple-checkboxes(array), threeway(number:-1,0,1), multiple-file(array:files), dropzone(array:files), slider(number)...

//states: default, info, warn, error, load, disabled, tip, valid/ok

//TODO: BUTTON STATES, LOADING, ERROR, SUCCESS
//TODO: CAPTCHA WIDGET
//TODO: FORM SUBMISSION

if (ivar === undefined) var ivar = {};

ivar.namespace('formality');
formality.formAggregator = {};

$(document).ready(function() {
	//console.log(jules.validate('lol',{type: 'string'}));
	initInputs($('.ivartech-input'));
});

var schema = {
	name: '',
	type: 'text', //text, textarea, checkbox, multiple-checkbox, threeway, select, multiple-select, button, file, multiple-file, dropzone
	value: null,
	updateOn: 'blur',
	form: null,

	state: {
		// normal, error, tip, warn, valid, info, load, disabled
		'default': 'normal',
		'message': {
			'tip': '',
			'info': '',
			'warn': '',
			'load': '',
			'valid': '',
			'error': ''
		}
	},

	schema: {
		// JSON SCHEMA
	}
};

function InputField(o) {
	this.elem = null;
	this.field = null;
	this.value = null;
	this.updateOn = 'blur';
	this.schema = {};

	this.skip_validation = false;
	this.form = null;
	this.classes = '';

	this.info_msg = null;
	this.error_msg = null;
	this.valid_msg = null;
	this.tip_msg = null;

	this.default_state = null;

	if(o !== undefined)
		ivar.extend(this, o);
};

InputField.prototype.setState = function(state, title, message) {
	this.elem.attr('class', this.classes);
	if(state)
		this.elem.addClass(state);
	if(title)
		this.setStateTitle(state, title);
	if(message)
		this.setStateMessage(message);
	else
		this.setStateMessage('');
};

InputField.prototype.setStateTitle = function(state, title) {
	this.elem.find('.'+state).attr('title', title);
};

InputField.prototype.setStateMessage = function(message) {
	this.elem.find('.message').html(message);
};

InputField.prototype.setDefaultState = function() {
	if(this.default_state !== null)
		this.setState(this.default_state);
	else
		this.setState();
}

InputField.prototype.buildState = function(elem, state) {
	var attrName = state+'_msg';
	attrToObjProp(this, elem, attrName);
	this.setStateTitle(state, this[attrName]);
};

ivar.namespace('value.update');

value.update.text = function(elem) {
	return $(elem).val();
};

value.update.textarea = value.update.text;

InputField.prototype.update = function() {
	this.value = value.update[this.type](this.field);
};

InputField.prototype.clear = function() {
	this.value = null;
	$(this.field).val('');
};

InputField.prototype.validate = function() {
	this.update();
	if(!jules.validator.type('string', 'type', this.schema)) //??? kako ovo uopšte radi....stamate konju
		this.value = ivar.parseText(this.value);
	return jules.validate(this.value, this.schema);
};

function attrToObjProp(obj, elem, attrName) {
	if (elem.attr(attrName)) {
		obj[attrName] = elem.attr(attrName);
		elem.removeAttr(attrName);
	}
};

ivar.namespace('store.attr');
store.attr.data_type = function(o, v) {
	if (/\s/.test(v))
		v = v.split(' ');
	o.schema.type = v;
};

store.setRange = function(prop, prop2, o, v) {
	v = ivar.parseText(v);
	if(!o.schema[prop]) o.schema[prop] = {};
	o.schema[prop][prop2] = v;
};

store.attr.min = function(o, v) {
	store.setRange('min', 'value', o, v);
};

store.attr.max = function(o, v) {
	store.setRange('max', 'value', o, v);
};

store.attr.minexclusive = function(o, v) {
	store.setRange('min', 'exclusive', o, v);
};

store.attr.maxexclusive = function(o, v) {
	store.setRange('max', 'exclusive', o, v);
};

//TODO: for numbers and for strings
store.attr.regex = function(o, v) {
	//if(jules.validator.type('string', 'type', o.schema)) {
		o.schema.pattern = v;
	//} else if(jules.validator.type('integer', 'type', o.schema) ||
	//	jules.validator.type('number', 'type', o.schema)) {
	//	o.schema.numberPattern = v;
	//}
};

store.attr.format = function(o, v) {
	o.schema.format = v;
};

store.attr.name = function(o, v) {
	o.name = v;
};

store.attr.form = function(o, v) {
	o.form = v;
	if(!formality.formAggregator.hasOwnProperty(o.form))
		formality.formAggregator[o.form] = [];

	formality.formAggregator[o.form].push(o);
};

function testPassword(pass) {
	var result = 0;
	if(/[a-z]+/.test(pass) && pass.length >= 6 )
		result = 1;
	if(result === 1 && /[0-9]+/.test(pass))
		result = 2;
	if(result === 2 && /[A-Z]+/.test(pass))
		result = 3;
	if(result === 3 && /[!@\#\$%\^&\*()_=+\/\|\-]+/.test(pass))
		result = 4;
	if(result === 4 && pass.length > 16)
		result = 5;

	return result;
}

function initInputs(elems) {
	for (var i = 0; i < elems.length; i++) {

		var ifield = new InputField();
		var attrs = elems[i].attributes;
		var stored = [];
		for (var j = 0; j < attrs.length; j++) {
			var attr = attrs[j];
			if(store.attr.hasOwnProperty(attr.name)) {
				store.attr[attr.name](ifield, attr.value);
				stored.push(attr.name);
			}
		}

		var template = $('#ivartech-templates .input-field').clone();
		var tmp = $(elems[i]).clone();
		ifield.elem = template;
		ifield.field = tmp;

		if(tmp.prop('tagName').toLowerCase() === 'input' && /(?:text|password)/.test(tmp.prop('type'))) {
			ifield.type = 'text';
		} else if(tmp.prop('tagName').toLowerCase() === 'textarea') {
			ifield.type = 'textarea';
		}

		if(!tmp.attr('data_type')) {
			if(ifield.type === 'text' || ifield.type === 'textarea')
			ifield.schema.type = 'string';
		}

		if(tmp.prop('tagName').toLowerCase() === 'textarea')
			template.addClass('textarea');

		template.find('#input-field-template').replaceWith(tmp);
		tmp.attr('name', tmp.attr('id'));
		template.find('label').html(
			tmp.attr('label')).attr(
				'for', tmp.attr('name'));

		var classes = template.attr('classes')?' '+template.attr('classes'):'';
		ifield.classes = template.attr('class') + classes;

		if(tmp.attr('mandatory') && tmp.attr('mandatory').toLowerCase() === 'true') {
			template.find('label').prepend('*');
			tmp.removeAttr('mandatory');
			template.attr('mandatory', 'true');
			ifield.mandatory = true;
		}

		attrToObjProp(ifield, tmp, 'default_state');

		ifield.buildState(tmp, 'info');
		ifield.buildState(tmp, 'tip');
		ifield.buildState(tmp, 'error');
		ifield.buildState(tmp, 'valid');
		ifield.buildState(tmp, 'load');
		ifield.buildState(tmp, 'warn');

		attrToObjProp(ifield, tmp, 'skip_validation');

		ifield.setDefaultState();

		tmp.data('ivartech-input', ifield);

		tmp.blur(function(e) {
			fieldBlur(this, e);
		});

		tmp.focus(function(e) {
			fieldFocus(this, e);
		});

		for (var j = 0; j < stored.length; j++) {
			elems[i].removeAttribute(stored[j]);
		}

		$(elems[i]).replaceWith(template);
	}
};

function fieldFocus(elem, e) {
	var ifield = $(elem).data('ivartech-input');
	if(!ifield.skipvalidation)
		ifield.setDefaultState();
}

function fieldBlur(elem, e) {
	var ifield = $(elem).data('ivartech-input');
	if(!ifield.skip_validation)
		if(ifield.validate()) {
			if(!ifield.mandatory && ifield.field.val().length === 0 ) {
				ifield.setDefaultState();
			} else {
				ifield.setState('valid');
			}
		} else {
			ifield.setState('error');
		}
}

//reverts all fields to prevous states
formality.revertStates = function(form_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		elems[i].setDefaultState();
	}
}

//Collects all field values and pacs them in json name:value
//TODO: collect other input fields than input and textbox
formality.collect = function(form_name) {
	var elems = formality.formAggregator[form_name];
	var res = {};

	for(var i = 0; i < elems.length; i++) {
		res[elems[i].name] = elems[i].value;
	}
	return res;
}

//Clear all values of all fields
formality.clearFields = function(form_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		elems[i].clear();
	}
}

//Clear all values of all fields
formality.isFormValid = function(form_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		if(!elems[i].validate())
			return false;
	}

	return true;
}

formality.validateForm = function(form_name) {
	var elems = formality.formAggregator[form_name];
	var res = true;
	for(var i = 0; i < elems.length; i++) {
		if(!elems[i].validate()) {
			if(res) res = false;
			elems[i].setState('error');
		}
	}

	return res;
}

//Get a certain field in a certain form
formality.getField = function(form_name, field_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		if (elems[i].name === field_name)
			return elems[i];
	}
}
<commit_msg>Connected properly to ivartech.js<commit_after>/*
 * formality.js
 *
 * @author Nikola Stamatovic Stamat
 * @copyright IVARTECH < http://ivartech.com >
 * @since May 2013
 */

//data types: null, boolean, integer, number, string, array (, file)

//elements-basic: text, textarea, checkbox, select, multiple-select, button, file

//elements-advanced: items-list/tags(array), date-picker(string), color-picker(string), number-spinner(number),  multiple-checkboxes(array), threeway(number:-1,0,1), multiple-file(array:files), dropzone(array:files), slider(number)...

//states: default, info, warn, error, load, disabled, tip, valid/ok

//TODO: BUTTON STATES, LOADING, ERROR, SUCCESS
//TODO: CAPTCHA WIDGET
//TODO: FORM SUBMISSION

if (ivar === undefined) var ivar = {};

ivar.namespace('formality');

ivar.require('ivar.data.jules');

formality.formAggregator = {};

ivar.ready(function() {
	//console.log(jules.validate('lol',{type: 'string'}));
	initInputs($('.ivartech-input'));
});

var schema = {
	name: '',
	type: 'text', //text, textarea, checkbox, multiple-checkbox, threeway, select, multiple-select, button, file, multiple-file, dropzone
	value: null,
	updateOn: 'blur',
	form: null,

	state: {
		// normal, error, tip, warn, valid, info, load, disabled
		'default': 'normal',
		'message': {
			'tip': '',
			'info': '',
			'warn': '',
			'load': '',
			'valid': '',
			'error': ''
		}
	},

	schema: {
		// JSON SCHEMA
	}
};

function InputField(o) {
	this.elem = null;
	this.field = null;
	this.value = null;
	this.updateOn = 'blur';
	this.schema = {};

	this.skip_validation = false;
	this.form = null;
	this.classes = '';

	this.info_msg = null;
	this.error_msg = null;
	this.valid_msg = null;
	this.tip_msg = null;

	this.default_state = null;

	if(o !== undefined)
		ivar.extend(this, o);
};

InputField.prototype.setState = function(state, title, message) {
	this.elem.attr('class', this.classes);
	if(state)
		this.elem.addClass(state);
	if(title)
		this.setStateTitle(state, title);
	if(message)
		this.setStateMessage(message);
	else
		this.setStateMessage('');
};

InputField.prototype.setStateTitle = function(state, title) {
	this.elem.find('.'+state).attr('title', title);
};

InputField.prototype.setStateMessage = function(message) {
	this.elem.find('.message').html(message);
};

InputField.prototype.setDefaultState = function() {
	if(this.default_state !== null)
		this.setState(this.default_state);
	else
		this.setState();
}

InputField.prototype.buildState = function(elem, state) {
	var attrName = state+'_msg';
	attrToObjProp(this, elem, attrName);
	this.setStateTitle(state, this[attrName]);
};

ivar.namespace('value.update');

value.update.text = function(elem) {
	return $(elem).val();
};

value.update.textarea = value.update.text;

InputField.prototype.update = function() {
	this.value = value.update[this.type](this.field);
};

InputField.prototype.clear = function() {
	this.value = null;
	$(this.field).val('');
};

InputField.prototype.validate = function() {
	this.update();
	if(!jules.validator.type('string', 'type', this.schema)) //??? kako ovo uopšte radi....stamate konju
		this.value = ivar.parseText(this.value);
	return jules.validate(this.value, this.schema);
};

function attrToObjProp(obj, elem, attrName) {
	if (elem.attr(attrName)) {
		obj[attrName] = elem.attr(attrName);
		elem.removeAttr(attrName);
	}
};

ivar.namespace('store.attr');
store.attr.data_type = function(o, v) {
	if (/\s/.test(v))
		v = v.split(' ');
	o.schema.type = v;
};

store.setRange = function(prop, prop2, o, v) {
	v = ivar.parseText(v);
	if(!o.schema[prop]) o.schema[prop] = {};
	o.schema[prop][prop2] = v;
};

store.attr.min = function(o, v) {
	store.setRange('min', 'value', o, v);
};

store.attr.max = function(o, v) {
	store.setRange('max', 'value', o, v);
};

store.attr.minexclusive = function(o, v) {
	store.setRange('min', 'exclusive', o, v);
};

store.attr.maxexclusive = function(o, v) {
	store.setRange('max', 'exclusive', o, v);
};

//TODO: for numbers and for strings
store.attr.regex = function(o, v) {
	//if(jules.validator.type('string', 'type', o.schema)) {
		o.schema.pattern = v;
	//} else if(jules.validator.type('integer', 'type', o.schema) ||
	//	jules.validator.type('number', 'type', o.schema)) {
	//	o.schema.numberPattern = v;
	//}
};

store.attr.format = function(o, v) {
	o.schema.format = v;
};

store.attr.name = function(o, v) {
	o.name = v;
};

store.attr.form = function(o, v) {
	o.form = v;
	if(!formality.formAggregator.hasOwnProperty(o.form))
		formality.formAggregator[o.form] = [];

	formality.formAggregator[o.form].push(o);
};

function testPassword(pass) {
	var result = 0;
	if(/[a-z]+/.test(pass) && pass.length >= 6 )
		result = 1;
	if(result === 1 && /[0-9]+/.test(pass))
		result = 2;
	if(result === 2 && /[A-Z]+/.test(pass))
		result = 3;
	if(result === 3 && /[!@\#\$%\^&\*()_=+\/\|\-]+/.test(pass))
		result = 4;
	if(result === 4 && pass.length > 16)
		result = 5;

	return result;
}

function initInputs(elems) {
	for (var i = 0; i < elems.length; i++) {

		var ifield = new InputField();
		var attrs = elems[i].attributes;
		var stored = [];
		for (var j = 0; j < attrs.length; j++) {
			var attr = attrs[j];
			if(store.attr.hasOwnProperty(attr.name)) {
				store.attr[attr.name](ifield, attr.value);
				stored.push(attr.name);
			}
		}

		var template = $('#ivartech-templates .input-field').clone();
		var tmp = $(elems[i]).clone();
		ifield.elem = template;
		ifield.field = tmp;

		if(tmp.prop('tagName').toLowerCase() === 'input' && /(?:text|password)/.test(tmp.prop('type'))) {
			ifield.type = 'text';
		} else if(tmp.prop('tagName').toLowerCase() === 'textarea') {
			ifield.type = 'textarea';
		}

		if(!tmp.attr('data_type')) {
			if(ifield.type === 'text' || ifield.type === 'textarea')
			ifield.schema.type = 'string';
		}

		if(tmp.prop('tagName').toLowerCase() === 'textarea')
			template.addClass('textarea');

		template.find('#input-field-template').replaceWith(tmp);
		tmp.attr('name', tmp.attr('id'));
		template.find('label').html(
			tmp.attr('label')).attr(
				'for', tmp.attr('name'));

		var classes = template.attr('classes')?' '+template.attr('classes'):'';
		ifield.classes = template.attr('class') + classes;

		if(tmp.attr('mandatory') && tmp.attr('mandatory').toLowerCase() === 'true') {
			template.find('label').prepend('*');
			tmp.removeAttr('mandatory');
			template.attr('mandatory', 'true');
			ifield.mandatory = true;
		}

		attrToObjProp(ifield, tmp, 'default_state');

		ifield.buildState(tmp, 'info');
		ifield.buildState(tmp, 'tip');
		ifield.buildState(tmp, 'error');
		ifield.buildState(tmp, 'valid');
		ifield.buildState(tmp, 'load');
		ifield.buildState(tmp, 'warn');

		attrToObjProp(ifield, tmp, 'skip_validation');

		ifield.setDefaultState();

		tmp.data('ivartech-input', ifield);

		tmp.blur(function(e) {
			fieldBlur(this, e);
		});

		tmp.focus(function(e) {
			fieldFocus(this, e);
		});

		for (var j = 0; j < stored.length; j++) {
			elems[i].removeAttribute(stored[j]);
		}

		$(elems[i]).replaceWith(template);
	}
};

function fieldFocus(elem, e) {
	var ifield = $(elem).data('ivartech-input');
	if(!ifield.skipvalidation)
		ifield.setDefaultState();
}

function fieldBlur(elem, e) {
	var ifield = $(elem).data('ivartech-input');
	if(!ifield.skip_validation)
		if(ifield.validate()) {
			if(!ifield.mandatory && ifield.field.val().length === 0 ) {
				ifield.setDefaultState();
			} else {
				ifield.setState('valid');
			}
		} else {
			ifield.setState('error');
		}
}

//reverts all fields to prevous states
formality.revertStates = function(form_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		elems[i].setDefaultState();
	}
}

//Collects all field values and pacs them in json name:value
//TODO: collect other input fields than input and textbox
formality.collect = function(form_name) {
	var elems = formality.formAggregator[form_name];
	var res = {};

	for(var i = 0; i < elems.length; i++) {
		res[elems[i].name] = elems[i].value;
	}
	return res;
}

//Clear all values of all fields
formality.clearFields = function(form_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		elems[i].clear();
	}
}

//Clear all values of all fields
formality.isFormValid = function(form_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		if(!elems[i].validate())
			return false;
	}

	return true;
}

formality.validateForm = function(form_name) {
	var elems = formality.formAggregator[form_name];
	var res = true;
	for(var i = 0; i < elems.length; i++) {
		if(!elems[i].validate()) {
			if(res) res = false;
			elems[i].setState('error');
		}
	}

	return res;
}

//Get a certain field in a certain form
formality.getField = function(form_name, field_name) {
	var elems = formality.formAggregator[form_name];

	for(var i = 0; i < elems.length; i++) {
		if (elems[i].name === field_name)
			return elems[i];
	}
}
<|endoftext|>


<commit_before>/*
formatter.js

The MIT License (MIT)
Copyright © 2014

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the “Software”), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

{{user input}}
any digit character: # = \d
any word character: a = \w
any alphabetic character: Z = [a-z,A-Z]
any non-word character:  @ = \W
any non-digit character: d = \D
any non-whitespace character: s = \S
any character: * = .

- need spaces and special characters
- preferably have one character specifiers

phone number = ({{###}}) {{###}}-{{####}} = /({{\d\d\d}}) {{\d\d\d}}-{{\d\d\d\d}}
*/

var formatter = function() {
	this.init = function() {
		$(document).on("keypress", "input", function(event) {   //Bind event listener for the keypress event on an input.
	            var target = event.currentTarget;
	            var code = event.charCode? event.charCode : event.keyCode;
            	    var key = String.fromCharCode(code);
	            if (($(target).hasClass("formatInput") || $(target).parents(".formatInput:first")) && $(target).data("inputformat") !== undefined) {
	                var formatOptions = {
	                    input: $(target),							//The input that is being formatted
	                    key: key,									//The value of the key that was entered
	                    format: $(target).data("inputformat")		//The format supplied in the data-inputformat attribute of the DOM element
	                };
	                verifyChar(formatOptions, event);
	            }
	        });
	}

	var verifyChar = function(options, event) {
		var patternArray = buildPatternArray(options.format);
		var newUserVal = insertKey(options);	//value the user wants to have with the current key inserted into the correct position in the existing string - takes into account a highlight-replace operation
		var cleanedInput = newUserVal.length > 1 ? stripFormatting(patternArray, newUserVal) : newUserVal;
		var formattedVal = stringBuilder(cleanedInput, patternArray);

		options.input.val(formattedVal);
		event.preventDefault();	//Don't allow the current event to go through - prevents the character from appearing twice in the case of acceptable chars and once in the case on unacceptable chars
	};

	var stringBuilder = function(inputVal, stringPattern) {		//Builds out the string that will be placed in the input
		var charCount = 0;			//where the loop is at in the input value
		var formattedString = "";	//return value after formatting is added
		var lastFailed = false;		//used to flag if the last attempted character was not added - we don't want to add more trailing formatting characters if it did

		for (var i = 0; i < stringPattern.length; i++) {
			if (charCount >= inputVal.length && stringPattern[i].type !== "format") {
				break;	//get out of loop, we're done
			}
			else if (charCount >= inputVal.length && stringPattern[i].type === "format" && formattedString.length <= i && !lastFailed) {
				formattedString += stringPattern[i].value;		//add trailing format characters
			}
			while (charCount < inputVal.length) {
				if (stringPattern[i].type === "format") {	//If the current type is a "format", go ahead and add it to the string
					formattedString += stringPattern[i].value;
					lastFailed = false;
					break;
				}
				else if (stringPattern[i].type === "input" && validChar(i, stringPattern, charCount, inputVal)) {	//If the current type is an "input" and the current inputVal is a valid character, add it to the string
					formattedString += inputVal[charCount];
					charCount++;
					lastFailed = false;
					break;
				}
				else if (stringPattern[i].type === "input" && !validChar(i, stringPattern, charCount, inputVal)) {	//If the current type is an "input" and the current inputVal is not a valid character, remove it from the input string
					charCount++;
					lastFailed = true;
					//var tempString = inputVal.substring(0, charCount) + inputVal.substring(charCount+1);
					//inputVal = tempString;
				}
			}
		}
		return formattedString;
	};

	var validChar = function(patternIndex, stringPattern, inputIndex, inputVal) {
		var regexVal = new RegExp(getRegexVal(stringPattern[patternIndex].value));
		var testChar = inputVal[inputIndex];
		return regexVal.test(testChar, "i");		//return true/false based on the test result
	};

	var buildPatternArray = function(formatString) {	//Builds out an array using the format provided in the data-inputformat attribute of the DOM element
		var matcher = [];								//Each character is denoted whether it is part of the format of just user input based on the "{{" and "}}" delimiters
		var tempPattern = "";
		var tempForm = "";

		for (var i = 0; i < formatString.length; i++) {
			if (formatString[i] === "{" && formatString[i+1] === "{") {
				for (var j = i+2; j < formatString.length-1; j++) {
					if (formatString[j] === "}" && formatString[j+1] === "}") {
						i = j+1;
						break;
					}
					else {
						matcher.push({
							value: formatString[j],
							type: "input"
						});
					}
				}
			}
			else {
				matcher.push({
					value: formatString[i],
					type: "format"
				});
			}
		}

		return matcher;
	};

	var getRegexVal = function(char) {	//returns the regex value given a specific character as defined in the data-inputformat attributes
		switch (char) {
			case "#":
				return "\\d";			//any digit
			case "d":
				return "\\D";			//any non-digit character
			case "Z":
				return "[a-z,A-Z]";		//any upper or lower case character
			case "a":
				return "\\w";			//any word character
			case "@":
				return "\\W";			//any non-word character
			case "s":
				return "\\S";			//any non-whitespace character
			case "*":
				return ".";				//any character at all - wildcard
			default:
				return char;
		}
	};

	var insertKey = function(options) {		//Inserts the new character to it's position in the string based on cursor position
		var loc = getInputSelection(options.input[0]);
		var val = options.input.val().substring(0, loc.start) + options.key + options.input.val().substring(loc.end, options.input.val().length);
		return val;
	};

	var stripFormatting = function(formatString, fieldVal) {
		var strippedVal = "";
		var count = 0;
		var numChars = fieldVal.length;
		var index = 0;

		for (var i = 0; i < formatString.length; i++) {
			if (formatString[i].type === "input") {
				strippedVal += fieldVal.substr(i, 1);
				index++;
			}
			if (index === fieldVal.length) {
				break;
			}
		}
		return strippedVal;
	};

	var getInputSelection = function(el) {		//Finds the cursor position in the input string - includes highlighted ranges.
	    var start = 0, end = 0, normalizedValue, range,
	        textInputRange, len, endRange;

	    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
	        start = el.selectionStart;
	        end = el.selectionEnd;
	    } else {
	        range = document.selection.createRange();

	        if (range && range.parentElement() == el) {
	            len = el.value.length;
	            normalizedValue = el.value.replace(/\r\n/g, "\n");

	            // Create a working TextRange that lives only in the input
	            textInputRange = el.createTextRange();
	            textInputRange.moveToBookmark(range.getBookmark());

	            // Check if the start and end of the selection are at the very end
	            // of the input, since moveStart/moveEnd doesn't return what we want
	            // in those cases
	            endRange = el.createTextRange();
	            endRange.collapse(false);

	            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
	                start = end = len;
	            } else {
	                start = -textInputRange.moveStart("character", -len);
	                start += normalizedValue.slice(0, start).split("\n").length - 1;

	                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
	                    end = len;
	                } else {
	                    end = -textInputRange.moveEnd("character", -len);
	                    end += normalizedValue.slice(0, end).split("\n").length - 1;
	                }
	            }
	        }
	    }

	    return {
	        start: start,
	        end: end
	    };
	}

	return this;
}
<commit_msg>Update formatter.js<commit_after>/*
formatter.js

The MIT License (MIT)
Copyright © 2014

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the “Software”), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

{{user input}}
any digit character: # = \d
any word character: a = \w
any alphabetic character: Z = [a-z,A-Z]
any non-word character:  @ = \W
any non-digit character: d = \D
any non-whitespace character: s = \S
any character: * = .

- need spaces and special characters
- preferably have one character specifiers

phone number = ({{###}}) {{###}}-{{####}} = /({{\d\d\d}}) {{\d\d\d}}-{{\d\d\d\d}}
*/

var formatter = function() {
	this.init = function() {
		$(document).on("keypress", "input", function(event) {   //Bind event listener for the keypress event on an input.
	            var target = event.currentTarget;
	            var code = event.charCode? event.charCode : event.keyCode;
            	    var key = String.fromCharCode(code);
	            if (($(target).hasClass("formatInput") || $(target).parents(".formatInput:first")) && $(target).data("inputformat") !== undefined) {
	                var formatOptions = {
	                    input: $(target),					//The input that is being formatted
	                    key: key,						//The value of the key that was entered
	                    format: $(target).data("inputformat"),		//The format supplied in the data-inputformat attribute of the DOM element
	                    event: event
	                };
	                verifyChar(formatOptions);
	            }
	        });

	        $(document).on("paste", "input", function(event){
	        	$(document).one("keyup", "input", function(event) {	//We only want to listen to the keyup event after a paste event
	        		var target = event.currentTarget;
	        		if (($(target).hasClass("formatInput") || $(target).parents(".formatInput:first")) && $(target).data("inputformat") !== undefined) {
		                var formatOptions = {
		                    input: $(target),					//The input that is being formatted
		                    format: $(target).data("inputformat"),		//The format supplied in the data-inputformat attribute of the DOM element
		                    event: event
		                };
		                var patternArray = buildPatternArray(formatOptions.format);	//builds an array for each value in the supplied format string in the data-inputformat value
		                formatInput(formatOptions, patternArray, $(target).val());
		            }
	        	});
	        });
	}

	var verifyChar = function(options) {
		var patternArray = buildPatternArray(options.format);	//builds an array for each value in the supplied format string in the data-inputformat value
		var newUserVal = insertKey(options);	//value the user wants to have with the current key inserted into the correct position in the existing string - takes into account a highlight-replace operation
		var cleanedInput = newUserVal.length > 1 ? stripFormatting(patternArray, newUserVal) : newUserVal;	//cleans the current input of all formatting
		formatInput(options, patternArray, cleanedInput);
	};

	var formatInput = function(options, patternArray, inputVal) {
		var formattedVal = stringBuilder(inputVal, patternArray);	//inserts formatting characters into the string
		options.input.val(formattedVal);	//sets the input's new value
		options.event.preventDefault();		//prevent default action from taking place
	};

	var stringBuilder = function(inputVal, stringPattern) {		//Builds out the string that will be placed in the input
		var charCount = 0;			//where the loop is at in the input value
		var formattedString = "";	//return value after formatting is added
		var lastFailed = false;		//used to flag if the last attempted character was not added - we don't want to add more trailing formatting characters if it did

		for (var i = 0; i < stringPattern.length; i++) {
			if (charCount >= inputVal.length && stringPattern[i].type !== "format") {
				break;	//get out of loop, we're done
			}
			else if (charCount >= inputVal.length && stringPattern[i].type === "format" && formattedString.length <= i && !lastFailed) {
				formattedString += stringPattern[i].value;		//add trailing format characters
			}
			while (charCount < inputVal.length) {
				if (stringPattern[i].type === "format") {	//If the current type is a "format", go ahead and add it to the string
					formattedString += stringPattern[i].value;
					lastFailed = false;
					break;
				}
				else if (stringPattern[i].type === "input" && validChar(i, stringPattern, charCount, inputVal)) {	//If the current type is an "input" and the current inputVal is a valid character, add it to the string
					formattedString += inputVal[charCount];
					charCount++;
					lastFailed = false;
					break;
				}
				else if (stringPattern[i].type === "input" && !validChar(i, stringPattern, charCount, inputVal)) {	//If the current type is an "input" and the current inputVal is not a valid character, remove it from the input string
					charCount++;
					lastFailed = true;
				}
			}
		}
		return formattedString;
	};

	var validChar = function(patternIndex, stringPattern, inputIndex, inputVal) {
		var regexVal = new RegExp(getRegexVal(stringPattern[patternIndex].value));
		var testChar = inputVal[inputIndex];
		return regexVal.test(testChar, "i");		//return true/false based on the test result
	};

	var buildPatternArray = function(formatString) {	//Builds out an array using the format provided in the data-inputformat attribute of the DOM element
		var matcher = [];								//Each character is denoted whether it is part of the format of just user input based on the "{{" and "}}" delimiters
		var tempPattern = "";
		var tempForm = "";

		for (var i = 0; i < formatString.length; i++) {
			if (formatString[i] === "{" && formatString[i+1] === "{") {
				for (var j = i+2; j < formatString.length-1; j++) {
					if (formatString[j] === "}" && formatString[j+1] === "}") {
						i = j+1;
						break;
					}
					else {
						matcher.push({
							value: formatString[j],
							type: "input"
						});
					}
				}
			}
			else {
				matcher.push({
					value: formatString[i],
					type: "format"
				});
			}
		}

		return matcher;
	};

	var getRegexVal = function(char) {	//returns the regex value given a specific character as defined in the data-inputformat attributes
		switch (char) {
			case "#":
				return "\\d";			//any digit
			case "d":
				return "\\D";			//any non-digit character
			case "Z":
				return "[a-z,A-Z]";		//any upper or lower case character
			case "a":
				return "\\w";			//any word character
			case "@":
				return "\\W";			//any non-word character
			case "s":
				return "\\S";			//any non-whitespace character
			case "*":
				return ".";				//any character at all - wildcard
			default:
				return char;
		}
	};

	var insertKey = function(options) {		//Inserts the new character to it's position in the string based on cursor position
		var loc = getInputSelection(options.input[0]);
		var val = options.input.val().substring(0, loc.start) + options.key + options.input.val().substring(loc.end, options.input.val().length);
		return val;
	};

	var stripFormatting = function(formatString, fieldVal) {
		var strippedVal = "";
		var count = 0;
		var numChars = fieldVal.length;
		var index = 0;

		for (var i = 0; i < formatString.length; i++) {
			if (formatString[i].type === "input") {
				strippedVal += fieldVal.substr(i, 1);
				index++;
			}
			if (index === fieldVal.length) {
				break;
			}
		}
		return strippedVal;
	};

	var getInputSelection = function(el) {		//Finds the cursor position in the input string - includes highlighted ranges.
	    var start = 0, end = 0, normalizedValue, range,
	        textInputRange, len, endRange;

	    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
	        start = el.selectionStart;
	        end = el.selectionEnd;
	    } else {
	        range = document.selection.createRange();

	        if (range && range.parentElement() == el) {
	            len = el.value.length;
	            normalizedValue = el.value.replace(/\r\n/g, "\n");

	            // Create a working TextRange that lives only in the input
	            textInputRange = el.createTextRange();
	            textInputRange.moveToBookmark(range.getBookmark());

	            // Check if the start and end of the selection are at the very end
	            // of the input, since moveStart/moveEnd doesn't return what we want
	            // in those cases
	            endRange = el.createTextRange();
	            endRange.collapse(false);

	            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
	                start = end = len;
	            } else {
	                start = -textInputRange.moveStart("character", -len);
	                start += normalizedValue.slice(0, start).split("\n").length - 1;

	                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
	                    end = len;
	                } else {
	                    end = -textInputRange.moveEnd("character", -len);
	                    end += normalizedValue.slice(0, end).split("\n").length - 1;
	                }
	            }
	        }
	    }

	    return {
	        start: start,
	        end: end
	    };
	}

	return this;
}
<|endoftext|>


<commit_before>var dropdownPrep = function(){
  var dropdown = document.getElementById("lang");
  var option;
  for (var lang in l10n){
    option = document.createElement("option");
    option.innerHTML = l10n[lang];
    option.value = lang;
    dropdown.appendChild(option);
  }
}

var render = function(){
  var results = document.getElementsByClassName('finish');
  for (var i = 0; i < results.length; i++){
    results[i].style.display = 'block';
  }

  var dropdown = document.getElementById("lang");
  var lang = dropdown.value;
  var final = {};
  final[lang] = {};
  final[lang]['language'] = dropdown.selectedOptions[0].text;

  final[lang]["translator"] = document.getElementById('translator').value.replace(/[\"]/g, "\\\"");
  var unique1 = document.getElementById('unique1').value.replace(/[\"]/g, "\\\"") + "\n" + "

";
  var unique2 = document.getElementById('unique2').value.replace(/[\"]/g, "\\\"") + "
";
  var unique3 = document.getElementById('unique3').value.replace(/[\"]/g, "\\\"") + "
";
  var unique4 = document.getElementById('unique4').value.replace(/[\"]/g, "\\\"") + "
";
  final[lang]["unique"] = unique1 + unique2 + unique3 + unique4;

  var link = document.getElementById('link').value.replace(/[\"]/g, "\\\"") + "\n" + "
";
  var age = document.getElementById('age').value.replace(/[\"]/g, "\\\"") + "\n" + "
";
  var appropriate = document.getElementById('appropriate').value.replace(/[\"]/g, "\\\"") + "\n" + "
";
  var patience = document.getElementById('patience').value.replace(/[\"]/g, "\\\"") + "\n" + "

";
  var whatIsSDS = document.getElementById('whatIsSDS').value.replace(/[\"]/g, "\\\"") + "\n";
  var selected = " " + document.getElementById('selected').value.replace(/[\"]/g, "\\\"") + " " + "https://scratch.mit.edu/projects/55738732/" + "" + "\n";
  var ask = document.getElementById('ask').value.replace(/[\"]/g, "\\\"") + "\n" + "

";
  var idea = document.getElementById('idea').value.replace(/[\"]/g, "\\\"") + " " + "https://scratch.mit.edu/studios/93627/" + "" + "\n" + "

";
  var wiki = document.getElementById('wiki').value.replace(/[\"]/g, "\\\"") + " " + "http://wiki.scratch.mit.edu/wiki/SDS/" + "" + "\n" + "

";
  var account = document.getElementById('account').value.replace(/[\"]/g, "\\\"") +  " " + "@SDS-Updates" + "" + "\n" + "

";
  var thumbnail = document.getElementById('thumbnail').value.replace(/[\"]/g, "\\\"");
  final[lang]["standard"] = link + age + appropriate + patience + whatIsSDS + selected + ask + idea + wiki + account + thumbnail;

  var curators = document.getElementById('curatorsp').value.replace(/[\"]/g, "\\\"");
  var result = document.getElementById('result');
  final[lang]["curators"] = curators;

  result.value = JSON.stringify(final,null,2).slice(2,-2) + ",";
  console.log(JSON.stringify(final,null,2).slice(2,-2) + ",");
};

document.onkeyup = render;
<commit_msg>Update
<commit_after>var dropdownPrep = function(){
  var dropdown = document.getElementById("lang");
  var option;
  for (var lang in l10n){
    option = document.createElement("option");
    option.innerHTML = l10n[lang];
    option.value = lang;
    dropdown.appendChild(option);
  }
}

var render = function(){
  var results = document.getElementsByClassName('finish');
  for (var i = 0; i < results.length; i++){
    results[i].style.display = 'block';
  }

  var dropdown = document.getElementById("lang");
  var lang = dropdown.value;
  var final = {};
  final[lang] = {};
  final[lang]['language'] = dropdown.selectedOptions[0].text;

  final[lang]["translator"] = document.getElementById('translator').value.replace(/[\"]/g, "\\\"");
  var unique1 = document.getElementById('unique1').value.replace(/[\"]/g, "\\\"") + "\n" + "

";
  var unique2 = document.getElementById('unique2').value.replace(/[\"]/g, "\\\"") + "

";
  var unique3 = document.getElementById('unique3').value.replace(/[\"]/g, "\\\"") + "

";
  var unique4 = document.getElementById('unique4').value.replace(/[\"]/g, "\\\"") + "
";
  final[lang]["unique"] = unique1 + unique2 + unique3 + unique4;

  var link = document.getElementById('link').value.replace(/[\"]/g, "\\\"") + "\n" + "
";
  var age = document.getElementById('age').value.replace(/[\"]/g, "\\\"") + "\n" + "
";
  var appropriate = document.getElementById('appropriate').value.replace(/[\"]/g, "\\\"") + "\n" + "
";
  var patience = document.getElementById('patience').value.replace(/[\"]/g, "\\\"") + "\n" + "

";
  var whatIsSDS = document.getElementById('whatIsSDS').value.replace(/[\"]/g, "\\\"") + "\n";
  var selected = " " + document.getElementById('selected').value.replace(/[\"]/g, "\\\"") + " " + "https://scratch.mit.edu/projects/55738732/" + "" + "\n";
  var ask = document.getElementById('ask').value.replace(/[\"]/g, "\\\"") + "\n" + "

";
  var idea = document.getElementById('idea').value.replace(/[\"]/g, "\\\"") + " " + "https://scratch.mit.edu/studios/93627/" + "" + "\n" + "

";
  var wiki = document.getElementById('wiki').value.replace(/[\"]/g, "\\\"") + " " + "http://wiki.scratch.mit.edu/wiki/SDS/" + "" + "\n" + "

";
  var account = document.getElementById('account').value.replace(/[\"]/g, "\\\"") +  " " + "@SDS-Updates" + "" + "\n" + "

";
  var thumbnail = document.getElementById('thumbnail').value.replace(/[\"]/g, "\\\"");
  final[lang]["standard"] = link + age + appropriate + patience + whatIsSDS + selected + ask + idea + wiki + account + thumbnail;

  var curators = document.getElementById('curatorsp').value.replace(/[\"]/g, "\\\"");
  var result = document.getElementById('result');
  final[lang]["curators"] = curators;

  result.value = JSON.stringify(final,null,2).slice(2,-2) + ",";
  console.log(JSON.stringify(final,null,2).slice(2,-2) + ",");
};

document.onkeyup = render;
<|endoftext|>


<commit_before>export class NestedLoopJoins {

    static INNER (a, aAccessor, b, bAccessor) {
        var val,
            cval;
        return a.reduce((previous, datum) => {
            val = aAccessor(datum);
            return previous.concat(b.reduce((oPrevious, oDatum) => {
                cval = bAccessor(oDatum);
                if (val <= cval && val >= cval) {
                    oPrevious.shift(Object.assign({}, datum, oDatum));
                }
            }, []));
        }, []);
    }

    static OUTER (a, aAccessor, b, bAccessor) {
        var val,
            cval,
            found = {},
            tmpLength;
        return a.reduce((previous, datum) => {
            val = aAccessor(datum);
            tmpLength = previous.length;
            previous = previous.concat(b.reduce((oPrevious, oDatum, index) => {
                cval = bAccessor(oDatum);
                if (val <= cval && val >= cval) {
                    found[index] = true;
                    oPrevious.shift(Object.assign({}, datum, oDatum));
                }
                return oPrevious;
            }, []));
            if (tmpLength === previous.length) {
                previous.shift(datum);
            }
            return previous;
        }, []).concat(b.filter((datum, index) => {
            return !found.hasOwnProperty(index);
        }));
    }

    static LEFT_OUTER (a, aAccessor, b, bAccessor) {
        var val,
            cval,
            tmpLength;
        return a.reduce((previous, datum) => {
            val = aAccessor(datum);
            tmpLength = previous.length;
            previous = previous.concat(b.reduce((oPrevious, oDatum) => {
                cval = bAccessor(oDatum);
                if (val <= cval && val >= cval) {
                    oPrevious.shift(Object.assign({}, datum, oDatum));
                }
                return oPrevious;
            }, []));
            if (tmpLength === previous.length) {
                previous.shift(datum);
            }
            return previous;
        })
    }

    static LEFT_ANTI (a, aAccessor, b, bAccessor) {
        var val,
            cval;
        return a.filter((datum) => {
            val = aAccessor(datum);
            return b.every((oDatum) => {
                cval = bAccessor(oDatum);
                return !(val <= cval && val >= cval);
            });
        })
    }

    static LEFT_SEMI (a, aAccessor, b, bAccessor) {
        var val,
            cval;
        return a.filter((datum) => {
            val = aAccessor(datum);
            return b.some((oDatum) => {
                cval = bAccessor(oDatum);
                return val <= cval && val >= cval;
            });
        });
    }

    static RIGHT_OUTER (a, aAccessor, b, bAccessor) {
        return LEFT_OUTER(b, bAccessor, a, aAccessor);
    }

    static RIGHT_ANTI (a, aAccessor, b, bAccessor) {
        return LEFT_ANTI(b, bAccessor, a, aAccessor);
    }

    static RIGHT_SEMI (a, aAccessor, b, bAccessor) {
        return LEFT_SEMI(b, bAccessor, a, aAccessor);
    }
}<commit_msg>Removed files, not necessary<commit_after><|endoftext|>


<commit_before>/**
 * fluidinfo.js - a small and simple client for Fluidinfo written in Javascript.
 *
 * @author onigiri, ntoll & barshirtcliff
 * @version 0.1
 * @constructor
 * @param options {Object} Contains various parameters for the new session with
 * Fluidinfo.
 *

 *
username

 *
The username to use when authenticating with Fluidinfo.

 *
password

 *
The password to use when authenticating with Fluidinfo

 *
instance

 *
The instance to connect to. Either "main", "sandbox" or a bespoke
 *  instance. Defaults to "main".

 *

 * returns {Object} An object through which one interacts with Fluidinfo.
 */
fluidinfo = function(options) {
    /**
     * Encodes strings into base64. Adapted from:
     * http://www.webtoolkit.info/javascript-base64.html
    */
    var Base64 = {
        // private property
        _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // public method for encoding
        encode : function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            input = Base64._utf8_encode(input);
            while (i < input.length) {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output +
                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
            }
            return output;
        },
        // private method for UTF-8 encoding
        _utf8_encode : function (string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
            for (var n = 0; n < string.length; n++) {
                var c = string.charCodeAt(n);
                if (c < 128) {
                    utftext += String.fromCharCode(c);
                }
                else if((c > 127) && (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
                else {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
            }
            return utftext;
        }
    }

    /**
     * Represents a session with Fluidinfo.
     */
    var session = new Object();
    var authorizationToken = "";

    if(options) {
      if(options.instance) {
        switch(options.instance.toLowerCase()) {
          case "main":
            session.baseURL = "https://fluiddb.fluidinfo.com/";
            break;
          case "sandbox":
            session.baseURL = "https://sandbox.fluidinfo.com/";
            break;
          default:
              // validate the bespoke instance
              var urlRegex = /^(http|https):\/\/[\w\-_\.]+\/$/;
              if(urlRegex.exec(options.instance)) {
                session.baseURL = options.instance;
              } else {
                throw {
                  name: "ValueError",
                  message: "The URL must start with http[s]:// and have a trailing slash ('/') to be valid. E.g. https://localhost/"
                };
              }
        }
      }
      if((options.username != undefined) && (options.password != undefined)) {
        authorizationToken = Base64.encode(options.username + ":" + options.password);
      }
    }

    // Catch-all to make sure the library defaults to the main instance
    if(session.baseURL === undefined){
      session.baseURL = "https://fluiddb.fluidinfo.com/";
    }

    /**
     * Magic voodoo used to identify an array (potentially a Fluidinfo set).
     * Taken from page 61 of Doug Crockford's "Javascript: The Good Parts".
     *
     * @param value A value that might be an array.
     * @return {boolean} An indication if the value is an array.
     */
    function isArray(value) {
      return Object.prototype.toString.apply(value) === "[object Array]";
    };

    /**
     * Given a path that is expressed as an array of path elements, will
     * return the correctly encoded URL. e.g. ["a", "b", "c"] -> "/a/b/c"
     *
     * @param value {Array} A list of values to be appropriately encoded between
     * '/' values.
     * @return {string} The appropriately encoded URL.
     */
    function encodeURL(path) {
      var result = "";
      for(i=0; i<path.length; i++) {
        result += "/" + encodeURIComponent(path[i]);
      }
      return result.slice(1); // chops the leading slash
    };

    /**
     * Checks the passed value to discover if it's a Fluidinfo "primitive"
     * type. See
     * the Fluidinfo docs for more
     * information on Fluidinfo's types.
     *
     * @param value A value whose "type" needs identifying
     * @return A boolean indication if the value is a Fluidinfo primitive type.
     */
    function isPrimitive(value) {
      // check the easy type matches first
      var valueType = typeof(value);
      var primitiveTypes = ["number", "string", "boolean"];
      for(i=0; i<primitiveTypes.length; i++) {
        if(valueType === primitiveTypes[i]) {
          return true;
        }
      }
      // A null value is also a primitive
      if(value===null) {
        return true;
      }
      // check for an array (potential set) and validate it only contains
      // strings (currently multi-type arrays are not allowed)
      if(isArray(value)) {
        for(i=0; i<value.length; i++) {
          memberType = typeof(value[i]);
          if(memberType !== "string") {
            return false;
          }
        }
        return true;
      }
      // value hasn't matched any of the primitive checks
      return false;
    }

    /**
     * Given the options describing a request, will return the most appropriate
     * MIME to set as the value for the Content-Type header
     *
     * @param options {Object} Contains various parameters describing the
     * request.
     * @return the most appropriate MIME to use of null if not appropriate /
     * required.
     */
    function detectContentType(options) {
      // a "PUT" to objects/ or about/ endpoints means dealing with the MIME
      // of a tag-value. If no MIME type is passed in the options objects
      // then check if the value is a Fluidinfo primitive type. Otherwise
      // complain.
      var result = null;
      if(options.type==="PUT" && (options.path.match("^objects\/") || options.path.match("^about\/"))) {
        if(options.contentType){
          result = options.contentType;
        } else if (isPrimitive(options.data)) {
          result = "application/vnd.fluiddb.value+json";
        } else {
          throw { name: "ValueError", message: "Must supply Content-Type"};
        }
      } else if (options.data) {
        // all other requests to the API that have payloads will be passing JSON
        result = "application/json";
      }
      return result;
    }

    /**
     * Given a value from a Content-Type header, will return a boolean
     * indication if the associated content is JSON.
     *
     * @param contentType {string} The MIME value associated with the content
     * @result {boolean} An indication if the associated content is JSON
     */
    function isJSONData(contentType) {
      return contentType && (contentType === "application/json" || contentType === "application/vnd.fluiddb.value+json");
    }

    /**
     * Given an object representing the arguments to append to a URL will return
     * an appropriately encoded string representation.
     */
    function createArgs(args) {
      var result = "";
      if(args) {
        var arg;
        for(arg in args) {
          if(typeof args[arg] !== "function") {
              if(isArray(args[arg])) {
                for(j=0; j<args[arg].length; j++) {
                  result += "&" + encodeURIComponent(arg)+"="+encodeURIComponent(args[arg][j]);
                }
              } else {
                result += "&"+encodeURIComponent(arg)+"="+encodeURIComponent(args[arg]);
              }
            }
        }
        result = "?" + result.slice(1);
      }
      return result;
    }

    /**
     * Returns an appropriate XMLHttpRequest Object depending on the browser.
     * Based upon code from here:
     * http://www.quirksmode.org/js/xmlhttp.html
     */
    function createXMLHTTPObject() {
      var XMLHttpFactories = [
        function () {return new XMLHttpRequest()},
        function () {return new ActiveXObject("Msxml2.XMLHTTP")},
        function () {return new ActiveXObject("Msxml3.XMLHTTP")},
        function () {return new ActiveXObject("Microsoft.XMLHTTP")}
      ];
      var xhr = false;
      for(var i=0; i<XMLHttpFactories.length; i++) {
        try {
          xhr = XMLHttpFactories[i]();
        } catch(e) {
          continue;
        }
        break;
      }
      return xhr;
    }

    /**
     * Sends an appropriate XMLHTTPRequest based request to Fluidinfo.
     * @param options {Object} An object containing the following named options:
     *

     *
type

     *
The request's HTTP method. [GET, POST, PUT, DELETE or HEAD]

     *
url

     *
The full URL of the resource to which the request is made.

     *
data

     *
The body of data that may be the payload of the request (in the
     *  case of POST and PUT requests).

     *
async

     *
Indicates if the request is to be asyncronous (default is true)

     *
onSuccess

     *
A function that takes the XHR request as an argument. Called upon
     *  successful completion of the request.

     *
onError

     *
A function that takes the XHR request as an argument. Called when
     *  the request resulted in an error.

     *

     *
     */
    function sendRequest(options) {
      if(isArray(options.path)) {
        options.path = encodeURL(options.path);
      }
      var method = options.type.toUpperCase() || "GET";
      var args = createArgs(options.args);
      var url = session.baseURL+options.path+args;
      var async = options.async || true;
      var xhr = createXMLHTTPObject();
      if(!xhr) return;
      xhr.open(method, url, async);
      if(authorizationToken != ""){
        xhr.setRequestHeader("Authorization", "Basic " + authorizationToken);
      };
      var contentType = detectContentType(options);
      if(contentType) {
        xhr.setRequestHeader("Content-Type", contentType);
        if(isJSONData(contentType)) {
          options.data = JSON.stringify(options.data);
        }
      }
      xhr.onreadystatechange = function() {
        if(xhr.readyState != 4) return;
        // build a simple result object
        var result = new Object();
        result.status = xhr.status;
        result.statusText = xhr.statusText;
        result.headers = xhr.responseHeaders;
        result.raw_data = xhr.responseText;
        if(isJSONData(result.headers['Content-Type'])) {
          result.data = JSON.parse(xhr.responseText);
        } else {
          result.data = xhr.responseText;
        }
        result.request = xhr;
        // call the event handlers
        if(xhr.status < 300 || xhr.status == 304) {
          if(options.onSuccess){
            options.onSuccess(result);
          }
        } else if (options.onError){
          // there appears to be a problem
          options.onError(result);
        }
      }
      xhr.send(options.data)
    }

    /**
     * Contains functions to facilitate the calling of the Fluidinfo REST API.
     */
    var api = new Object();

    /**
     * Makes an HTTP GET call to the Fluidinfo API
     *
     */
    api.get = function(options){
      options.type = "GET";
      options.data = null;
      sendRequest(options);
    }

    /**
     * Makes an HTTP POST call to the Fluidinfo API
     *
     */
    api.post = function(options){
      options.type = "POST";
      sendRequest(options);
    }

    /**
     * Makes an HTTP PUT call to the Fluidinfo API
     *
     */
    api.put = function(options){
      options.type = "PUT";
      sendRequest(options);
    }

    /**
     * Makes an HTTP DELETE call to the Fluidinfo API
     *
     */
    api.delete = function(options){
      options.type = "DELETE";
      options.data = null;
      sendRequest(options);
    }

    /**
     * Makes an HTTP HEAD call to the Fluidinfo API
     *
     */
    api.head = function(options){
      options.type = "HEAD";
      options.data = null;
      sendRequest(options);
    }

    session.api = api;

    /**
     * Easily gets results from Fluidinfo.
     */
    session.query = function(options) {
      // process the options
      if(options.select === undefined) {
        throw {
          name: "ValueError",
          message: "Missing select option."
        }
      }
      if(options.where === undefined) {
        throw {
          name: "ValueError",
          message: "Missing where option."
        }
      }
      /**
       * Takes the raw result from Fluidinfo and turns it into an easy-to-use
       * array of useful objects representing the matching results then calls
       * the onSuccess function with the newly created array.
       *
       * @param {Object} The raw result from Fluidinfo that is to be processed
       */
      var processResult = function(raw) {
        result = [];
        var data = raw.data.results;
        var objectID;
        for(objectID in data.id){
          if(typeof data.id[objectID] !== "function") {
            var obj = new Object();
            obj["id"] = objectID;
            for(tag in data.id[objectID]) {
              if(typeof data.id[objectID][tag] !== "function") {
                if(data.id[objectID][tag].value !== undefined) {
                  obj[tag] = data.id[objectID][tag].value;
                } else {
                  obj[tag] = data.id[objectID][tag];
                }
              }
            }
            result[result.length] = obj;
          }
        }
        raw.data = result;
        options.onSuccess(raw);
      }
      // Make the appropriate call to Fluidinfo
      this.api.get({path: "values",
        args: {tag: options.select, query: options.where},
        onSuccess: processResult, onError: options.onError});
    }

    /**
     * Easily updates results from Fluidinfo.
     */
    session.update = function(options) {
      // process the options
      if(options.values === undefined) {
        throw {
          name: "ValueError",
          message: "Missing values option."
        }
      }
      if(options.where === undefined) {
        throw {
          name: "ValueError",
          message: "Missing where option."
        }
      }
      var payload = new Object();
      var queries = [];
      var updateSpecification = [];
      updateSpecification[0] = options.where;
      var valueSpec = new Object();
      for(val in options.values){
        if(typeof options.values[val] !== "function") {
          valueSpec[val]= {value: options.values[val]};
        }
      }
      updateSpecification[1] = valueSpec;
      queries[0] = updateSpecification;
      payload["queries"] = queries;
      // Make the appropriate call to Fluidinfo
      this.api.put({path: "values", data: payload,
        onSuccess: options.onSuccess, onError: options.onError});
    }

    return session;
}
<commit_msg>Damn damn damn damn damn damn damn. Updated function comment to actually make sense and reflect what the damn thing does. Obviously having a bad afternoon...<commit_after>/**
 * fluidinfo.js - a small and simple client for Fluidinfo written in Javascript.
 *
 * @author onigiri, ntoll & barshirtcliff
 * @version 0.1
 * @constructor
 * @param options {Object} Contains various parameters for the new session with
 * Fluidinfo.
 *

 *
username

 *
The username to use when authenticating with Fluidinfo.

 *
password

 *
The password to use when authenticating with Fluidinfo

 *
instance

 *
The instance to connect to. Either "main", "sandbox" or a bespoke
 *  instance. Defaults to "main".

 *

 * returns {Object} An object through which one interacts with Fluidinfo.
 */
fluidinfo = function(options) {
    /**
     * Encodes strings into base64. Adapted from:
     * http://www.webtoolkit.info/javascript-base64.html
    */
    var Base64 = {
        // private property
        _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // public method for encoding
        encode : function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            input = Base64._utf8_encode(input);
            while (i < input.length) {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output +
                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
            }
            return output;
        },
        // private method for UTF-8 encoding
        _utf8_encode : function (string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
            for (var n = 0; n < string.length; n++) {
                var c = string.charCodeAt(n);
                if (c < 128) {
                    utftext += String.fromCharCode(c);
                }
                else if((c > 127) && (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
                else {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
            }
            return utftext;
        }
    }

    /**
     * Represents a session with Fluidinfo.
     */
    var session = new Object();
    var authorizationToken = "";

    if(options) {
      if(options.instance) {
        switch(options.instance.toLowerCase()) {
          case "main":
            session.baseURL = "https://fluiddb.fluidinfo.com/";
            break;
          case "sandbox":
            session.baseURL = "https://sandbox.fluidinfo.com/";
            break;
          default:
              // validate the bespoke instance
              var urlRegex = /^(http|https):\/\/[\w\-_\.]+\/$/;
              if(urlRegex.exec(options.instance)) {
                session.baseURL = options.instance;
              } else {
                throw {
                  name: "ValueError",
                  message: "The URL must start with http[s]:// and have a trailing slash ('/') to be valid. E.g. https://localhost/"
                };
              }
        }
      }
      if((options.username != undefined) && (options.password != undefined)) {
        authorizationToken = Base64.encode(options.username + ":" + options.password);
      }
    }

    // Catch-all to make sure the library defaults to the main instance
    if(session.baseURL === undefined){
      session.baseURL = "https://fluiddb.fluidinfo.com/";
    }

    /**
     * Magic voodoo used to identify an array (potentially a Fluidinfo set).
     * Taken from page 61 of Doug Crockford's "Javascript: The Good Parts".
     *
     * @param value A value that might be an array.
     * @return {boolean} An indication if the value is an array.
     */
    function isArray(value) {
      return Object.prototype.toString.apply(value) === "[object Array]";
    };

    /**
     * Given a path that is expressed as an array of path elements, will
     * return the correctly encoded URL. e.g. ["a", "b", "c"] -> "/a/b/c"
     *
     * @param value {Array} A list of values to be appropriately encoded between
     * '/' values.
     * @return {string} The appropriately encoded URL.
     */
    function encodeURL(path) {
      var result = "";
      for(i=0; i<path.length; i++) {
        result += "/" + encodeURIComponent(path[i]);
      }
      return result.slice(1); // chops the leading slash
    };

    /**
     * Checks the passed value to discover if it's a Fluidinfo "primitive"
     * type. See
     * the Fluidinfo docs for more
     * information on Fluidinfo's types.
     *
     * @param value A value whose "type" needs identifying
     * @return A boolean indication if the value is a Fluidinfo primitive type.
     */
    function isPrimitive(value) {
      // check the easy type matches first
      var valueType = typeof(value);
      var primitiveTypes = ["number", "string", "boolean"];
      for(i=0; i<primitiveTypes.length; i++) {
        if(valueType === primitiveTypes[i]) {
          return true;
        }
      }
      // A null value is also a primitive
      if(value===null) {
        return true;
      }
      // check for an array (potential set) and validate it only contains
      // strings (currently multi-type arrays are not allowed)
      if(isArray(value)) {
        for(i=0; i<value.length; i++) {
          memberType = typeof(value[i]);
          if(memberType !== "string") {
            return false;
          }
        }
        return true;
      }
      // value hasn't matched any of the primitive checks
      return false;
    }

    /**
     * Given the options describing a request, will return the most appropriate
     * MIME to set as the value for the Content-Type header
     *
     * @param options {Object} Contains various parameters describing the
     * request.
     * @return the most appropriate MIME to use of null if not appropriate /
     * required.
     */
    function detectContentType(options) {
      // a "PUT" to objects/ or about/ endpoints means dealing with the MIME
      // of a tag-value. If no MIME type is passed in the options objects
      // then check if the value is a Fluidinfo primitive type. Otherwise
      // complain.
      var result = null;
      if(options.type==="PUT" && (options.path.match("^objects\/") || options.path.match("^about\/"))) {
        if(options.contentType){
          result = options.contentType;
        } else if (isPrimitive(options.data)) {
          result = "application/vnd.fluiddb.value+json";
        } else {
          throw { name: "ValueError", message: "Must supply Content-Type"};
        }
      } else if (options.data) {
        // all other requests to the API that have payloads will be passing JSON
        result = "application/json";
      }
      return result;
    }

    /**
     * Given a value from a Content-Type header, will return a boolean
     * indication if the associated content is JSON.
     *
     * @param contentType {string} The MIME value associated with the content
     * @result {boolean} An indication if the associated content is JSON
     */
    function isJSONData(contentType) {
      return contentType && (contentType === "application/json" || contentType === "application/vnd.fluiddb.value+json");
    }

    /**
     * Given an object representing the arguments to append to a URL will return
     * an appropriately encoded string representation.
     */
    function createArgs(args) {
      var result = "";
      if(args) {
        var arg;
        for(arg in args) {
          if(typeof args[arg] !== "function") {
              if(isArray(args[arg])) {
                for(j=0; j<args[arg].length; j++) {
                  result += "&" + encodeURIComponent(arg)+"="+encodeURIComponent(args[arg][j]);
                }
              } else {
                result += "&"+encodeURIComponent(arg)+"="+encodeURIComponent(args[arg]);
              }
            }
        }
        result = "?" + result.slice(1);
      }
      return result;
    }

    /**
     * Returns an appropriate XMLHttpRequest Object depending on the browser.
     * Based upon code from here:
     * http://www.quirksmode.org/js/xmlhttp.html
     */
    function createXMLHTTPObject() {
      var XMLHttpFactories = [
        function () {return new XMLHttpRequest()},
        function () {return new ActiveXObject("Msxml2.XMLHTTP")},
        function () {return new ActiveXObject("Msxml3.XMLHTTP")},
        function () {return new ActiveXObject("Microsoft.XMLHTTP")}
      ];
      var xhr = false;
      for(var i=0; i<XMLHttpFactories.length; i++) {
        try {
          xhr = XMLHttpFactories[i]();
        } catch(e) {
          continue;
        }
        break;
      }
      return xhr;
    }

    /**
     * Sends an appropriate XMLHTTPRequest based request to Fluidinfo.
     * @param options {Object} An object containing the following named options:
     *

     *
type

     *
The request's HTTP method. [GET, POST, PUT, DELETE or HEAD]

     *
url

     *
The full URL of the resource to which the request is made.

     *
data

     *
The body of data that may be the payload of the request (in the
     *  case of POST and PUT requests).

     *
async

     *
Indicates if the request is to be asyncronous (default is true)

     *
onSuccess

     *
A function that takes the XHR request as an argument. Called upon
     *  successful completion of the request.

     *
onError

     *
A function that takes the XHR request as an argument. Called when
     *  the request resulted in an error.

     *

     *
     */
    function sendRequest(options) {
      if(isArray(options.path)) {
        options.path = encodeURL(options.path);
      }
      var method = options.type.toUpperCase() || "GET";
      var args = createArgs(options.args);
      var url = session.baseURL+options.path+args;
      var async = options.async || true;
      var xhr = createXMLHTTPObject();
      if(!xhr) return;
      xhr.open(method, url, async);
      if(authorizationToken != ""){
        xhr.setRequestHeader("Authorization", "Basic " + authorizationToken);
      };
      var contentType = detectContentType(options);
      if(contentType) {
        xhr.setRequestHeader("Content-Type", contentType);
        if(isJSONData(contentType)) {
          options.data = JSON.stringify(options.data);
        }
      }
      xhr.onreadystatechange = function() {
        if(xhr.readyState != 4) return;
        // build a simple result object
        var result = new Object();
        result.status = xhr.status;
        result.statusText = xhr.statusText;
        result.headers = xhr.responseHeaders;
        result.raw_data = xhr.responseText;
        if(isJSONData(result.headers['Content-Type'])) {
          result.data = JSON.parse(xhr.responseText);
        } else {
          result.data = xhr.responseText;
        }
        result.request = xhr;
        // call the event handlers
        if(xhr.status < 300 || xhr.status == 304) {
          if(options.onSuccess){
            options.onSuccess(result);
          }
        } else if (options.onError){
          // there appears to be a problem
          options.onError(result);
        }
      }
      xhr.send(options.data)
    }

    /**
     * Contains functions to facilitate the calling of the Fluidinfo REST API.
     */
    var api = new Object();

    /**
     * Makes an HTTP GET call to the Fluidinfo API
     *
     */
    api.get = function(options){
      options.type = "GET";
      options.data = null;
      sendRequest(options);
    }

    /**
     * Makes an HTTP POST call to the Fluidinfo API
     *
     */
    api.post = function(options){
      options.type = "POST";
      sendRequest(options);
    }

    /**
     * Makes an HTTP PUT call to the Fluidinfo API
     *
     */
    api.put = function(options){
      options.type = "PUT";
      sendRequest(options);
    }

    /**
     * Makes an HTTP DELETE call to the Fluidinfo API
     *
     */
    api.delete = function(options){
      options.type = "DELETE";
      options.data = null;
      sendRequest(options);
    }

    /**
     * Makes an HTTP HEAD call to the Fluidinfo API
     *
     */
    api.head = function(options){
      options.type = "HEAD";
      options.data = null;
      sendRequest(options);
    }

    session.api = api;

    /**
     * Easily gets results from Fluidinfo.
     */
    session.query = function(options) {
      // process the options
      if(options.select === undefined) {
        throw {
          name: "ValueError",
          message: "Missing select option."
        }
      }
      if(options.where === undefined) {
        throw {
          name: "ValueError",
          message: "Missing where option."
        }
      }
      /**
       * Takes the raw result from Fluidinfo and turns it into an easy-to-use
       * array of useful objects representing the matching results then calls
       * the onSuccess function with the newly created array.
       *
       * @param {Object} The raw result from Fluidinfo that is to be processed
       */
      var processResult = function(raw) {
        result = [];
        var data = raw.data.results;
        var objectID;
        for(objectID in data.id){
          if(typeof data.id[objectID] !== "function") {
            var obj = new Object();
            obj["id"] = objectID;
            for(tag in data.id[objectID]) {
              if(typeof data.id[objectID][tag] !== "function") {
                if(data.id[objectID][tag].value !== undefined) {
                  obj[tag] = data.id[objectID][tag].value;
                } else {
                  obj[tag] = data.id[objectID][tag];
                }
              }
            }
            result[result.length] = obj;
          }
        }
        raw.data = result;
        options.onSuccess(raw);
      }
      // Make the appropriate call to Fluidinfo
      this.api.get({path: "values",
        args: {tag: options.select, query: options.where},
        onSuccess: processResult, onError: options.onError});
    }

    /**
     * Easily updates objects in Fluidinfo.
     */
    session.update = function(options) {
      // process the options
      if(options.values === undefined) {
        throw {
          name: "ValueError",
          message: "Missing values option."
        }
      }
      if(options.where === undefined) {
        throw {
          name: "ValueError",
          message: "Missing where option."
        }
      }
      var payload = new Object();
      var queries = [];
      var updateSpecification = [];
      updateSpecification[0] = options.where;
      var valueSpec = new Object();
      for(val in options.values){
        if(typeof options.values[val] !== "function") {
          valueSpec[val]= {value: options.values[val]};
        }
      }
      updateSpecification[1] = valueSpec;
      queries[0] = updateSpecification;
      payload["queries"] = queries;
      // Make the appropriate call to Fluidinfo
      this.api.put({path: "values", data: payload,
        onSuccess: options.onSuccess, onError: options.onError});
    }

    return session;
}
<|endoftext|>


<commit_before>/* eslint-disable no-console, react/forbid-prop-types */

import React, { Component } from 'react';
import { Route, withRouter, Switch } from 'react-router-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import * as CookieHelpers from 'shared/utils/cookieHelper';
import familyImage from 'images/Family-2.jpg';
import SignUp from './signup/signup';
import MentorRequestsTable from './mentor/mentorRequestsTable/mentorRequestsTable';
import SquadsTable from './squads/squadsTable/squadsTable';
import Dashboard from './dashboard/dashboard';
import MentorsTable from './mentor/mentorsTable/mentorsTable';
import Thanks from './thanks/thanks';
import Gala from './gala/gala';
import FinancialStatements from './about/financialStatements/financialStatements';
import styles from './home.css';
import Header from './header/header';
import Landing from './landing/landing';
import Footer from './footer/footer';
import FourOhFour from './404/fourOhFour';
import MentorRequest from './mentorRequest/mentorRequest';
import SquadsNew from './squads/squadsNew/squadsNew';
import CodeSchools from './codeSchools/codeSchools';

class Home extends Component {
  constructor(props) {
    super(props);
    this.state = {
      bgImage: false,
      bgImageUrl: null,
      signedIn: false,
      mentor: false
    };

    this.props.history.listen((location) => {
      this.setBgImage(location);
    });
  }

  componentWillMount() {
    this.setBgImage(this.props.location);
    const cookies = CookieHelpers.getUserStatus();
    this.setState({
      signedIn: cookies.signedIn,
      mentor: cookies.mentor
    });
  }

  setBgImage(location) {
    if (location.pathname === '/') {
      this.setState({ bgChanged: !(this.state.bgImage), bgImage: true, bgImageUrl: familyImage });
    } else {
      this.setState({ bgChanged: this.state.bgImage, bgImage: false, bgImageUrl: null });
    }
  }

  updateRootAuthState = () => {
    this.setState({
      mentor: true,
      signedIn: true
    });
  }

  logOut = () => {
    CookieHelpers.clearAuthCookies();
    window.location = '/';
  }

  render() {
    const { mentor, signedIn } = this.state;
    const authProps = {
      signedIn,
      mentor
    };
    const classes = classNames({
      [`${styles.home}`]: true,
      [`${styles.backgroundImage}`]: this.state.bgImage
    });
    return (
      <div
        className={classes}
        style={(this.state.bgImage) ? { backgroundImage: `url(${this.state.bgImageUrl})` } : {}}
      >

          <Switch>
            <Route
              path="/home"
              component={Dashboard}
            />
            <Route
              path="/code-schools"
              component={CodeSchools}
            />
            <Route
              path="/code_schools"
              component={CodeSchools}
            />
            <Route
              path="/signup"
              component={SignUp}
            />
            <Route
              path="/join"
              component={SignUp}
            />
            <Route
              path="/sign-up"
              component={SignUp}
            />
            <Route
              path="/thanks"
              component={Thanks}
            />
            <Route
              exact
              path="/"
              render={props => (
                <Landing {...props} />
              )}
            />
            <Route
              path="/mentor-request"
              render={() => (
                <MentorRequest {...authProps} />
              )}
            />
            <Route
              path="/requests"
              render={() => (
                <MentorRequestsTable {...authProps} />
              )}
            />
            <Route
              path="/squads/new-squad"
              render={() => (
                <SquadsNew {...authProps} />
              )}
            />
            <Route
              exact path="/mentors"
              render={() => (
                <MentorsTable {...authProps} />
              )}
            />
            <Route
              path="/squads"
              render={() => (
                <SquadsTable {...authProps} />
              )}
            />
            <Route
              path="/gala"
              render={() => (
                <Gala {...authProps} />
              )}
            />
            <Route exact path="/about/financial-statements" component={FinancialStatements} />
            <Route
              path="*" component={FourOhFour}
            />
          </Switch>

    );
  }
}

Home.propTypes = {
  history: PropTypes.object.isRequired,
  location: PropTypes.object.isRequired
};

export default withRouter(Home);
<commit_msg>Adds a wildcard route to handle the Id.Me auth redirect<commit_after>/* eslint-disable no-console, react/forbid-prop-types */

import React, { Component } from 'react';
import { Route, withRouter, Switch } from 'react-router-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import * as CookieHelpers from 'shared/utils/cookieHelper';
import familyImage from 'images/Family-2.jpg';
import SignUp from './signup/signup';
import MentorRequestsTable from './mentor/mentorRequestsTable/mentorRequestsTable';
import SquadsTable from './squads/squadsTable/squadsTable';
import Dashboard from './dashboard/dashboard';
import MentorsTable from './mentor/mentorsTable/mentorsTable';
import Thanks from './thanks/thanks';
import Gala from './gala/gala';
import FinancialStatements from './about/financialStatements/financialStatements';
import styles from './home.css';
import Header from './header/header';
import Landing from './landing/landing';
import Footer from './footer/footer';
import FourOhFour from './404/fourOhFour';
import MentorRequest from './mentorRequest/mentorRequest';
import SquadsNew from './squads/squadsNew/squadsNew';
import CodeSchools from './codeSchools/codeSchools';

class Home extends Component {
  constructor(props) {
    super(props);
    this.state = {
      bgImage: false,
      bgImageUrl: null,
      signedIn: false,
      mentor: false
    };

    this.props.history.listen((location) => {
      this.setBgImage(location);
    });
  }

  componentWillMount() {
    this.setBgImage(this.props.location);
    const cookies = CookieHelpers.getUserStatus();
    this.setState({
      signedIn: cookies.signedIn,
      mentor: cookies.mentor
    });
  }

  setBgImage(location) {
    if (location.pathname === '/') {
      this.setState({ bgChanged: !(this.state.bgImage), bgImage: true, bgImageUrl: familyImage });
    } else {
      this.setState({ bgChanged: this.state.bgImage, bgImage: false, bgImageUrl: null });
    }
  }

  updateRootAuthState = () => {
    this.setState({
      mentor: true,
      signedIn: true
    });
  }

  logOut = () => {
    CookieHelpers.clearAuthCookies();
    window.location = '/';
  }

  render() {
    const { mentor, signedIn } = this.state;
    const authProps = {
      signedIn,
      mentor
    };
    const classes = classNames({
      [`${styles.home}`]: true,
      [`${styles.backgroundImage}`]: this.state.bgImage
    });
    return (
      <div
        className={classes}
        style={(this.state.bgImage) ? { backgroundImage: `url(${this.state.bgImageUrl})` } : {}}
      >

          <Switch>
            <Route
              path="/home"
              component={Dashboard}
            />
            <Route
              path="/code-schools"
              component={CodeSchools}
            />
            <Route
              path="/code_schools"
              component={CodeSchools}
            />
            <Route
              path="/signup"
              component={SignUp}
            />
            <Route
              path="/join"
              component={SignUp}
            />
            <Route
              path="/sign-up"
              component={SignUp}
            />
            <Route
              path="/thanks"
              component={Thanks}
            />
            <Route
              exact
              path="/"
              render={props => (
                <Landing {...props} />
              )}
            />
            <Route
              path="/mentor-request"
              render={() => (
                <MentorRequest {...authProps} />
              )}
            />
            <Route
              path="/requests"
              render={() => (
                <MentorRequestsTable {...authProps} />
              )}
            />
            <Route
              path="/squads/new-squad"
              render={() => (
                <SquadsNew {...authProps} />
              )}
            />
            <Route
              exact path="/mentors"
              render={() => (
                <MentorsTable {...authProps} />
              )}
            />
            <Route
              path="/squads"
              render={() => (
                <SquadsTable {...authProps} />
              )}
            />
            <Route
              path="/gala"
              render={() => (
                <Gala {...authProps} />
              )}
            />
            <Route
              path="/profile/verify"
              component={Thanks}
            />
            <Route exact path="/about/financial-statements" component={FinancialStatements} />
            <Route
              path="*" component={FourOhFour}
            />
          </Switch>

    );
  }
}

Home.propTypes = {
  history: PropTypes.object.isRequired,
  location: PropTypes.object.isRequired
};

export default withRouter(Home);
<|endoftext|>