<commit_before>/*
 * SimpleJS v0.0.1
 * https://github.com/TylerOBrien/SimpleJS
 *
 * Copyright (c) 2012 Tyler O'Brien
 *
 * 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.
 * */

/*
 * AJAX fallback for IE6.
 * Might not work for IE5 and earlier.
 * */
if (typeof XMLHttpRequest === 'undefined') {
	var XMLHttpRequest = function() {
		return new ActiveXObject('Microsoft.XMLHTTP');
	};
	XMLHttpRequest.prototype.isActiveX = true;
} else {
	XMLHttpRequest.prototype.isActiveX = false;
}

/*
 * send_s() returns Nothing
 * Input: Object
    * A "safe" version of XMLHttpRequest.send().
    * Is compatible with both ActiveX-based AJAX and otherwise.
    * */
XMLHttpRequest.prototype.send_s = function(args) {
	if (typeof args === 'undefined' || args === null) {
		if (this.isActiveX) this.send();
		else this.send(null);
	} else if ('method' in args && 'queryString' in args && args.method === 'POST') {
		this.send(args.queryString);
	} else {
		this.send_s();
	}
}

/*
 * decodeQueryString() returns Object
 * Input: Nothing
    * Converts the string to an Object that represents a query string.
    * Examples of valid formats:
       * ?id=42&email=foo@bar.com&type=helloworld
       * &id=42&foo&name=John+Doe
       * foo&bar
    * */
String.prototype.decodeQueryString = function() {
	var buffer;
	var queryString = this.replace('+', ' ');
	var regex = /[?&]?([^&=]+)=?([^&]+)?/g;
	var result = {};

	while (buffer = regex.exec(queryString)) {
		result[decodeURIComponent(buffer[1])] = decodeURIComponent(buffer[2]);
	}

	return result;
};

var Simple = {
	AJAX: function(args) {
		var ajaxRequest = new Simple.AJAXRequest(args);

		ajaxRequest.http.open(ajaxRequest.method, ajaxRequest.urlToOpen, true);
		ajaxRequest.http.setRequestHeader('Content-type', ajaxRequest.contentType+'; charset='+ajaxRequest.charset);

		if (ajaxRequest.method === 'POST') {
			ajaxRequest.http.setRequestHeader('Content-length', ajaxRequest.queryString.length);
			ajaxRequest.http.setRequestHeader('Connection', 'close');
		}

		ajaxRequest.http.onreadystatechange = function(){
			switch (ajaxRequest.http.readyState) {
				case 1:
					ajaxRequest.timeBegin = new Date().getTime();
					Simple.AJAXHandler.CallIfExists(ajaxRequest.onConnect);
				break;
				case 2:
					Simple.AJAXHandler.CallIfExists(ajaxRequest.onRequest);
				break;
				case 3:
					Simple.AJAXHandler.CallIfExists(ajaxRequest.onProcess);
				break;
				case 4:
					if (typeof ajaxRequest.timeout !== 'undefined') {
						clearTimeout(ajaxRequest.timeout);
					}

					ajaxRequest.timeEnd = new Date().getTime();
					ajaxRequest.timeDifference = (ajaxRequest.timeEnd - ajaxRequest.timeBegin);

					switch (ajaxRequest.http.status) {
						case 200:
							Simple.AJAXHandler.CallIfExists(ajaxRequest.onSuccess, ajaxRequest.http.responseText, ajaxRequest.timeDifference);
						break;
						case 404:
							Simple.AJAXHandler.CallIfExists(ajaxRequest.onNotFound, ajaxRequest.http.responseText, ajaxRequest.timeDifference);
						default:
							Simple.AJAXHandler.CallIfExists(ajaxRequest.onError, ajaxRequest.http.status, ajaxRequest.timeDifference);
						break;
					}
				break;
			}
		};

		/*
		 * Add a new timeout if one is given.
		 * The time is assumed to be milliseconds.
		 * */
		if ('timeout' in args && args['timeout'] === true) {
			ajaxRequest.timeout = setTimeout(function() {
				ajaxRequest.http.abort();
				Simple.AJAXHandler.CallIfExists(ajaxRequest.onTimeout);
			}, args['timeout']);
		}

		ajaxRequest.http.send_s(ajaxRequest);
	},

	/*
	 * AJAXHandler
	 * This object contains boilerplate functions that help organise the code of Simple AJAX.
	 * These probably won't need to be used outside of the AjaxRequest constructor function.
	 * Note:
		* These functions are also where the default values are assigned.
	 * */
	AJAXHandler: {
		/*
		 * CallIfExists() returns Nothing
		 * Input: Function, Mixed, Mixed
			* Takes a callback, and up to two optional parameters.
			* Depending on the number of parameters given will make one of three different calls.
			* */
		CallIfExists: function(callback, param1, param2) {
			if (typeof callback === 'function') {
				if (typeof param2 !== 'undefined') callback(param1, param2);
				else if (typeof param1 !== 'undefined') callback(param1);
				else callback();
			}
		},

		/*
		 * GetCarset() returns String
		 * Input: String
		 * */
		GetCharset: function(charset) {
			return (typeof charset === 'string') ? charset : 'utf-8';
		},

		/*
		 * GetContentType() returns String
		 * Input: String
		 */
		GetContentType: function(contentType) {
			return (typeof contentType === 'string') ? contentType : 'application/x-www-form-urlencoded';
		},

		/*
		 * GetMethod() returns String
		 * Input: String
		 */
		GetMethod: function(method) {
			return (typeof method === 'string') ? method : 'GET';
		},

		/*
		 * GetQueryString() returns String
		 * Input: Object
		 * Takes an object of (key=>value) pairs and converts them to a query string.
		 * For example:
			* The object {a:1,b:2,c:3} would become "a=1&b=2&c=3".
			* Note that the question mark is not appended to the beginning.
		 * */
		GetQueryString: function(data) {
			var output = '';

			if (typeof data !== 'undefined') {
				var output = '';

				for (var key in data) {
					output = (output + key +'='+ data[key] + '&');
				}

				// Trim off the extra ampersand.
				output = output.substring(0, output.length-1);
			}

			return output;
		},

		/*
		 * GetUrl() returns String
		 * Input: String
		 */
		GetUrl: function(url) {
			return (typeof url === 'string') ? url : '/';
		},

		/*
		 * GetUrlToOpen() returns String
		 * Input: String, String, String
			* Returns the value that will be passed to the XMLHttpRequest.open() function.
			* If the method is a GET it will be the entire URL, as well as the query string.
			* If the method is a POST then it will only be the query string.
			* */
		GetUrlToOpen: function(url, queryString, method) {
			return (method === 'POST') ? url : (url + '?' + queryString);
		}
	},

	AJAXRequest: function(args) {
		this.charset = Simple.AJAXHandler.GetCharset(args['charset']);
		this.contentType = Simple.AJAXHandler.GetContentType(args['contentType']);
		this.http = new XMLHttpRequest();
		this.method = Simple.AJAXHandler.GetMethod(args['method']);
		this.onConnect = args['onConnect'];
		this.onError = args['onError'];
		this.onNotFound = args['onNotFound'];
		this.onProcess = args['onProcess'];
		this.onRequest = args['onRequest'];
		this.onSuccess = args['onSuccess'];
		this.onTimeout = args['onTimeout'];
		this.queryString = Simple.AJAXHandler.GetQueryString(args['data']);
		this.timeBegin = 0;
		this.timeDifference = 0;
		this.timeEnd = 0;
		this.timeout = null;
		this.url = Simple.AJAXHandler.GetUrl(args['url']);
		this.urlToOpen = Simple.AJAXHandler.GetUrlToOpen(this.url, this.queryString, this.method);
	},

	Cookie: {
		data: {},

		DoUpdateData: function() {
			this.data = {};

			var arr = document.cookie.split('; ');
			var buffer = null;
			var cookie = null;
			var regex = /([^=]+)=(.*)/;

			Simple.Each(arr, function(){
				cookie = regex.exec(this);
				Simple.Cookie.data[escape(cookie[1])] = escape(cookie[2]);
			});
		},

		/*
		 * Get() returns Mixed
		 * Input: String
		 * */
		Get: function(name) {
			if (this.data === null) {
				this.DoUpdateData();
			}
			return Simple.Cookie.data[name];
		},

		/*
		 * Set() returns Nothing
		 * Input: String, String, String(Optional)
		 * */
		Set: function(name, value, expiration) {
			document.cookie = (name+'='+value+';') + (expiration ? ' expires=0;' : '');
			this.DoUpdateData();
		}
	},

	/*
	 * Each() returns Nothing
	 * Input: Array|Object, Function
	    *
	    * */
	Each: function (haystack, callback) {
		if (typeof haystack !== 'undefined' && haystack !== null) {
			var iterator = {
				i: null,
				parent: haystack,
				value: null
			};
			if (haystack.forEach !== undefined) {
				var end = haystack.length;
				for (var i = 0; i < end; i++) {
					iterator.value = haystack[i];
					if (callback.call(iterator.value, iterator) === false) {
						break;
					}
				}
			} else {
				for (iterator.i in haystack) {
					iterator.value = haystack[iterator.i];
					if (callback.call(iterator.value, iterator) === false) {
						break;
					}
				}
			}
		}
	},

	/*
	 * Equals() returns Boolean
	 * Input: Mixed, Mixed
	    * Compares each element of both passed objects, checking for strict equality.
	    * */
	Equals: function(first, second) {
		var result = true;

		Simple.Each(first, function(itr) {
			if (itr.value !== second[itr.index]) {
				return result = false;
			}
		});

		return result;
	},

	/*
	 * Exists() returns Mixed
	 * Input: Mixed, Mixed, Boolean
	    *
	    * */
	Exists: function(value, override, doReturnBoolean) {
		var output;

		if (typeof value !== 'undefined') {
			output = value;
		} else if (typeof doReturnBoolean !== 'undefined' && doReturnBoolean === true) {
			output = false;
		} else {
			output = override;
		}

		return output;
	},

	DOM: {
		callbacks: [], // The array of each callback function to be called when the DOM is ready.
		isReady: false, // This boolean is used to ensure that DOM.OnReady is only called once.

		/*
		 * OnDOMContentLoaded() returns Nothing
		 * Input: Nothing
		    * The function called by the event listeners.
		    * Because of the legacy event listener this may be called twice.
		    * */
		OnDOMContentLoaded: function() {
			if (typeof document.addEventListener !== 'undefined') {
				document.removeEventListener('DOMContentLoaded', Simple.DOM.OnDOMContentLoaded, false);
				Simple.DOM.OnReady();
			} else if (typeof document.attachEvent !== 'undefined' && document.readyState === 'complete' && document.body !== null) {
				document.detachEvent('onreadystatechange', Simple.DOM.OnDOMContentLoaded);
				Simple.DOM.OnReady();
			}
		},

		/*
		 * OnReady() returns Nothing
		 * Input: Nothing
		    * The function called when the DOM has finished loading/is ready.
		    * Uses a boolean to prevent multiple calls because it may be called twice by
		    * the event listener and legacy event listener.
		    * */
		OnReady: function() {
			if (Simple.DOM.isReady === false) {
				if (Simple.DOM.callbacks.length > 0) {
					Simple.Each(Simple.DOM.callbacks, function(){
						this.call(null);
					});
				}
				Simple.DOM.isReady = true;
			}
		},

		/*
		 * WhenReady() returns Nothing
		 * Input: Function
		    * Adds the passed callback to the array of callbacks that are called when
		    * the DOM is ready.
		    * */
		WhenReady: function(callback) {
			if (Simple.DOM.isReady === false) {
				Simple.DOM.callbacks.push(callback);
			}
		}
	},

	GET: {
		data: document.location.search.decodeQueryString(),

		/*
		 * exists() returns Boolean
		 * Input: String
		 * */
		exists: function(index) {
			return (typeof index === 'string' && index in this.data);
		},

		/*
		 * find() returns Mixed
		 * Input: String
		 * */
		find: function(index) {
			if (this.exists(index)) {
				return this.data[index];
			}
		}
	}
};

Simple.Cookie.DoUpdateData();

if (typeof document.addEventListener !== 'undefined') {
	document.addEventListener('DOMContentLoaded', Simple.DOM.OnDOMContentLoaded, false);
	window.addEventListener('load', Simple.DOM.OnReady, false);
} else if (typeof document.attachEvent !== 'undefined') {
	document.attachEvent('onreadystatechange', Simple.DOM.OnDOMContentLoaded);
	window.attachEvent('onload', Simple.DOM.OnReady, false);
} else {
	window.onload = Simple.DOM.OnReady;
}<commit_msg>Adjusted functionality of Simple.DOM.WhenReady() to allow callbacks to be added after the DOM has already loaded<commit_after>/*
 * SimpleJS v0.0.1
 * https://github.com/TylerOBrien/SimpleJS
 *
 * Copyright (c) 2012 Tyler O'Brien
 *
 * 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.
 * */

/*
 * AJAX fallback for IE6.
 * Might not work for IE5 and earlier.
 * */
if (typeof XMLHttpRequest === 'undefined') {
	var XMLHttpRequest = function() {
		return new ActiveXObject('Microsoft.XMLHTTP');
	};
	XMLHttpRequest.prototype.isActiveX = true;
} else {
	XMLHttpRequest.prototype.isActiveX = false;
}

/*
 * send_s() returns Nothing
 * Input: Object
    * A "safe" version of XMLHttpRequest.send().
    * Is compatible with both ActiveX-based AJAX and otherwise.
    * */
XMLHttpRequest.prototype.send_s = function(args) {
	if (typeof args === 'undefined' || args === null) {
		if (this.isActiveX) this.send();
		else this.send(null);
	} else if ('method' in args && 'queryString' in args && args.method === 'POST') {
		this.send(args.queryString);
	} else {
		this.send_s();
	}
}

/*
 * decodeQueryString() returns Object
 * Input: Nothing
    * Converts the string to an Object that represents a query string.
    * Examples of valid formats:
       * ?id=42&email=foo@bar.com&type=helloworld
       * &id=42&foo&name=John+Doe
       * foo&bar
    * */
String.prototype.decodeQueryString = function() {
	var buffer;
	var queryString = this.replace('+', ' ');
	var regex = /[?&]?([^&=]+)=?([^&]+)?/g;
	var result = {};

	while (buffer = regex.exec(queryString)) {
		result[decodeURIComponent(buffer[1])] = decodeURIComponent(buffer[2]);
	}

	return result;
};

var Simple = {
	AJAX: function(args) {
		var ajaxRequest = new Simple.AJAXRequest(args);

		ajaxRequest.http.open(ajaxRequest.method, ajaxRequest.urlToOpen, true);
		ajaxRequest.http.setRequestHeader('Content-type', ajaxRequest.contentType+'; charset='+ajaxRequest.charset);

		if (ajaxRequest.method === 'POST') {
			ajaxRequest.http.setRequestHeader('Content-length', ajaxRequest.queryString.length);
			ajaxRequest.http.setRequestHeader('Connection', 'close');
		}

		ajaxRequest.http.onreadystatechange = function(){
			switch (ajaxRequest.http.readyState) {
				case 1:
					ajaxRequest.timeBegin = new Date().getTime();
					Simple.AJAXHandler.CallIfExists(ajaxRequest.onConnect);
				break;
				case 2:
					Simple.AJAXHandler.CallIfExists(ajaxRequest.onRequest);
				break;
				case 3:
					Simple.AJAXHandler.CallIfExists(ajaxRequest.onProcess);
				break;
				case 4:
					if (typeof ajaxRequest.timeout !== 'undefined') {
						clearTimeout(ajaxRequest.timeout);
					}

					ajaxRequest.timeEnd = new Date().getTime();
					ajaxRequest.timeDifference = (ajaxRequest.timeEnd - ajaxRequest.timeBegin);

					switch (ajaxRequest.http.status) {
						case 200:
							Simple.AJAXHandler.CallIfExists(ajaxRequest.onSuccess, ajaxRequest.http.responseText, ajaxRequest.timeDifference);
						break;
						case 404:
							Simple.AJAXHandler.CallIfExists(ajaxRequest.onNotFound, ajaxRequest.http.responseText, ajaxRequest.timeDifference);
						default:
							Simple.AJAXHandler.CallIfExists(ajaxRequest.onError, ajaxRequest.http.status, ajaxRequest.timeDifference);
						break;
					}
				break;
			}
		};

		/*
		 * Add a new timeout if one is given.
		 * The time is assumed to be milliseconds.
		 * */
		if ('timeout' in args && args['timeout'] === true) {
			ajaxRequest.timeout = setTimeout(function() {
				ajaxRequest.http.abort();
				Simple.AJAXHandler.CallIfExists(ajaxRequest.onTimeout);
			}, args['timeout']);
		}

		ajaxRequest.http.send_s(ajaxRequest);
	},

	/*
	 * AJAXHandler
	 * This object contains boilerplate functions that help organise the code of Simple AJAX.
	 * These probably won't need to be used outside of the AjaxRequest constructor function.
	 * Note:
		* These functions are also where the default values are assigned.
	 * */
	AJAXHandler: {
		/*
		 * CallIfExists() returns Nothing
		 * Input: Function, Mixed, Mixed
			* Takes a callback, and up to two optional parameters.
			* Depending on the number of parameters given will make one of three different calls.
			* */
		CallIfExists: function(callback, param1, param2) {
			if (typeof callback === 'function') {
				if (typeof param2 !== 'undefined') callback(param1, param2);
				else if (typeof param1 !== 'undefined') callback(param1);
				else callback();
			}
		},

		/*
		 * GetCarset() returns String
		 * Input: String
		 * */
		GetCharset: function(charset) {
			return (typeof charset === 'string') ? charset : 'utf-8';
		},

		/*
		 * GetContentType() returns String
		 * Input: String
		 */
		GetContentType: function(contentType) {
			return (typeof contentType === 'string') ? contentType : 'application/x-www-form-urlencoded';
		},

		/*
		 * GetMethod() returns String
		 * Input: String
		 */
		GetMethod: function(method) {
			return (typeof method === 'string') ? method : 'GET';
		},

		/*
		 * GetQueryString() returns String
		 * Input: Object
		 * Takes an object of (key=>value) pairs and converts them to a query string.
		 * For example:
			* The object {a:1,b:2,c:3} would become "a=1&b=2&c=3".
			* Note that the question mark is not appended to the beginning.
		 * */
		GetQueryString: function(data) {
			var output = '';

			if (typeof data !== 'undefined') {
				var output = '';

				for (var key in data) {
					output = (output + key +'='+ data[key] + '&');
				}

				// Trim off the extra ampersand.
				output = output.substring(0, output.length-1);
			}

			return output;
		},

		/*
		 * GetUrl() returns String
		 * Input: String
		 */
		GetUrl: function(url) {
			return (typeof url === 'string') ? url : '/';
		},

		/*
		 * GetUrlToOpen() returns String
		 * Input: String, String, String
			* Returns the value that will be passed to the XMLHttpRequest.open() function.
			* If the method is a GET it will be the entire URL, as well as the query string.
			* If the method is a POST then it will only be the query string.
			* */
		GetUrlToOpen: function(url, queryString, method) {
			return (method === 'POST') ? url : (url + '?' + queryString);
		}
	},

	AJAXRequest: function(args) {
		this.charset = Simple.AJAXHandler.GetCharset(args['charset']);
		this.contentType = Simple.AJAXHandler.GetContentType(args['contentType']);
		this.http = new XMLHttpRequest();
		this.method = Simple.AJAXHandler.GetMethod(args['method']);
		this.onConnect = args['onConnect'];
		this.onError = args['onError'];
		this.onNotFound = args['onNotFound'];
		this.onProcess = args['onProcess'];
		this.onRequest = args['onRequest'];
		this.onSuccess = args['onSuccess'];
		this.onTimeout = args['onTimeout'];
		this.queryString = Simple.AJAXHandler.GetQueryString(args['data']);
		this.timeBegin = 0;
		this.timeDifference = 0;
		this.timeEnd = 0;
		this.timeout = null;
		this.url = Simple.AJAXHandler.GetUrl(args['url']);
		this.urlToOpen = Simple.AJAXHandler.GetUrlToOpen(this.url, this.queryString, this.method);
	},

	Cookie: {
		data: {},

		DoUpdateData: function() {
			this.data = {};

			var arr = document.cookie.split('; ');
			var buffer = null;
			var cookie = null;
			var regex = /([^=]+)=(.*)/;

			Simple.Each(arr, function(){
				cookie = regex.exec(this);
				Simple.Cookie.data[escape(cookie[1])] = escape(cookie[2]);
			});
		},

		/*
		 * Get() returns Mixed
		 * Input: String
		 * */
		Get: function(name) {
			if (this.data === null) {
				this.DoUpdateData();
			}
			return Simple.Cookie.data[name];
		},

		/*
		 * Set() returns Nothing
		 * Input: String, String, String(Optional)
		 * */
		Set: function(name, value, expiration) {
			document.cookie = (name+'='+value+';') + (expiration ? ' expires=0;' : '');
			this.DoUpdateData();
		}
	},

	/*
	 * Each() returns Nothing
	 * Input: Array|Object, Function
	    *
	    * */
	Each: function (haystack, callback) {
		if (typeof haystack !== 'undefined' && haystack !== null) {
			var iterator = {
				i: null,
				parent: haystack,
				value: null
			};
			if (haystack.forEach !== undefined) {
				var end = haystack.length;
				for (var i = 0; i < end; i++) {
					iterator.value = haystack[i];
					if (callback.call(iterator.value, iterator) === false) {
						break;
					}
				}
			} else {
				for (iterator.i in haystack) {
					iterator.value = haystack[iterator.i];
					if (callback.call(iterator.value, iterator) === false) {
						break;
					}
				}
			}
		}
	},

	/*
	 * Equals() returns Boolean
	 * Input: Mixed, Mixed
	    * Compares each element of both passed objects, checking for strict equality.
	    * */
	Equals: function(first, second) {
		var result = true;

		Simple.Each(first, function(itr) {
			if (itr.value !== second[itr.index]) {
				return result = false;
			}
		});

		return result;
	},

	/*
	 * Exists() returns Mixed
	 * Input: Mixed, Mixed, Boolean
	    *
	    * */
	Exists: function(value, override, doReturnBoolean) {
		var output;

		if (typeof value !== 'undefined') {
			output = value;
		} else if (typeof doReturnBoolean !== 'undefined' && doReturnBoolean === true) {
			output = false;
		} else {
			output = override;
		}

		return output;
	},

	DOM: {
		callbacks: [], // The array of each callback function to be called when the DOM is ready.
		isReady: false, // This boolean is used to ensure that DOM.OnReady is only called once.

		/*
		 * OnDOMContentLoaded() returns Nothing
		 * Input: Nothing
		    * The function called by the event listeners.
		    * Because of the legacy event listener this may be called twice.
		    * */
		OnDOMContentLoaded: function() {
			if (typeof document.addEventListener !== 'undefined') {
				document.removeEventListener('DOMContentLoaded', Simple.DOM.OnDOMContentLoaded, false);
				Simple.DOM.OnReady();
			} else if (typeof document.attachEvent !== 'undefined' && document.readyState === 'complete' && document.body !== null) {
				document.detachEvent('onreadystatechange', Simple.DOM.OnDOMContentLoaded);
				Simple.DOM.OnReady();
			}
		},

		/*
		 * OnReady() returns Nothing
		 * Input: Nothing
		    * The function called when the DOM has finished loading/is ready.
		    * Uses a boolean to prevent multiple calls because it may be called twice by
		    * the event listener and legacy event listener.
		    * */
		OnReady: function() {
			if (Simple.DOM.isReady === false) {
				if (Simple.DOM.callbacks.length > 0) {
					Simple.Each(Simple.DOM.callbacks, function(){
						this.call(null);
					});
				}
				Simple.DOM.isReady = true;
			}
		},

		/*
		 * WhenReady() returns Nothing
		 * Input: Function
		    * Adds the passed callback to the array of callbacks that are called when
		    * the DOM is ready.
		    * */
		WhenReady: function(callback) {
			if (Simple.DOM.isReady === false) {
				Simple.DOM.callbacks.push(callback);
			} else {
				callback();
			}
		}
	},

	GET: {
		data: document.location.search.decodeQueryString(),

		/*
		 * exists() returns Boolean
		 * Input: String
		 * */
		exists: function(index) {
			return (typeof index === 'string' && index in this.data);
		},

		/*
		 * find() returns Mixed
		 * Input: String
		 * */
		find: function(index) {
			if (this.exists(index)) {
				return this.data[index];
			}
		}
	}
};

Simple.Cookie.DoUpdateData();

if (typeof document.addEventListener !== 'undefined') {
	document.addEventListener('DOMContentLoaded', Simple.DOM.OnDOMContentLoaded, false);
	window.addEventListener('load', Simple.DOM.OnReady, false);
} else if (typeof document.attachEvent !== 'undefined') {
	document.attachEvent('onreadystatechange', Simple.DOM.OnDOMContentLoaded);
	window.attachEvent('onload', Simple.DOM.OnReady, false);
} else {
	window.onload = Simple.DOM.OnReady;
}<|endoftext|>


<commit_before><commit_msg>fix tests<commit_after><|endoftext|>


<commit_before>'use strict';

import dom from 'metal-dom';
import Alert from '../src/Alert';

describe('Alert', function() {
	var component;

	afterEach(function() {
		component.dispose();
	});

	it('should show alert and fire transitionend', function(done) {
		component = new Alert().render();
		assert.ok(!component.visible);
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.visible);
			component.dispose();
			done();
		});
		component.visible = true;
	});

	it('should hide alert and fire transitionend', function(done) {
		component = new Alert({
			visible: true
		}).render();
		assert.ok(component.visible);
		dom.once(component.element, 'transitionend', function() {
			assert.ok(!component.visible);
			component.dispose();
			done();
		});
		component.visible = false;
	});

	it('should toggle alert and fire transitionend', function(done) {
		component = new Alert({
			visible: true
		}).render();
		assert.ok(component.visible);
		dom.once(component.element, 'transitionend', function() {
			assert.ok(!component.visible);
			dom.once(component.element, 'transitionend', function() {
				component.dispose();
				done();
			});
			component.toggle();
		});
		component.toggle();
	});

	it('should close alert, fire transitionend and dispose itself', function(done) {
		component = new Alert({
			visible: true
		}).render();
		component.close();
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.isDisposed());
			done();
		});
	});

	it('should hide alert and fire transitionend from close element', function(done) {
		component = new Alert({
			visible: true
		}).render();
		dom.triggerEvent(component.element.querySelector('.close'), 'click');
		dom.once(component.element, 'transitionend', function() {
			assert.ok(!component.visible);
			done();
		});
	});

	it('should show alert via `show` method', function() {
		component = new Alert().render();
		component.show();
		assert.ok(component.visible);
	});

	it('should alert be not dismissible', function() {
		component = new Alert({
			visible: true,
			dismissible: false
		}).render();
		assert.ok(!dom.hasClass(component.element, 'alert-dismissible'));
		assert.ok(!component.element.querySelector('.close'));
	});

	it('should decorate', function() {
		var config = {
			element: '#alert',
			elementClasses: 'alert-success fade',
			id: 'alert',
			body: 'body',
			spinner: true,
			spinnerClasses: 'my-spinner',
			dismissible: true
		};
		IncrementalDOM.patch(document.body, () => Alert.TEMPLATE(config));

		var markupFromDom = document.getElementById('alert').outerHTML;
		component = new Alert(config).decorate();

		assert.strictEqual(component.element.outerHTML, markupFromDom);
	});

	it('should close alert when click outside', function(done) {
		component = new Alert({
			visible: true
		}).render();

		assert.ok(component.visible);
		dom.triggerEvent(component.element, 'click');
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.visible);
			dom.triggerEvent(document, 'click');
			dom.once(component.element, 'transitionend', function() {
				assert.ok(!component.visible);
				done();
			});
		});
	});

	it('should not close alert when click on the element', function(done) {
		component = new Alert({
			visible: true
		}).render();

		assert.ok(component.visible);
		dom.triggerEvent(component.element, 'click');
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.visible);
			dom.triggerEvent(component.element, 'click');
			assert.ok(component.visible);
			done();
		});
	});

	it('should hide alert after delay', function(done) {
		component = new Alert({
			hideDelay: 0
		}).render();

		assert.ok(!component.visible);
		component.visible = true;
		dom.once(component.element, 'transitionend', function() {
			dom.once(component.element, 'transitionend', function() {
				setTimeout(function() {
					assert.ok(!component.visible);
					done();
				}, 100);
			});
		});
	});

	it('should update spinner as done', function(done) {
		component = new Alert({
			spinner: true,
			spinnerDone: false
		}).render();
		assert.ok(!dom.hasClass(component.element.querySelector('.alert-spinner'), 'alert-spinner-done'));
		component.once('stateChanged', () => {
			assert.ok(dom.hasClass(component.element.querySelector('.alert-spinner'), 'alert-spinner-done'));
			component.once('stateChanged', () => {
				assert.ok(!dom.hasClass(component.element.querySelector('.alert-spinner'), 'alert-spinner-done'));
				done();
			});
			component.spinnerDone = false;
		});
		component.spinnerDone = true;
	});
});
<commit_msg>Stops dirtying the body on tests<commit_after>'use strict';

import dom from 'metal-dom';
import Alert from '../src/Alert';

describe('Alert', function() {
	var component;

	afterEach(function() {
		component.dispose();
	});

	it('should show alert and fire transitionend', function(done) {
		component = new Alert().render();
		assert.ok(!component.visible);
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.visible);
			component.dispose();
			done();
		});
		component.visible = true;
	});

	it('should hide alert and fire transitionend', function(done) {
		component = new Alert({
			visible: true
		}).render();
		assert.ok(component.visible);
		dom.once(component.element, 'transitionend', function() {
			assert.ok(!component.visible);
			component.dispose();
			done();
		});
		component.visible = false;
	});

	it('should toggle alert and fire transitionend', function(done) {
		component = new Alert({
			visible: true
		}).render();
		assert.ok(component.visible);
		dom.once(component.element, 'transitionend', function() {
			assert.ok(!component.visible);
			dom.once(component.element, 'transitionend', function() {
				component.dispose();
				done();
			});
			component.toggle();
		});
		component.toggle();
	});

	it('should close alert, fire transitionend and dispose itself', function(done) {
		component = new Alert({
			visible: true
		}).render();
		component.close();
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.isDisposed());
			done();
		});
	});

	it('should hide alert and fire transitionend from close element', function(done) {
		component = new Alert({
			visible: true
		}).render();
		dom.triggerEvent(component.element.querySelector('.close'), 'click');
		dom.once(component.element, 'transitionend', function() {
			assert.ok(!component.visible);
			done();
		});
	});

	it('should show alert via `show` method', function() {
		component = new Alert().render();
		component.show();
		assert.ok(component.visible);
	});

	it('should alert be not dismissible', function() {
		component = new Alert({
			visible: true,
			dismissible: false
		}).render();
		assert.ok(!dom.hasClass(component.element, 'alert-dismissible'));
		assert.ok(!component.element.querySelector('.close'));
	});

	it('should decorate', function() {
		var config = {
			element: '#alert',
			elementClasses: 'alert-success fade',
			id: 'alert',
			body: 'body',
			spinner: true,
			spinnerClasses: 'my-spinner',
			dismissible: true
		};
		var element = document.createElement('div');
		IncrementalDOM.patch(element, () => Alert.TEMPLATE(config));

		var markupFromDom = element.querySelector('#alert').outerHTML;
		component = new Alert(config).decorate();

		assert.strictEqual(component.element.outerHTML, markupFromDom);
	});

	it('should close alert when click outside', function(done) {
		component = new Alert({
			visible: true
		}).render();

		assert.ok(component.visible);
		dom.triggerEvent(component.element, 'click');
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.visible);
			dom.triggerEvent(document, 'click');
			dom.once(component.element, 'transitionend', function() {
				assert.ok(!component.visible);
				done();
			});
		});
	});

	it('should not close alert when click on the element', function(done) {
		component = new Alert({
			visible: true
		}).render();

		assert.ok(component.visible);
		dom.triggerEvent(component.element, 'click');
		dom.once(component.element, 'transitionend', function() {
			assert.ok(component.visible);
			dom.triggerEvent(component.element, 'click');
			assert.ok(component.visible);
			done();
		});
	});

	it('should hide alert after delay', function(done) {
		component = new Alert({
			hideDelay: 0
		}).render();

		assert.ok(!component.visible);
		component.visible = true;
		dom.once(component.element, 'transitionend', function() {
			dom.once(component.element, 'transitionend', function() {
				setTimeout(function() {
					assert.ok(!component.visible);
					done();
				}, 100);
			});
		});
	});

	it('should update spinner as done', function(done) {
		component = new Alert({
			spinner: true,
			spinnerDone: false
		}).render();
		assert.ok(!dom.hasClass(component.element.querySelector('.alert-spinner'), 'alert-spinner-done'));
		component.once('stateChanged', () => {
			assert.ok(dom.hasClass(component.element.querySelector('.alert-spinner'), 'alert-spinner-done'));
			component.once('stateChanged', () => {
				assert.ok(!dom.hasClass(component.element.querySelector('.alert-spinner'), 'alert-spinner-done'));
				done();
			});
			component.spinnerDone = false;
		});
		component.spinnerDone = true;
	});
});
<|endoftext|>


<commit_before>/*jshint node: true, mocha:true*/
/**
 * @author pmeijer / https://github.com/pmeijer
 */

var testFixture = require('../../../_globals.js');

describe('ExecutorServer', function () {
    'use strict';

    var gmeConfig,
        agent = testFixture.superagent.agent(),
        should = testFixture.should,
        expect = testFixture.expect,
        Q = testFixture.Q,
        server;

    beforeEach(function (done) {
        Q.allDone([
            Q.ninvoke(testFixture, 'rimraf', './test-tmp/executor'),
            Q.ninvoke(testFixture, 'rimraf', './test-tmp/executor-tmp')
        ])
            .then(function () {
                gmeConfig = testFixture.getGmeConfig();
            })
            .nodeify(done);
    });

    afterEach(function (done) {
        server.stop(function (err) {
            setTimeout(function () {
                done(err);
            }, 300); // FIXME: This is really ugly and bad
        });
    });

    it('should return 200 at rest/executor/worker/ with enableExecutor=true', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/worker/').end(function (err, res) {
                should.equal(res.status, 200, err);
                done();
            });
        });
    });

    it('should return 404 at rest/executor/worker/ with enableExecutor=false', function (done) {
        gmeConfig.executor.enable = false;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/worker/').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 200 GET rest/executor?status=SUCCESS', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor?status=SUCCESS').end(function (err, res) {
                should.equal(res.status, 200, err);
                expect(res.body).to.deep.equal({});
                done();
            });
        });
    });

    it('should return 405 GET rest/executor/cancel', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/cancel').end(function (err, res) {
                should.equal(res.status, 405, err);
                done();
            });
        });
    });

    it('should return 500 POST rest/executor/cancel', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/cancel').end(function (err, res) {
                should.equal(res.status, 500, err);
                done();
            });
        });
    });

    it('should return 500 POST rest/executor/cancel/some_hash', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/cancel/some_hash').end(function (err, res) {
                should.equal(res.status, 500, err);
                done();
            });
        });
    });

    it('should return 405 POST rest/executor/info', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/info').end(function (err, res) {
                should.equal(res.status, 405, err);
                done();
            });
        });
    });

    it('should return 500 GET rest/executor/info/', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/info/').end(function (err, res) {
                should.equal(res.status, 500, err);
                done();
            });
        });
    });

    it('should return 404 GET rest/executor/info/does_not_exist', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/info/does_not_exist').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 GET rest/executor/unknown_command', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/unknown_command').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 405 PUT rest/executor/worker', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.put(serverBaseUrl + '/rest/executor/worker').end(function (err, res) {
                should.equal(res.status, 405, err);
                done();
            });
        });
    });

    it('should return 405 PUT rest/executor/update', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.put(serverBaseUrl + '/rest/executor/update').end(function (err, res) {
                should.equal(res.status, 405, err);
                done();
            });
        });
    });

    it('should return 404 POST rest/executor/update/does_not_exist', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/update/does_not_exist').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 405 PUT rest/executor/create', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.put(serverBaseUrl + '/rest/executor/create').end(function (err, res) {
                should.equal(res.status, 405, err);
                done();
            });
        });
    });

    it('should return 404 POST rest/executor/create', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/create').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 200 POST rest/executor/create/new_element', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/create/new_element').end(function (err, res) {
                should.equal(res.status, 200, err);
                done();
            });
        });
    });
});<commit_msg>ExecutorServer: change some status codes from 405/500 to 404.<commit_after>/*jshint node: true, mocha:true*/
/**
 * @author pmeijer / https://github.com/pmeijer
 */

var testFixture = require('../../../_globals.js');

describe('ExecutorServer', function () {
    'use strict';

    var gmeConfig,
        agent = testFixture.superagent.agent(),
        should = testFixture.should,
        expect = testFixture.expect,
        Q = testFixture.Q,
        server;

    beforeEach(function (done) {
        Q.allDone([
            Q.ninvoke(testFixture, 'rimraf', './test-tmp/executor'),
            Q.ninvoke(testFixture, 'rimraf', './test-tmp/executor-tmp')
        ])
            .then(function () {
                gmeConfig = testFixture.getGmeConfig();
            })
            .nodeify(done);
    });

    afterEach(function (done) {
        server.stop(function (err) {
            setTimeout(function () {
                done(err);
            }, 300); // FIXME: This is really ugly and bad
        });
    });

    it('should return 200 at rest/executor/worker/ with enableExecutor=true', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/worker/').end(function (err, res) {
                should.equal(res.status, 200, err);
                done();
            });
        });
    });

    it('should return 404 at rest/executor/worker/ with enableExecutor=false', function (done) {
        gmeConfig.executor.enable = false;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/worker/').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 200 GET rest/executor?status=SUCCESS', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor?status=SUCCESS').end(function (err, res) {
                should.equal(res.status, 200, err);
                expect(res.body).to.deep.equal({});
                done();
            });
        });
    });

    it('should return 404 GET rest/executor/cancel', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/cancel').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 POST rest/executor/cancel', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/cancel').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 500 POST rest/executor/cancel/some_hash', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/cancel/some_hash').end(function (err, res) {
                should.equal(res.status, 500, err);
                done();
            });
        });
    });

    it('should return 404 POST rest/executor/info', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/info').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 GET rest/executor/info/', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/info/').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 GET rest/executor/info/does_not_exist', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/info/does_not_exist').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 GET rest/executor/unknown_command', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.get(serverBaseUrl + '/rest/executor/unknown_command').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 PUT rest/executor/worker', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.put(serverBaseUrl + '/rest/executor/worker').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 PUT rest/executor/update', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.put(serverBaseUrl + '/rest/executor/update').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 POST rest/executor/update/does_not_exist', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/update/does_not_exist').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 PUT rest/executor/create', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.put(serverBaseUrl + '/rest/executor/create').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 404 POST rest/executor/create', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/create').end(function (err, res) {
                should.equal(res.status, 404, err);
                done();
            });
        });
    });

    it('should return 200 POST rest/executor/create/new_element', function (done) {
        gmeConfig.executor.enable = true;
        server = testFixture.WebGME.standaloneServer(gmeConfig);
        server.start(function () {
            var serverBaseUrl = server.getUrl();
            agent.post(serverBaseUrl + '/rest/executor/create/new_element').end(function (err, res) {
                should.equal(res.status, 200, err);
                done();
            });
        });
    });
});<|endoftext|>


<commit_before>/**
 *  entry point for table
 */

$(function() {

  var Table = cdb.core.View.extend({

    el: document.body,

    events: {
      'keypress': 'keyPress',
      'keyup': 'keyUp'
    },

    initialize: function(options) {
      this.table = null;
      this.selectedMenu = null; // enable this
      this.workViewActive = 'table';
                                      // for oppening a menu in the startup
      // Get user layers as well
      this.options.user_data.get_layers = true;

      this.user = new cdb.admin.User(this.options.user_data);
      cdb.config.set('user', this.user);

      this._initModels();
      this._initViews();
      this._createLoader();

      cdb.admin.hotkeys.enable();
      this.keyBind();

    },

    /**
    * Bind the keystrokes associated with menu actions
    * alt + <- : show right menu
    * alt + -> : hide right menu
    * alt + c : toggle carto
    * alt + s : toggle sql
    * @method keyBind
    */
    keyBind: function() {
      var self = this;
      cdb.god.bind('hotkey:d', function(e) {
        self.menu.isOpen
          ? self.menu.hide()
          : self.menu.show('sql_mod');
      });
      cdb.god.bind('hotkey:s', function(e) {
        self.menu.show('sql_mod');
      })
      cdb.god.bind('hotkey:c', function(e) {
        self.menu.show('style_mod');
      })
    },

    _initModels: function() {
      var self = this;
      this.vis = new cdb.admin.Visualization(this.options.vis_data);
        // when the user changes slides the visualization is changed
        // but we want to keep the master one for tasks that require to use it
      this.master_vis = new cdb.admin.Visualization(_.omit(this.options.vis_data, 'children'));

      this.vis.setMaster(this.master_vis);

      // if slides are available enable first one to fetch the map
      // if not use the master map
      if (this.vis.slides.length === 0) {
        this.vis.map.set(this.vis.map.parse(this.options.map_data));
      } else {
        this.vis.activeSlide(0);
      }

      this.map = this.vis.map;
      this.vis.enableOverlays();

      var layers = this.options.basemaps;

      this.baseLayers = this.user.layers;
      this.baseLayers.each(function(m) {
        m.set('category', 'Yours');
      })

      _(layers).each(function(catLayers, cat) {
        _(catLayers).map(function(m) {
          self.baseLayers.add(new cdb.admin.TileLayer({
            name:        m.name,
            className:   "default " + m.className,
            base_type:   m.className,
            urlTemplate: m.url,
            read_only:   true,
            minZoom:     m.minZoom,
            maxZoom:     m.maxZoom,
            attribution: m.attribution,
            subdomains: m.subdomains,
            category: cat
          }));
        });
      });
    },

    _resetModel: function(_id) {
      this.vis = new cdb.admin.Visualization({ id: _id });
      this.vis.fetch();
    },

    _initViews: function() {
      this.globalError = new cdb.admin.GlobalError({
        el: $('.globalerror')
      });
      this.globalError.listenGlobal();
      this.addView(this.globalError);

      // ***  Locked visualization (table or visualization type)?
      if (this.vis.get('locked')) {
        var locked_dialog = new cdb.admin.LockVisualizationDialog({
          user:           this.user,
          model:          this.vis,
          cancelEnabled:  false
        });

        locked_dialog
          .appendToBody()
          .open({ center: true });

        this.addView(locked_dialog);
      }

      // ***  tabs
      this.tabs = new cdb.admin.Tabs({
        el: this.$('nav'),
        slash: true
      });
      this.addView(this.tabs);

      // *** work pane (table and map)
      this.workView = new cdb.ui.common.TabPane({
        el: this.$('.panes')
      });

      this.addView(this.workView);

      // *** right menu
      // We need to provide the master/parent vis to allow creating a new visualization
      // and the regular vis to work with the layers
      this.menu = new cdb.admin.LayersPanel({
        vis: this.vis,
        master_vis: this.master_vis,
        user: this.user,
        globalError: this.globalError
      });

      this.$el.append(this.menu.render().el);
      this.menu.hide();
      this.addView(this.menu);

      this.menu.bind('switch', function(layerView) {
        this.setTable(layerView.table, layerView.sqlView);
        if(!this.tableTab) {
          this._initTableMap();
          this.table.trigger('change', this.table);
        }
        this.backgroundTab.setActiveLayer(layerView);
        this.tableTab.setActiveLayer(layerView);
        this.mapTab.setActiveLayer(layerView);
        this.header.setActiveLayer(layerView);
      }, this);

      // Set watching notifier if needed
      if (!this.vis.isVisualization()) {
        this._setWatchingNotifier();
      }

      // global click
      enableClickOut(this.$el);

      // On resize window...
      $(window).bind("resize", this._onResize);

      var importsCollection = new cdb.editor.ImportsCollection(null, {
        user: this.user
      });
      var backgroundImporterModel = new cdb.editor.BackgroundImporterModel({}, {
        collection: importsCollection,
        user: this.user,
        vis: this.vis
      });
      var bgImporterView = new cdb.editor.BackgroundImporterView({
        model: backgroundImporterModel,
        createVis: false,
        items: { fetch: function() {} },
        user: this.user
      });
      this.$el.append(bgImporterView.render().el);
      bgImporterView.enable();
      this.addView(bgImporterView);
    },

    _initTableMap: function() {
      var self = this;

      // Init geocoder
      this.geocoder = new cdb.admin.Geocoding();

      // New visualization header
      this.header = new cdb.admin.Header({
        el: this.$('header'),
        globalError: this.globalError,
        model: this.master_vis,
        visualization: this.vis,
        user: this.user,
        config: this.options.config,
        geocoder: this.geocoder
      });
      this.addView(this.header);

      // Table tab
      this.tableTab = new cdb.admin.TableTab({
        model: this.table,
        user: this.user,
        vis: this.vis,
        sqlView: this.sqlView,
        geocoder: this.geocoder,
        globalError: this.globalError,
        menu: this.menu
      });

      // Map tab
      this.mapTab = new cdb.admin.MapTab({
        model: this.map,
        baseLayers: this.baseLayers,
        vis: this.vis,
        master_vis: this.master_vis,
        geocoder: this.geocoder,
        table: this.table,
        user: this.user,
        menu: this.menu
      });

      // Background tab
      this.backgroundTab = new cdb.admin.BackgroundTab({
        el: this.el,
        model: this.geocoder,
        vis: this.vis,
        table: this.table,
        globalError: this.globalError,
        user: this.user
      });

      // Geocoder result
      var geocoder_result = new cdb.admin.GeocodingResult({
        geocoder: this.geocoder
      });

      this._addVideoPlayer();

      this.addView(geocoder_result);

      this.map.bind('notice', this.globalError.showError, this.globalError);

      this.workView.bind('tabEnabled:map', this.mapTab.enableMap, this.mapTab);
      this.workView.bind('tabEnabled', this.tabs.activate);
      this.mapTab.bind('missingClick', self.menu.hide, self.menu);

      this.workView.addTab('table', this.tableTab.render(), { active: false });
      this.workView.addTab('map', this.mapTab.render(), { active: false });
      this.workView.active(this.workViewActive);
    },

    setTable: function(table, sqlView) {
      var self = this;
      if(this.table) {
        this.table.unbind('notice', null, this.globalError);
        this.table.unbind('change:permission', null, this);
      }

      function setPermissions() {
        // check permissions to set read only
        table.setReadOnly(table.permission.getPermission(self.user) !== cdb.admin.Permission.READ_WRITE);
      }
      table.bind('change:permission', setPermissions, this);
      setPermissions();

      this.table = table;
      this.sqlView = sqlView;
      this.table.bind('notice', this.globalError.showError, this.globalError);
      this.table.bind('change:isSync', this._setSyncInfo, this);
      this._setSyncInfo();
    },

    _addVideoPlayer: function() {

      this.player = new cdb.admin.VideoPlayer();

      if (this.player.hasVideoData()) {
        this.$el.append(this.player.render().$el);
      }

    },

    // Set necessary info if the table is synced
    _setSyncInfo: function() {
      if (this.table && this.table.isSync() && !this.vis.isVisualization()) {
        this.workView.$el.addClass('synced');
      } else {
        this.workView.$el.removeClass('synced');
      }
    },

    _setWatchingNotifier: function() {
      // Create model
      var watchvis_notifier = new cdb.admin.WatchingNotifierModel({}, {
        vis:      this.vis,
        interval: cdb.config.get('watcher_ttl')
      });

      // And then the view
      var watchvis_notifier_view = new cdb.admin.WatchingNotifierView({
        model:  watchvis_notifier,
        user:   this.user
      });

      this.$el.append(watchvis_notifier_view.render().el);
      this.addView(watchvis_notifier_view);
    },

    // Close all dialogs in window resize
    _onResize: function(e) {
      cdb.god.trigger("closeDialogs");
    },

    keyUp: function(e) {},

    keyPress: function(e) {},

    // Big table loader
    _createLoader: function() {
      this.big_loader = new cdb.admin.TableBigLoader();
      this.$el.append(this.big_loader.render().el);
    },

    // Show big loader when changes to visualization
    // or table
    showLoader: function(type) {
      this.big_loader.change(type);
      this.big_loader.open();
    },

    // Hide big loader when visualization
    // or table finishes
    hideLoader: function() {
      this.big_loader.hide();
    },

    activeView: function(name) {
      this.workView.active(name);
      // table or map is active?
      this.menu.setActiveWorkView(name);
      this.workViewActive = name;
    }
  });

  cdb._test = cdb._test || {};
  cdb._test.Table = Table;

  cdb.init(function() {
    cdb.config.set(config);
    cdb.config.set('api_key', user_data.api_key);
    cdb.templates.namespace = 'cartodb/';
    cdb.config.set('url_prefix', user_data.base_url);

    // Store JS errors
    var errors = new cdb.admin.ErrorStats({ user_data: user_data });

    // Main view
    var table = new Table({
      vis_data: vis_data,
      user_data: user_data,
      config: config,
      map_data: map_data,
      basemaps: basemaps || cdb.admin.DEFAULT_BASEMAPS
    });

    // Mixpanel test
    if (window.mixpanel) {
      new cdb.admin.Mixpanel({
        user: user_data,
        token: mixpanel_token
      });
    }

    // expose to debug
    window.table = table;
    window.table_router = new cdb.admin.TableRouter(table);

    Backbone.history.start({
      pushState: true,
      root: cdb.config.prefixUrlPathname() + '/'
    });

    /**
     * @param {Object} opts where keys are:
     *   user: {cdb.admin.User}
     *   addVisLayer: {Function} taking two args: {cdb.admin.Visualization} and {cdb.core.View}
     */
    cdb.god.bind('openAddLayerDialog', function(opts) {
      var model = new cdb.editor.AddLayerModel({}, {
        vis: opts.vis,
        map: opts.map,
        user: opts.user
      });
      var dialog = new cdb.editor.AddLayerView({
        model: model,
        user: opts.user
      });
      dialog.appendToBody();
    });
  });

});
<commit_msg>Fix add layer to not break non-feature enabled users<commit_after>/**
 *  entry point for table
 */

$(function() {

  var Table = cdb.core.View.extend({

    el: document.body,

    events: {
      'keypress': 'keyPress',
      'keyup': 'keyUp'
    },

    initialize: function(options) {
      this.table = null;
      this.selectedMenu = null; // enable this
      this.workViewActive = 'table';
                                      // for oppening a menu in the startup
      // Get user layers as well
      this.options.user_data.get_layers = true;

      this.user = new cdb.admin.User(this.options.user_data);
      cdb.config.set('user', this.user);

      this._initModels();
      this._initViews();
      this._createLoader();

      cdb.admin.hotkeys.enable();
      this.keyBind();

    },

    /**
    * Bind the keystrokes associated with menu actions
    * alt + <- : show right menu
    * alt + -> : hide right menu
    * alt + c : toggle carto
    * alt + s : toggle sql
    * @method keyBind
    */
    keyBind: function() {
      var self = this;
      cdb.god.bind('hotkey:d', function(e) {
        self.menu.isOpen
          ? self.menu.hide()
          : self.menu.show('sql_mod');
      });
      cdb.god.bind('hotkey:s', function(e) {
        self.menu.show('sql_mod');
      })
      cdb.god.bind('hotkey:c', function(e) {
        self.menu.show('style_mod');
      })
    },

    _initModels: function() {
      var self = this;
      this.vis = new cdb.admin.Visualization(this.options.vis_data);
        // when the user changes slides the visualization is changed
        // but we want to keep the master one for tasks that require to use it
      this.master_vis = new cdb.admin.Visualization(_.omit(this.options.vis_data, 'children'));

      this.vis.setMaster(this.master_vis);

      // if slides are available enable first one to fetch the map
      // if not use the master map
      if (this.vis.slides.length === 0) {
        this.vis.map.set(this.vis.map.parse(this.options.map_data));
      } else {
        this.vis.activeSlide(0);
      }

      this.map = this.vis.map;
      this.vis.enableOverlays();

      var layers = this.options.basemaps;

      this.baseLayers = this.user.layers;
      this.baseLayers.each(function(m) {
        m.set('category', 'Yours');
      })

      _(layers).each(function(catLayers, cat) {
        _(catLayers).map(function(m) {
          self.baseLayers.add(new cdb.admin.TileLayer({
            name:        m.name,
            className:   "default " + m.className,
            base_type:   m.className,
            urlTemplate: m.url,
            read_only:   true,
            minZoom:     m.minZoom,
            maxZoom:     m.maxZoom,
            attribution: m.attribution,
            subdomains: m.subdomains,
            category: cat
          }));
        });
      });
    },

    _resetModel: function(_id) {
      this.vis = new cdb.admin.Visualization({ id: _id });
      this.vis.fetch();
    },

    _initViews: function() {
      this.globalError = new cdb.admin.GlobalError({
        el: $('.globalerror')
      });
      this.globalError.listenGlobal();
      this.addView(this.globalError);

      // ***  Locked visualization (table or visualization type)?
      if (this.vis.get('locked')) {
        var locked_dialog = new cdb.admin.LockVisualizationDialog({
          user:           this.user,
          model:          this.vis,
          cancelEnabled:  false
        });

        locked_dialog
          .appendToBody()
          .open({ center: true });

        this.addView(locked_dialog);
      }

      // ***  tabs
      this.tabs = new cdb.admin.Tabs({
        el: this.$('nav'),
        slash: true
      });
      this.addView(this.tabs);

      // *** work pane (table and map)
      this.workView = new cdb.ui.common.TabPane({
        el: this.$('.panes')
      });

      this.addView(this.workView);

      // *** right menu
      // We need to provide the master/parent vis to allow creating a new visualization
      // and the regular vis to work with the layers
      this.menu = new cdb.admin.LayersPanel({
        vis: this.vis,
        master_vis: this.master_vis,
        user: this.user,
        globalError: this.globalError
      });

      this.$el.append(this.menu.render().el);
      this.menu.hide();
      this.addView(this.menu);

      this.menu.bind('switch', function(layerView) {
        this.setTable(layerView.table, layerView.sqlView);
        if(!this.tableTab) {
          this._initTableMap();
          this.table.trigger('change', this.table);
        }
        this.backgroundTab.setActiveLayer(layerView);
        this.tableTab.setActiveLayer(layerView);
        this.mapTab.setActiveLayer(layerView);
        this.header.setActiveLayer(layerView);
      }, this);

      // Set watching notifier if needed
      if (!this.vis.isVisualization()) {
        this._setWatchingNotifier();
      }

      // global click
      enableClickOut(this.$el);

      // On resize window...
      $(window).bind("resize", this._onResize);

      if (this.user.featureEnabled('new_modals')) {
        /**
         * NOTE: Dependencies loaded in editor.js bundle!
         * @param {Object} opts where keys are:
         *   user: {cdb.admin.User}
         *   addVisLayer: {Function} taking two args: {cdb.admin.Visualization} and {cdb.core.View}
         */
        cdb.god.bind('openAddLayerDialog', function(opts) {
          var model = new cdb.editor.AddLayerModel({}, {
            vis: opts.vis,
            map: opts.map,
            user: opts.user
          });
          var dialog = new cdb.editor.AddLayerView({
            model: model,
            user: opts.user
          });
          dialog.appendToBody();
        });

        var importsCollection = new cdb.editor.ImportsCollection(null, {
          user: this.user
        });
        var backgroundImporterModel = new cdb.editor.BackgroundImporterModel({}, {
          collection: importsCollection,
          user: this.user,
          vis: this.vis
        });
        var bgImporterView = new cdb.editor.BackgroundImporterView({
          model: backgroundImporterModel,
          createVis: false,
          items: { fetch: function() {} },
          user: this.user
        });
        this.$el.append(bgImporterView.render().el);
        bgImporterView.enable();
        this.addView(bgImporterView);
      }
    },

    _initTableMap: function() {
      var self = this;

      // Init geocoder
      this.geocoder = new cdb.admin.Geocoding();

      // New visualization header
      this.header = new cdb.admin.Header({
        el: this.$('header'),
        globalError: this.globalError,
        model: this.master_vis,
        visualization: this.vis,
        user: this.user,
        config: this.options.config,
        geocoder: this.geocoder
      });
      this.addView(this.header);

      // Table tab
      this.tableTab = new cdb.admin.TableTab({
        model: this.table,
        user: this.user,
        vis: this.vis,
        sqlView: this.sqlView,
        geocoder: this.geocoder,
        globalError: this.globalError,
        menu: this.menu
      });

      // Map tab
      this.mapTab = new cdb.admin.MapTab({
        model: this.map,
        baseLayers: this.baseLayers,
        vis: this.vis,
        master_vis: this.master_vis,
        geocoder: this.geocoder,
        table: this.table,
        user: this.user,
        menu: this.menu
      });

      // Background tab
      this.backgroundTab = new cdb.admin.BackgroundTab({
        el: this.el,
        model: this.geocoder,
        vis: this.vis,
        table: this.table,
        globalError: this.globalError,
        user: this.user
      });

      // Geocoder result
      var geocoder_result = new cdb.admin.GeocodingResult({
        geocoder: this.geocoder
      });

      this._addVideoPlayer();

      this.addView(geocoder_result);

      this.map.bind('notice', this.globalError.showError, this.globalError);

      this.workView.bind('tabEnabled:map', this.mapTab.enableMap, this.mapTab);
      this.workView.bind('tabEnabled', this.tabs.activate);
      this.mapTab.bind('missingClick', self.menu.hide, self.menu);

      this.workView.addTab('table', this.tableTab.render(), { active: false });
      this.workView.addTab('map', this.mapTab.render(), { active: false });
      this.workView.active(this.workViewActive);
    },

    setTable: function(table, sqlView) {
      var self = this;
      if(this.table) {
        this.table.unbind('notice', null, this.globalError);
        this.table.unbind('change:permission', null, this);
      }

      function setPermissions() {
        // check permissions to set read only
        table.setReadOnly(table.permission.getPermission(self.user) !== cdb.admin.Permission.READ_WRITE);
      }
      table.bind('change:permission', setPermissions, this);
      setPermissions();

      this.table = table;
      this.sqlView = sqlView;
      this.table.bind('notice', this.globalError.showError, this.globalError);
      this.table.bind('change:isSync', this._setSyncInfo, this);
      this._setSyncInfo();
    },

    _addVideoPlayer: function() {

      this.player = new cdb.admin.VideoPlayer();

      if (this.player.hasVideoData()) {
        this.$el.append(this.player.render().$el);
      }

    },

    // Set necessary info if the table is synced
    _setSyncInfo: function() {
      if (this.table && this.table.isSync() && !this.vis.isVisualization()) {
        this.workView.$el.addClass('synced');
      } else {
        this.workView.$el.removeClass('synced');
      }
    },

    _setWatchingNotifier: function() {
      // Create model
      var watchvis_notifier = new cdb.admin.WatchingNotifierModel({}, {
        vis:      this.vis,
        interval: cdb.config.get('watcher_ttl')
      });

      // And then the view
      var watchvis_notifier_view = new cdb.admin.WatchingNotifierView({
        model:  watchvis_notifier,
        user:   this.user
      });

      this.$el.append(watchvis_notifier_view.render().el);
      this.addView(watchvis_notifier_view);
    },

    // Close all dialogs in window resize
    _onResize: function(e) {
      cdb.god.trigger("closeDialogs");
    },

    keyUp: function(e) {},

    keyPress: function(e) {},

    // Big table loader
    _createLoader: function() {
      this.big_loader = new cdb.admin.TableBigLoader();
      this.$el.append(this.big_loader.render().el);
    },

    // Show big loader when changes to visualization
    // or table
    showLoader: function(type) {
      this.big_loader.change(type);
      this.big_loader.open();
    },

    // Hide big loader when visualization
    // or table finishes
    hideLoader: function() {
      this.big_loader.hide();
    },

    activeView: function(name) {
      this.workView.active(name);
      // table or map is active?
      this.menu.setActiveWorkView(name);
      this.workViewActive = name;
    }
  });

  cdb._test = cdb._test || {};
  cdb._test.Table = Table;

  cdb.init(function() {
    cdb.config.set(config);
    cdb.config.set('api_key', user_data.api_key);
    cdb.templates.namespace = 'cartodb/';
    cdb.config.set('url_prefix', user_data.base_url);

    // Store JS errors
    var errors = new cdb.admin.ErrorStats({ user_data: user_data });

    // Main view
    var table = new Table({
      vis_data: vis_data,
      user_data: user_data,
      config: config,
      map_data: map_data,
      basemaps: basemaps || cdb.admin.DEFAULT_BASEMAPS
    });

    // Mixpanel test
    if (window.mixpanel) {
      new cdb.admin.Mixpanel({
        user: user_data,
        token: mixpanel_token
      });
    }

    // expose to debug
    window.table = table;
    window.table_router = new cdb.admin.TableRouter(table);

    Backbone.history.start({
      pushState: true,
      root: cdb.config.prefixUrlPathname() + '/'
    });
  });

});
<|endoftext|>


<commit_before>import Ember from 'ember';
import ENV from '../config/environment';
import BaseAuthenticator from 'ember-simple-auth/authenticators/base';

export default BaseAuthenticator.extend({
    session: Ember.inject.service(),

    csrfToken() {
        if (!document.cookie && document.cookie === '') {
            return null;
        }
        let cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            let cookie = cookies[i].trim();
            if (cookie.substring(0, ENV.csrfCookie.length + 1) === `${ENV.csrfCookie}=`) {
                return decodeURIComponent(cookie.substring(ENV.csrfCookie.length + 1));
            }
        }
    },

    restore() {
        return this.authenticate(false);
    },

    authenticate(redirectToLogin = true) {
        return new Ember.RSVP.Promise((resolve, reject) => {
            this.getUserInfo().then(response => {
                if (!response || !response.token) {
                    if (redirectToLogin) {
                        window.location = `${ENV.apiBaseUrl}/accounts/osf/login/`;
                        return;
                    }
                    reject('not logged in');
                } else {
                    resolve({
                        user: response,
                        csrfToken: this.csrfToken()
                    });
                }
            });
        });
    },

    invalidate() {
        return Ember.$.ajax({
            method: 'POST',
            url: `${ENV.apiBaseUrl}/accounts/logout/`,
            crossDomain: true,
            xhrFields: { withCredentials: true }
        });
    },

    getUserInfo() {
        return Ember.$.ajax({
            url: `${ENV.apiBaseUrl}/api/userinfo`,
            crossDomain: true,
            xhrFields: { withCredentials: true }
        });
    }
});
<commit_msg>Redirect users to the page they logged in from<commit_after>import Ember from 'ember';
import ENV from '../config/environment';
import BaseAuthenticator from 'ember-simple-auth/authenticators/base';

export default BaseAuthenticator.extend({
    session: Ember.inject.service(),

    csrfToken() {
        if (!document.cookie && document.cookie === '') {
            return null;
        }
        let cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            let cookie = cookies[i].trim();
            if (cookie.substring(0, ENV.csrfCookie.length + 1) === `${ENV.csrfCookie}=`) {
                return decodeURIComponent(cookie.substring(ENV.csrfCookie.length + 1));
            }
        }
    },

    restore() {
        return this.authenticate(false);
    },

    authenticate(redirectToLogin = true) {
        return new Ember.RSVP.Promise((resolve, reject) => {
            this.getUserInfo().then(response => {
                if (!response || !response.token) {
                    if (redirectToLogin) {
                        return window.location = `${ENV.apiBaseUrl}/accounts/osf/login/?${Ember.$.param({ next: window.location.pathname + window.location.search })}`;
                    }
                    reject('not logged in');
                } else {
                    resolve({
                        user: response,
                        csrfToken: this.csrfToken()
                    });
                }
            });
        });
    },

    invalidate() {
        return Ember.$.ajax({
            method: 'POST',
            url: `${ENV.apiBaseUrl}/accounts/logout/`,
            crossDomain: true,
            xhrFields: { withCredentials: true }
        });
    },

    getUserInfo() {
        return Ember.$.ajax({
            url: `${ENV.apiBaseUrl}/api/userinfo`,
            crossDomain: true,
            xhrFields: { withCredentials: true }
        });
    }
});
<|endoftext|>


<commit_before>import _ from 'lodash'
import uuid from 'uuid'
import Reflux from 'reflux'

import DashboardChartsStore from 'stores/DashboardChartsStore'

import DashboardActions from 'actions/DashboardActions'
import DashboardPageActions from 'actions/DashboardPageActions'
import DashboardChartsActions from 'actions/DashboardChartsActions'

class Row {
  constructor () {
    this.layout = null
    this.charts = []
  }
}

const DashboardPageStore = Reflux.createStore({

  listenables: DashboardPageActions,

  dashboard: {
    title: '',
    editMode: false,
    rows: []
  },

  charts: {},

  init () {
    this.listenTo(DashboardChartsStore, charts => this.charts = charts)
    this.listenTo(DashboardActions.postDashboard.completed, () => {
      this.dashboard.saving = false
      this.dashboard.editMode = false
      this.trigger(this.dashboard)
    })
  },

  getInitialState: function () {
    return this.dashboard
  },

  // =========================================================================== //
  //                            REGULAR ACTION HANDLERS                          //
  // =========================================================================== //

  onToggleEditMode: function () {
    this.dashboard.editMode = !this.dashboard.editMode
    this.dashboard.rows.forEach(row => {
      row.charts.forEach(chart_uuid => {
        DashboardChartsActions.exitEditMode(chart_uuid)
        DashboardChartsActions.exitSelectTypeMode(chart_uuid)
      })
    })
    this.trigger(this.dashboard)
  },

  onSetDashboardTitle: function (title) {
    this.dashboard.title = title
    this.trigger(this.dashboard)
  },

  onAddRow: function () {
    const row = new Row()
    this.dashboard.rows.push(row)
    this.trigger(this.dashboard)
  },

  onRemoveChart: function (row_index, chart_index) { console.info('DashboardPageStore - onRemoveChart')
    const row = this.dashboard.rows[row_index]
    const uuid_to_remove = row.charts[chart_index]
    row.charts.splice(chart_index, 1)
    DashboardChartsActions.removeChart(uuid_to_remove)
    if (row.layout === 3 || row.layout === 4) {
      this.dashboard.rows[row_index].layout = 2
    } else if (row.layout === 2) {
      this.dashboard.rows[row_index].layout = 1
    } else if (row.layout === 1) {
      this.dashboard.rows.splice(row_index, 1)
    }
    this.trigger(this.dashboard)
  },

  onSelectRowLayout: function (layout) {
    console.info('')
    console.info('------------------------------------------------------------')
    console.info('DashboardPageStore - onSelectRowLayout')
    const row_index = this.dashboard.rows.length - 1
    this.dashboard.rows[row_index].layout = layout
    this._addChartToRow(row_index)
    if (layout === 2) {
      this._addChartToRow(row_index)
    } else if (layout === 3 || layout === 4) {
      this._addChartToRow(row_index)
      this._addChartToRow(row_index)
    }
    console.log('this.dashboard.rows', this.dashboard.rows)
    this.trigger(this.dashboard)
  },

  _addChartToRow: function (row_index) { console.info('DashboardPageStore - _addChartToRow')
    const chart_uuid = uuid.v4()
    this.dashboard.rows[row_index].charts.push(chart_uuid)
    DashboardChartsActions.addChart(chart_uuid)
  },

  onSaveDashboard: function (dashboard_id = null) {
    if (!this.dashboard.title || this.dashboard.title === 'Untitled Dashboard') {
      return window.alert('Please add a Title to your dashboard')
    }
    let allChartsSaved = true
    _.toArray(this.charts).forEach(chart => {
      if (!chart.title || chart.title === 'Untitled Chart') {
        allChartsSaved = false
        return
      }
      DashboardChartsActions.saveChart(chart.uuid)
    })
    if (!allChartsSaved) {
      return window.alert('Please title all of your charts')
    }
    this.dashboard.saving = true
    this.trigger(this.dashboard)
    const query = {
      id: dashboard_id,
      title: this.dashboard.title,
      rows: JSON.stringify(this.dashboard.rows)
    }
    DashboardActions.postDashboard(query)
  },

  // =========================================================================== //
  //                               API CALL HANDLERS                             //
  // =========================================================================== //
  // =============================  Fetch Dashboard  =========================== //
  onFetchDashboard: function (uuid) {
    this.trigger(this.dashboard)
  },
  onFetchDashboardCompleted: function (response) {
    this.dashboard.title = response.title
    response.rows.forEach(row => {
      row.charts.forEach(chart => DashboardChartsActions.fetchChart.completed(chart))
      row.charts = row.charts.map(chart => chart.uuid)
      this.dashboard.rows.push(row)
    })
    this.trigger(this.dashboard)
  },
  onFetchDashboardFailed: function (error) {
    this.setState({ error: error })
  }
})

export default DashboardPageStore
<commit_msg>Remove some console logs<commit_after>import _ from 'lodash'
import uuid from 'uuid'
import Reflux from 'reflux'

import DashboardChartsStore from 'stores/DashboardChartsStore'

import DashboardActions from 'actions/DashboardActions'
import DashboardPageActions from 'actions/DashboardPageActions'
import DashboardChartsActions from 'actions/DashboardChartsActions'

class Row {
  constructor () {
    this.layout = null
    this.charts = []
  }
}

const DashboardPageStore = Reflux.createStore({

  listenables: DashboardPageActions,

  dashboard: {
    title: '',
    editMode: false,
    rows: []
  },

  charts: {},

  init () {
    this.listenTo(DashboardChartsStore, charts => this.charts = charts)
    this.listenTo(DashboardActions.postDashboard.completed, () => {
      this.dashboard.saving = false
      this.dashboard.editMode = false
      this.trigger(this.dashboard)
    })
  },

  getInitialState: function () {
    return this.dashboard
  },

  // =========================================================================== //
  //                            REGULAR ACTION HANDLERS                          //
  // =========================================================================== //

  onToggleEditMode: function () {
    this.dashboard.editMode = !this.dashboard.editMode
    this.dashboard.rows.forEach(row => {
      row.charts.forEach(chart_uuid => {
        DashboardChartsActions.exitEditMode(chart_uuid)
        DashboardChartsActions.exitSelectTypeMode(chart_uuid)
      })
    })
    this.trigger(this.dashboard)
  },

  onSetDashboardTitle: function (title) {
    this.dashboard.title = title
    this.trigger(this.dashboard)
  },

  onAddRow: function () {
    const row = new Row()
    this.dashboard.rows.push(row)
    this.trigger(this.dashboard)
  },

  onRemoveChart: function (row_index, chart_index) {
    const row = this.dashboard.rows[row_index]
    const uuid_to_remove = row.charts[chart_index]
    row.charts.splice(chart_index, 1)
    DashboardChartsActions.removeChart(uuid_to_remove)
    if (row.layout === 3 || row.layout === 4) {
      this.dashboard.rows[row_index].layout = 2
    } else if (row.layout === 2) {
      this.dashboard.rows[row_index].layout = 1
    } else if (row.layout === 1) {
      this.dashboard.rows.splice(row_index, 1)
    }
    this.trigger(this.dashboard)
  },

  onSelectRowLayout: function (layout) {
    const row_index = this.dashboard.rows.length - 1
    this.dashboard.rows[row_index].layout = layout
    this._addChartToRow(row_index)
    if (layout === 2) {
      this._addChartToRow(row_index)
    } else if (layout === 3 || layout === 4) {
      this._addChartToRow(row_index)
      this._addChartToRow(row_index)
    }
    this.trigger(this.dashboard)
  },

  _addChartToRow: function (row_index) {
    const chart_uuid = uuid.v4()
    this.dashboard.rows[row_index].charts.push(chart_uuid)
    DashboardChartsActions.addChart(chart_uuid)
  },

  onSaveDashboard: function (dashboard_id = null) {
    if (!this.dashboard.title || this.dashboard.title === 'Untitled Dashboard') {
      return window.alert('Please add a Title to your dashboard')
    }
    let allChartsSaved = true
    _.toArray(this.charts).forEach(chart => {
      if (!chart.title || chart.title === 'Untitled Chart') {
        allChartsSaved = false
        return
      }
      DashboardChartsActions.saveChart(chart.uuid)
    })
    if (!allChartsSaved) {
      return window.alert('Please title all of your charts')
    }
    this.dashboard.saving = true
    this.trigger(this.dashboard)
    const query = {
      id: dashboard_id,
      title: this.dashboard.title,
      rows: JSON.stringify(this.dashboard.rows)
    }
    DashboardActions.postDashboard(query)
  },

  // =========================================================================== //
  //                               API CALL HANDLERS                             //
  // =========================================================================== //
  // =============================  Fetch Dashboard  =========================== //
  onFetchDashboard: function (uuid) {
    this.trigger(this.dashboard)
  },
  onFetchDashboardCompleted: function (response) {
    this.dashboard.title = response.title
    response.rows.forEach(row => {
      row.charts.forEach(chart => DashboardChartsActions.fetchChart.completed(chart))
      row.charts = row.charts.map(chart => chart.uuid)
      this.dashboard.rows.push(row)
    })
    this.trigger(this.dashboard)
  },
  onFetchDashboardFailed: function (error) {
    this.setState({ error: error })
  }
})

export default DashboardPageStore
<|endoftext|>