<commit_before>define([
	"dojo/_base/connect",
	"dojo/_base/lang",
	"dojo/_base/window",
	"dojo/sniff",
	"dojo/query",
	"dojo/dom-class",
	"dojo/dom-construct",
	"dojo/dom-geometry",
	"dojo/dom-style",
	"dojo/keys",
	"dojo/touch",
	"dojo/on",
	"./register",
	"./FormValueWidget",
	"./themes/load!common,Slider"	// common for duiInline etc., Slider for duiSlider etc.
], function (connect, lang, win, has, query, domClass, domConstruct, domGeometry, domStyle,
		keys, touch, on, register, FormValueWidget) {

	return register("d-slider", [HTMLElement, FormValueWidget], {
		// summary:
		//		A non-templated Slider widget similar to the HTML5 INPUT type=range.

		// min: [const] Number
		//		The first value the slider can be set to.
		min: NaN,

		// max: [const] Number
		//		The last value the slider can be set to.
		max: NaN,

		// step: [const] Number
		//		The delta from 1 value to another.
		//		This causes the slider handle to snap/jump to the closest possible value.
		//		A value of 0 means continuous (as much as allowed by pixel resolution).
		step: 1,

		// baseClass: [const] String
		//		The name of the CSS class of this widget.
		baseClass: "duiSlider",

		// flip: [const] Boolean
		//		Specifies if the slider should change its default: ascending <--> descending.
		flip: false,

		// orientation: [const] String
		//		The slider direction for ascending values.
		//		- "H": horizontal (dependent on default left-to-right or right-to-left direction)
		//		- "V": vertical
		orientation: "H",

		preCreate: function () {
			this._orientationAttrs = {
				"H": { start: "x", size: "w", pageStart: "pageX", clientStart: "clientX",
						progressBarStart: "left", progressBarSize: "width" },
				"V": { start: "y", size: "h", pageStart: "pageY", clientStart: "clientY", progressBarStart: "top",
						progressBarSize: "height" }
			};

			this.addInvalidatingProperties(
				{ value: "invalidateProperty" },
				{ min: "invalidateProperty" },
				{ max: "invalidateProperty" },
				"name",
				"flip",
				"step",
				"orientation"
			);
		},

		refreshProperties: function (props) {
			if (props.value && !this.handleMin && String(this.value).indexOf(",") > 0) {
				this.handleMin = domConstruct.create("div", { role: "slider" }, this.progressBar, "first");
				this.tabStops = "handleMin,focusNode";
			}
			if (props.value || props.min || props.max) {
				// force the value in bounds
				var values = String(this.value).split(/,/g);
				var	minValue = Math.max(Math.min(values[0], values[values.length-1], this.max), this.min),
					maxValue = Math.min(Math.max(values[0], values[values.length-1], this.min), this.max);
				// correct value in case the values were outside min/max
				var correctedValue = values.length === 1 ? String(maxValue) : (minValue + "," + maxValue);
				if (correctedValue !== this.value) {
					this.value = correctedValue;
					this.validateProperties();
				}
			}
			if (props.value) {
				this.valueNode.value = String(this.value);
			}
		},

		refreshRendering: register.before(function (props) {
			var toCSS = function (baseClass, modifier) {
				return baseClass.split(/ /g).map(function (c) {
					return c + modifier;
				}).join(" ");
			};

			if (props.orientation || props.flip) {
				// add V or H suffix to baseClass for styling purposes
				var	horizontal = this.orientation !== "V",
					ltr = horizontal ? this.isLeftToRight() : false,
					flip = !!this.flip;
				// _reversed is complicated since you can have flipped right-to-left and vertical is upside down by default
				this._reversed = !((horizontal && ((ltr && !flip) || (!ltr && flip))) || (!horizontal && flip));
				this._attrs = this._orientationAttrs[this.orientation];
				var baseClass = toCSS(this.className, this.orientation);
				domClass.add(this, baseClass);
				baseClass = this.baseClass + " " + baseClass;
				domClass.add(this, toCSS(baseClass, this._reversed ? "HtL" : "LtH"));
				domClass.add(this.containerNode, toCSS(baseClass, "Bar") + " " + toCSS(baseClass, "RemainingBar"));
				domClass.add(this.progressBar, toCSS(baseClass, "Bar") + " " + toCSS(baseClass, "ProgressBar"));
				domClass.add(this.focusNode, toCSS(baseClass, "Handle") + " " + toCSS(baseClass, "HandleMax"));
				if (this.handleMin) {
					domClass.add(this.handleMin, toCSS(baseClass, "Handle") + " " + toCSS(baseClass, "HandleMin"));
				}
				// pass widget attributes to children
				var self = this;
				this.getChildren().forEach(function (obj) {
					obj.orientation = self.orientation;
					obj.reverse = self._reversed;
				});
			}
			if (props.name) {
				this.valueNode.name = this.name;
			}
			if (props.max) {
				this.focusNode.setAttribute("aria-valuemax", this.max);
			}
			if (props.min) {
				(this.handleMin || this.focusNode).setAttribute("aria-valuemin", this.min);
			}
			if (props.value || props.min || props.max) {
				this._positionHandles();
			}
		}),

		buildRendering: function () {

			// look for child INPUT node under root node
			this.valueNode = query("> INPUT", this)[0];
			if (!this.valueNode) {
				this.valueNode = domConstruct.create("input", { "type": "text", readOnly: true, value: this.value }, this, "last");
			}

			this.containerNode = domConstruct.create("div", {}, this, "last");
			var n = this.firstChild;
			while (n) {
				var next = n.nextSibling;
				if (n !== this.valueNode && n !== this.containerNode) {
					// move all extra markup nodes to the containerNode for relative sizing and placement
					this.containerNode.appendChild(n);
				}
				n = next;
			}
			this.progressBar = domConstruct.create("div", {}, this.containerNode, "last");
			this.focusNode = domConstruct.create("div", { role: "slider" }, this.progressBar, "last");

			// prevent browser scrolling on IE10 (evt.preventDefault() is not enough)
			if (typeof this.style.msTouchAction !== "undefined") {
				this.style.msTouchAction = "none";
			}
		},

		_positionHandles: function () {
			var values = String(this.value).split(/,/g);
			if (values.length === 1) {
				values = [this.min, values[0]];
			} else {
				this.handleMin.setAttribute("aria-valuenow", values[0]);
				this.handleMin.setAttribute("aria-valuemax", values[1]);
			}
			this.focusNode.setAttribute("aria-valuenow", values[1]);
			this.focusNode.setAttribute("aria-valuemin", values[0]);
			var	toPercent = (values[1] - this.min) * 100 / (this.max - this.min),
				toPercentMin = (values[0] - this.min) * 100 / (this.max - this.min),
				s = {};
			s[this._attrs.progressBarSize] = (toPercent - toPercentMin) + "%";
			s[this._attrs.progressBarStart] = (this._reversed ? (100 - toPercent) : toPercentMin) + "%";
			domStyle.set(this.progressBar, s);
		},

		postCreate: function () {
			var	beginDrag = lang.hitch(this,
				function (e) {
					e.preventDefault();
					var	setValue = lang.hitch(this, function (priorityChange) {
							var values = String(this.value).split(/,/g);
							value -= offsetValue;
							// now perform visual slide
							domClass.toggle(this.progressBar, "duiSliderTransition", !!priorityChange);
							this.value =
								values.length === 1
									? String(value)
									: (isMax
										? (values[0] + "," + value)
										: (value + "," + values[1]));
							this.validateProperties();
							this._handleOnChange(this.value, priorityChange);
						}),
						getEventData = lang.hitch(this, function (e) {
							point = isMouse
								? e[this._attrs.pageStart]
								: ((e.touches && e.touches[0])
									? e.touches[0][this._attrs.pageStart]
									: e[this._attrs.clientStart]);
							pixelValue = point - startPixel;
							pixelValue = Math.min(Math.max(pixelValue, 0), maxPixels);
							var discreteValues = this.step ? ((this.max - this.min) / this.step) : maxPixels;
							if (discreteValues <= 1 || discreteValues === Infinity) { discreteValues = maxPixels; }
							var wholeIncrements = Math.round(pixelValue * discreteValues / maxPixels);
							value = (this.max - this.min) * wholeIncrements / discreteValues;
							value = this._reversed ? (this.max - value) : (this.min + value);
						}),
						continueDrag = lang.hitch(this, function (e) {
							e.preventDefault();
							getEventData(e);
							setValue(false);
						}),
						endDrag = lang.hitch(this, function (e) {
							e.preventDefault();
							if (actionHandles) {
								actionHandles.forEach(function (h) { h.remove(); });
							}
							actionHandles = [];
							getEventData(e);
							setValue(true);
							// fire onChange
						}),
						isMouse = e instanceof MouseEvent, // e.type can be MSPointerDown but still be instanceof MouseEvent
						// get the starting position of the content area (dragging region)
						// can't use true since the added docScroll and the returned x are body-zoom incompatibile
						box = domGeometry.position(this.containerNode, false),
						scroll = domGeometry.docScroll(),
						bodyZoom = has("ie") ? 1 : (parseFloat(domStyle.get(win.body(), "zoom")) || 1),
						nodeZoom = has("ie") ? 1 : (parseFloat(domStyle.get(node, "zoom")) || 1),
						root = win.doc.documentElement,
						actionHandles;
					if (this.disabled || this.readOnly) { return; }
					// fix scroll.y in IE10 for incorrect pageYOffset
					// https://connect.microsoft.com/IE/feedback/details/768781/ie10-window-pageyoffset-incorrect-value-when-page-zoomed-breaks-jquery-etc
					scroll.y = Math.min(scroll.y, this.containerNode.ownerDocument.documentElement.scrollTop || scroll.y);
					var startPixel = box[this._attrs.start] * nodeZoom * bodyZoom + scroll[this._attrs.start];
					var maxPixels = box[this._attrs.size] * nodeZoom * bodyZoom;
					var offsetValue = 0;
					getEventData(e);
					var values = String(this.value).split(/,/g);
					var isMax = (values.length === 1) || (Math.abs(value - values[0]) > Math.abs(value - values[1]));
					if (e.target !== this.focusNode && e.target !== this.handleMin) {
						setValue(true);
					} else {
						offsetValue = value - ((isMax && this.handleMin) ? values[1] : values[0]);
					}
					this[isMax ? "focusNode" : "handleMin"].focus();
					if (actionHandles) {
						actionHandles.forEach(function (h) { h.remove(); });
					}
					actionHandles = this.own(
						on(root, touch.move, continueDrag),
						on(root, touch.release, endDrag)
					);
				}),

				keyDown = lang.hitch(this, function (e) {
					function handleKeys() {
						var	step = this.step,
							multiplier = 1,
							horizontal = this.orientation !== "V";
						switch (e.keyCode) {
							case keys.HOME:
								values[handleIdx] = [ this.min, values[0] ][handleIdx];
								break;
							case keys.END:
								values[handleIdx] = maxValue;
								break;
							case keys.RIGHT_ARROW:
								multiplier = -1;
								/* falls through */
							case keys.LEFT_ARROW:
								values[handleIdx] = parseFloat(values[handleIdx]) +
									multiplier * ((this.flip && horizontal) ? step : -step);
								break;
							case keys.DOWN_ARROW:
								multiplier = -1;
								/* falls through */
							case keys.UP_ARROW:
								values[handleIdx] = parseFloat(values[handleIdx]) +
									multiplier * ((!this.flip || horizontal) ? step : -step);
								break;
							default:
								return;
						}
						e.preventDefault();
						this.value = values.join(",");
						this.validateProperties();
						this._handleOnChange(this.value, false);
					}

					if (this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey) { return; }
					var	handleIdx = 0,
						maxValue = this.max,
						values = String(this.value).split(/,/g);
					if (e.target === this.focusNode) {
						handleIdx = values.length - 1;
					} else if (e.target === this.handleMin) {
						maxValue = values[1];
					} else {
						return;
					}
					lang.hitch(this, handleKeys)();
				}),

				keyUp = lang.hitch(this, function (e) {
					if (this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey) { return; }
					this._handleOnChange(this.value, true);
				}),

				point, pixelValue, value,
				node = this;
			if (!isNaN(parseFloat(this.valueNode.value))) { // browser back button or value coded on INPUT
				this.value = this.valueNode.value;
			}
			this.own(
				on(this, touch.press, beginDrag),
				on(this, "keydown", keyDown), // for desktop a11y
				on(this.focusNode, "keyup", keyUp) // fire onChange on desktop
			);
			this.invalidateProperty("orientation"); // apply appropriate CSS class names in case the default is used
			this.invalidateProperty("tabIndex"); // apply default tabIndex in case the default is used
		},

		startup: function () {
			this.valueNode.setAttribute("value", this.value); // set the reset value once
			// if the form is reset, then notify the widget to reposition the handles
			if (this.valueNode.form) {
				this.own(on(this.valueNode.form, "reset", lang.hitch(this, "defer",
					function () {
						if (this.value !== this.valueNode.value) {
							this.value = this.valueNode.value;
						}
					}, 0
				)));
			}
		}
	});
});
<commit_msg>Slider (and other future subclasses) should define refreshRendering().<commit_after>define([
	"dojo/_base/connect",
	"dojo/_base/lang",
	"dojo/_base/window",
	"dojo/sniff",
	"dojo/query",
	"dojo/dom-class",
	"dojo/dom-construct",
	"dojo/dom-geometry",
	"dojo/dom-style",
	"dojo/keys",
	"dojo/touch",
	"dojo/on",
	"./register",
	"./FormValueWidget",
	"./themes/load!common,Slider"	// common for duiInline etc., Slider for duiSlider etc.
], function (connect, lang, win, has, query, domClass, domConstruct, domGeometry, domStyle,
		keys, touch, on, register, FormValueWidget) {

	return register("d-slider", [HTMLElement, FormValueWidget], {
		// summary:
		//		A non-templated Slider widget similar to the HTML5 INPUT type=range.

		// min: [const] Number
		//		The first value the slider can be set to.
		min: NaN,

		// max: [const] Number
		//		The last value the slider can be set to.
		max: NaN,

		// step: [const] Number
		//		The delta from 1 value to another.
		//		This causes the slider handle to snap/jump to the closest possible value.
		//		A value of 0 means continuous (as much as allowed by pixel resolution).
		step: 1,

		// baseClass: [const] String
		//		The name of the CSS class of this widget.
		baseClass: "duiSlider",

		// flip: [const] Boolean
		//		Specifies if the slider should change its default: ascending <--> descending.
		flip: false,

		// orientation: [const] String
		//		The slider direction for ascending values.
		//		- "H": horizontal (dependent on default left-to-right or right-to-left direction)
		//		- "V": vertical
		orientation: "H",

		preCreate: function () {
			this._orientationAttrs = {
				"H": { start: "x", size: "w", pageStart: "pageX", clientStart: "clientX",
						progressBarStart: "left", progressBarSize: "width" },
				"V": { start: "y", size: "h", pageStart: "pageY", clientStart: "clientY", progressBarStart: "top",
						progressBarSize: "height" }
			};

			this.addInvalidatingProperties(
				{ value: "invalidateProperty" },
				{ min: "invalidateProperty" },
				{ max: "invalidateProperty" },
				"name",
				"flip",
				"step",
				"orientation"
			);
		},

		refreshProperties: function (props) {
			if (props.value && !this.handleMin && String(this.value).indexOf(",") > 0) {
				this.handleMin = domConstruct.create("div", { role: "slider" }, this.progressBar, "first");
				this.tabStops = "handleMin,focusNode";
			}
			if (props.value || props.min || props.max) {
				// force the value in bounds
				var values = String(this.value).split(/,/g);
				var	minValue = Math.max(Math.min(values[0], values[values.length-1], this.max), this.min),
					maxValue = Math.min(Math.max(values[0], values[values.length-1], this.min), this.max);
				// correct value in case the values were outside min/max
				var correctedValue = values.length === 1 ? String(maxValue) : (minValue + "," + maxValue);
				if (correctedValue !== this.value) {
					this.value = correctedValue;
					this.validateProperties();
				}
			}
			if (props.value) {
				this.valueNode.value = String(this.value);
			}
		},

		refreshRendering: function (props) {
			var toCSS = function (baseClass, modifier) {
				return baseClass.split(/ /g).map(function (c) {
					return c + modifier;
				}).join(" ");
			};

			if (props.orientation || props.flip) {
				// add V or H suffix to baseClass for styling purposes
				var	horizontal = this.orientation !== "V",
					ltr = horizontal ? this.isLeftToRight() : false,
					flip = !!this.flip;
				// _reversed is complicated since you can have flipped right-to-left and vertical is upside down by default
				this._reversed = !((horizontal && ((ltr && !flip) || (!ltr && flip))) || (!horizontal && flip));
				this._attrs = this._orientationAttrs[this.orientation];
				var baseClass = toCSS(this.className, this.orientation);
				domClass.add(this, baseClass);
				baseClass = this.baseClass + " " + baseClass;
				domClass.add(this, toCSS(baseClass, this._reversed ? "HtL" : "LtH"));
				domClass.add(this.containerNode, toCSS(baseClass, "Bar") + " " + toCSS(baseClass, "RemainingBar"));
				domClass.add(this.progressBar, toCSS(baseClass, "Bar") + " " + toCSS(baseClass, "ProgressBar"));
				domClass.add(this.focusNode, toCSS(baseClass, "Handle") + " " + toCSS(baseClass, "HandleMax"));
				if (this.handleMin) {
					domClass.add(this.handleMin, toCSS(baseClass, "Handle") + " " + toCSS(baseClass, "HandleMin"));
				}
				// pass widget attributes to children
				var self = this;
				this.getChildren().forEach(function (obj) {
					obj.orientation = self.orientation;
					obj.reverse = self._reversed;
				});
			}
			if (props.name) {
				this.valueNode.name = this.name;
			}
			if (props.max) {
				this.focusNode.setAttribute("aria-valuemax", this.max);
			}
			if (props.min) {
				(this.handleMin || this.focusNode).setAttribute("aria-valuemin", this.min);
			}
			if (props.value || props.min || props.max) {
				this._positionHandles();
			}
		},

		buildRendering: function () {

			// look for child INPUT node under root node
			this.valueNode = query("> INPUT", this)[0];
			if (!this.valueNode) {
				this.valueNode = domConstruct.create("input", { "type": "text", readOnly: true, value: this.value }, this, "last");
			}

			this.containerNode = domConstruct.create("div", {}, this, "last");
			var n = this.firstChild;
			while (n) {
				var next = n.nextSibling;
				if (n !== this.valueNode && n !== this.containerNode) {
					// move all extra markup nodes to the containerNode for relative sizing and placement
					this.containerNode.appendChild(n);
				}
				n = next;
			}
			this.progressBar = domConstruct.create("div", {}, this.containerNode, "last");
			this.focusNode = domConstruct.create("div", { role: "slider" }, this.progressBar, "last");

			// prevent browser scrolling on IE10 (evt.preventDefault() is not enough)
			if (typeof this.style.msTouchAction !== "undefined") {
				this.style.msTouchAction = "none";
			}
		},

		_positionHandles: function () {
			var values = String(this.value).split(/,/g);
			if (values.length === 1) {
				values = [this.min, values[0]];
			} else {
				this.handleMin.setAttribute("aria-valuenow", values[0]);
				this.handleMin.setAttribute("aria-valuemax", values[1]);
			}
			this.focusNode.setAttribute("aria-valuenow", values[1]);
			this.focusNode.setAttribute("aria-valuemin", values[0]);
			var	toPercent = (values[1] - this.min) * 100 / (this.max - this.min),
				toPercentMin = (values[0] - this.min) * 100 / (this.max - this.min),
				s = {};
			s[this._attrs.progressBarSize] = (toPercent - toPercentMin) + "%";
			s[this._attrs.progressBarStart] = (this._reversed ? (100 - toPercent) : toPercentMin) + "%";
			domStyle.set(this.progressBar, s);
		},

		postCreate: function () {
			var	beginDrag = lang.hitch(this,
				function (e) {
					e.preventDefault();
					var	setValue = lang.hitch(this, function (priorityChange) {
							var values = String(this.value).split(/,/g);
							value -= offsetValue;
							// now perform visual slide
							domClass.toggle(this.progressBar, "duiSliderTransition", !!priorityChange);
							this.value =
								values.length === 1
									? String(value)
									: (isMax
										? (values[0] + "," + value)
										: (value + "," + values[1]));
							this.validateProperties();
							this._handleOnChange(this.value, priorityChange);
						}),
						getEventData = lang.hitch(this, function (e) {
							point = isMouse
								? e[this._attrs.pageStart]
								: ((e.touches && e.touches[0])
									? e.touches[0][this._attrs.pageStart]
									: e[this._attrs.clientStart]);
							pixelValue = point - startPixel;
							pixelValue = Math.min(Math.max(pixelValue, 0), maxPixels);
							var discreteValues = this.step ? ((this.max - this.min) / this.step) : maxPixels;
							if (discreteValues <= 1 || discreteValues === Infinity) { discreteValues = maxPixels; }
							var wholeIncrements = Math.round(pixelValue * discreteValues / maxPixels);
							value = (this.max - this.min) * wholeIncrements / discreteValues;
							value = this._reversed ? (this.max - value) : (this.min + value);
						}),
						continueDrag = lang.hitch(this, function (e) {
							e.preventDefault();
							getEventData(e);
							setValue(false);
						}),
						endDrag = lang.hitch(this, function (e) {
							e.preventDefault();
							if (actionHandles) {
								actionHandles.forEach(function (h) { h.remove(); });
							}
							actionHandles = [];
							getEventData(e);
							setValue(true);
							// fire onChange
						}),
						isMouse = e instanceof MouseEvent, // e.type can be MSPointerDown but still be instanceof MouseEvent
						// get the starting position of the content area (dragging region)
						// can't use true since the added docScroll and the returned x are body-zoom incompatibile
						box = domGeometry.position(this.containerNode, false),
						scroll = domGeometry.docScroll(),
						bodyZoom = has("ie") ? 1 : (parseFloat(domStyle.get(win.body(), "zoom")) || 1),
						nodeZoom = has("ie") ? 1 : (parseFloat(domStyle.get(node, "zoom")) || 1),
						root = win.doc.documentElement,
						actionHandles;
					if (this.disabled || this.readOnly) { return; }
					// fix scroll.y in IE10 for incorrect pageYOffset
					// https://connect.microsoft.com/IE/feedback/details/768781/ie10-window-pageyoffset-incorrect-value-when-page-zoomed-breaks-jquery-etc
					scroll.y = Math.min(scroll.y, this.containerNode.ownerDocument.documentElement.scrollTop || scroll.y);
					var startPixel = box[this._attrs.start] * nodeZoom * bodyZoom + scroll[this._attrs.start];
					var maxPixels = box[this._attrs.size] * nodeZoom * bodyZoom;
					var offsetValue = 0;
					getEventData(e);
					var values = String(this.value).split(/,/g);
					var isMax = (values.length === 1) || (Math.abs(value - values[0]) > Math.abs(value - values[1]));
					if (e.target !== this.focusNode && e.target !== this.handleMin) {
						setValue(true);
					} else {
						offsetValue = value - ((isMax && this.handleMin) ? values[1] : values[0]);
					}
					this[isMax ? "focusNode" : "handleMin"].focus();
					if (actionHandles) {
						actionHandles.forEach(function (h) { h.remove(); });
					}
					actionHandles = this.own(
						on(root, touch.move, continueDrag),
						on(root, touch.release, endDrag)
					);
				}),

				keyDown = lang.hitch(this, function (e) {
					function handleKeys() {
						var	step = this.step,
							multiplier = 1,
							horizontal = this.orientation !== "V";
						switch (e.keyCode) {
							case keys.HOME:
								values[handleIdx] = [ this.min, values[0] ][handleIdx];
								break;
							case keys.END:
								values[handleIdx] = maxValue;
								break;
							case keys.RIGHT_ARROW:
								multiplier = -1;
								/* falls through */
							case keys.LEFT_ARROW:
								values[handleIdx] = parseFloat(values[handleIdx]) +
									multiplier * ((this.flip && horizontal) ? step : -step);
								break;
							case keys.DOWN_ARROW:
								multiplier = -1;
								/* falls through */
							case keys.UP_ARROW:
								values[handleIdx] = parseFloat(values[handleIdx]) +
									multiplier * ((!this.flip || horizontal) ? step : -step);
								break;
							default:
								return;
						}
						e.preventDefault();
						this.value = values.join(",");
						this.validateProperties();
						this._handleOnChange(this.value, false);
					}

					if (this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey) { return; }
					var	handleIdx = 0,
						maxValue = this.max,
						values = String(this.value).split(/,/g);
					if (e.target === this.focusNode) {
						handleIdx = values.length - 1;
					} else if (e.target === this.handleMin) {
						maxValue = values[1];
					} else {
						return;
					}
					lang.hitch(this, handleKeys)();
				}),

				keyUp = lang.hitch(this, function (e) {
					if (this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey) { return; }
					this._handleOnChange(this.value, true);
				}),

				point, pixelValue, value,
				node = this;
			if (!isNaN(parseFloat(this.valueNode.value))) { // browser back button or value coded on INPUT
				this.value = this.valueNode.value;
			}
			this.own(
				on(this, touch.press, beginDrag),
				on(this, "keydown", keyDown), // for desktop a11y
				on(this.focusNode, "keyup", keyUp) // fire onChange on desktop
			);
			this.invalidateProperty("orientation"); // apply appropriate CSS class names in case the default is used
			this.invalidateProperty("tabIndex"); // apply default tabIndex in case the default is used
		},

		startup: function () {
			this.valueNode.setAttribute("value", this.value); // set the reset value once
			// if the form is reset, then notify the widget to reposition the handles
			if (this.valueNode.form) {
				this.own(on(this.valueNode.form, "reset", lang.hitch(this, "defer",
					function () {
						if (this.value !== this.valueNode.value) {
							this.value = this.valueNode.value;
						}
					}, 0
				)));
			}
		}
	});
});
<|endoftext|>


<commit_before>var icons = new Array("share", "explore", "connect");

function showIcon(id, delay) {
	$("#" + id).delay(delay+500).animate({
		marginTop: "0px",
		filter : 'alpha(opacity=100)',
		opacity: '1'
	}, 500);
}

function pushUpIcons()
{
	for(i=0;i<icons.length;i++)
	{
		$("#" + icons[i]).animate({
			top: '20px'
		}, 100).animate({
			top: '-' + $('body').height()
		}, 300);
	}
}

function pushDownIcons()
{
	for(i=0;i<icons.length;i++)
	{
		$("#" + icons[i]).animate({
			top: '0'
		});
	}
}

$(document).ready(

	function()
	{

		 for(i=0;i<icons.length;i++)
		 {

		 	showIcon(icons[i], i*150);

		 }

		 $('.footer').delay(1200).animate(
		 {
		 	filter : 'alpha(opacity=1)',
			opacity: '1'
		 },

		 500

		 );

		 $('.element').click(pushUpIcons);

		 $('#share').click(function(){

		 	$('#share-page').fadeIn();

		 });

		 $('.footer').click(function(){
		 	pushDownIcons();

		 	$('.page').fadeOut();

		 });

	}

);<commit_msg>blablabla<commit_after>var icons = new Array("share", "explore", "connect");

function showIcon(id, delay) {
	$("#" + id).delay(delay+500).animate({
		marginTop: "0px",
		filter : 'alpha(opacity=100)',
		opacity: '1'
	}, 500);
}

function pushUpIcons()
{
	for(i=0;i<icons.length;i++)
	{
		$("#" + icons[i]).animate({
			top: '35px'
		}, 100).animate({
			top: '-' + $('body').height()
		},
		{
			duration: 600,
			step: function(now, fx)
			{
				if(now < -$('body').height()*0.1)
				{
					$(this).css('opacity', $(this).css('opacity')-0.1);
				}
			}
		});
	}
}

function pushDownIcons()
{
	for(i=0;i<icons.length;i++)
	{
		$("#" + icons[i]).animate({
			top: '0'
		});
	}
}

$(document).ready(

	function()
	{

		 for(i=0;i<icons.length;i++)
		 {

		 	showIcon(icons[i], i*150);

		 }

		 $('.footer').delay(1200).animate(
		 {
		 	filter : 'alpha(opacity=1)',
			opacity: '1'
		 },

		 500

		 );

		 $('.element').click(pushUpIcons);

		 $('#share').click(function(){

		 	$('#share-page').fadeIn();

		 });

		 $('.footer').click(function(){
		 	pushDownIcons();

		 	$('.page').fadeOut();

		 });

	}

);<|endoftext|>


<commit_before>(function() {

  function obo2json (conf) {

    if (typeof(conf) == 'string')
      conf = { obo: conf }

    var oboString = conf['obo']

    var termList = [], termInfo = [], currentTerm, termIndex = {}
    function clear() { currentTerm = { parents: [], name: "" } }
    clear()

    function newTerm (id, parents, name) {
      termIndex[id] = termList.length
      termList.push ([id].concat (parents))
      termInfo.push (name)
    }

    function addTerm() {
      if (currentTerm.id) {
        newTerm (currentTerm.id, currentTerm.parents, currentTerm.name)
	clear()
      }
    }

    oboString.split("\n").forEach (function (line) {
      var m
      if (line.match (/^\[Term\]/))
	addTerm()
      else if (m = line.match (/^id: (GO:\d+)/))
	currentTerm.id = m[1]
      else if (m = line.match (/^name: (\S.*\S)/))
	currentTerm.name = m[1]
      else if (m = line.match (/^is_a: (GO:\d+)/))
	currentTerm.parents.push (m[1])
      else if (m = line.match (/^relationship: part_of (GO:\d+)/))
	currentTerm.parents.push (m[1])
      else if (line.match(/^is_obsolete/))
	clear()
    })
    addTerm()

    if (conf.discardMissingParents)
      termList = termList.map (function (termParents) {
        return [termParents[0]].concat (termParents.slice(1).filter (function (p) {
          return p in termIndex
        }))
      })

    if (conf['compress'])
      termList.forEach (function (termParents) {
	for (var i = 1; i < termParents.length; ++i) {
          var p = termParents[i]
          if (!(p in termIndex))
            newTerm (p, [], '')
	  termParents[i] = termIndex[p]
        }
      })

    var result = { termParents: termList}
    if (conf['includeTermInfo'])
      result.termInfo = termInfo

    return result
  }

  function gaf2json (conf) {

    if (typeof(conf) == 'string')
      conf = { gaf: conf }

    var primary = {}, isAlias = {}, isDuplicate = {}
    function addAlias (id, alias) {
      if (id in primary) {
        if (primary[id] == alias)
          return
        id = primary[id]
      }

      if (!(id in isAlias))
        isAlias[id] = {}
      primary[id] = id

      if (alias in isDuplicate) {
        isDuplicate[alias][id] = true
        return
      }

      if ((alias in primary) && primary[alias] != id) {
        var oldPrimary = primary[alias]
        if (conf.mergeDuplicates) {
          var toMerge = Object.keys (isAlias[oldPrimary])
          toMerge.push (oldPrimary)
          toMerge.forEach (function (mergeId) {
            primary[mergeId] = id
            isAlias[id][mergeId] = true
          })
          delete isAlias[oldPrimary]
        } else {
          delete isAlias[oldPrimary][alias]
          isDuplicate[alias] = {}
          isDuplicate[alias][oldPrimary] = true
          isDuplicate[alias][id] = true
          return
        }
      }

      if (id != alias)
        isAlias[id][alias] = 1
      primary[alias] = id
    }

    if (conf.aliases) {
      var stripRegex = /^\s*(.+?)\s*$/
        conf.aliases.split("\n").forEach (function (aliasLine) {
	  var stripMatch = stripRegex.exec(aliasLine)
	  if (stripMatch != null) {
            var a = stripMatch[1].split(/\s+/)
            a.forEach (function (alias) {
              addAlias (a[0], alias)
            })
          }
        })
    }

    var gafString = conf['gaf']
    var useDatabaseID = conf['useDatabaseID']

    var gafs = []
    gafString.split("\n").forEach (function (line) {
      if (!line.match(/^\s*\!/)) {
	var fields = line.split("\t")
	if (fields.length >= 7) {
	  var id = fields[useDatabaseID ? 1 : 2]
	  var alt = fields[useDatabaseID ? 2 : 1]
	  var synonyms = fields[10].split("|")
          addAlias (id, alt)
          synonyms.forEach (function (syn) { addAlias (id, syn) })
          gafs.push ({ id: id,
                       qualifier: fields[3],
                       go_id: fields[4] })
        }
      }
    })

    var assocs = {}
    Object.keys(isAlias).forEach (function (id) {
      if (!(id in isDuplicate))
        assocs[id] = []
    })

    gafs.forEach (function (gaf) {
      if (gaf.qualifier != "NOT") {
        if (!(gaf.id in isDuplicate)) {
          var p = primary[gaf.id]
          if (!(p in assocs))
            assocs[p] = []
	  assocs[p].push (gaf.go_id)
        }
      }
    })

    if (Object.keys(isDuplicate).length)
      console.warn ("Warning: the following duplicate aliases were discarded:\n"
                    + Object.keys(isDuplicate).sort().map (function (dup) {
                      return dup + " -> " + Object.keys(isDuplicate[dup]).sort().join(" ") + "\n"
                    }).join(""))

    var idAliasesTermsList = Object.keys(assocs).sort()
        .map (function (id) {
          return [ id, Object.keys(isAlias[id]).sort(), assocs[id] ]
        })
    return { idAliasTerm: idAliasesTermsList }
  }

  function flatfile2list (conf) {

    if (typeof(conf) == 'string')
      conf = { text: conf }

    var text = conf['text']
    var filter = conf.filter || function(line) { return line.length > 0 }

    var list = []
    text.split("\n").forEach (function (line) {
      list.push (line)
    })

    return list.filter (filter)
  }

  module.exports.obo2json = obo2json
  module.exports.gaf2json = gaf2json
  module.exports.flatfile2list = flatfile2list
}) ()
<commit_msg>minor corrections<commit_after>(function() {

  function obo2json (conf) {

    if (typeof(conf) == 'string')
      conf = { obo: conf }

    var oboString = conf['obo']

    var termList = [], termInfo = [], currentTerm, termIndex = {}
    function clear() { currentTerm = { parents: [], name: "" } }
    clear()

    function newTerm (id, parents, name) {
      termIndex[id] = termList.length
      termList.push ([id].concat (parents))
      termInfo.push (name)
    }

    function addTerm() {
      if (currentTerm.id) {
        newTerm (currentTerm.id, currentTerm.parents, currentTerm.name)
	clear()
      }
    }

    oboString.split("\n").forEach (function (line) {
      var m
      if (line.match (/^\[Term\]/))
	addTerm()
      else if (m = line.match (/^id: (GO:\d+)/))
	currentTerm.id = m[1]
      else if (m = line.match (/^name: (\S.*\S)/))
	currentTerm.name = m[1]
      else if (m = line.match (/^is_a: (GO:\d+)/))
	currentTerm.parents.push (m[1])
      else if (m = line.match (/^relationship: part_of (GO:\d+)/))
	currentTerm.parents.push (m[1])
      else if (line.match(/^is_obsolete/))
	clear()
    })
    addTerm()

    if (conf.discardMissingParents)
      termList = termList.map (function (termParents) {
        return [termParents[0]].concat (termParents.slice(1).filter (function (p) {
          return p in termIndex
        }))
      })

    if (conf['compress'])
      termList.forEach (function (termParents) {
	for (var i = 1; i < termParents.length; ++i) {
          var p = termParents[i]
          if (!(p in termIndex))
            newTerm (p, [], '')
	  termParents[i] = termIndex[p]
        }
      })

    var result = { termParents: termList}
    if (conf['includeTermInfo'])
      result.termInfo = termInfo

    return result
  }

  function gaf2json (conf) {

    if (typeof(conf) == 'string')
      conf = { gaf: conf }

    var primary = {}, isAlias = {}, isDuplicate = {}
    function addAlias (id, alias) {
      if (id in primary) {
        if (primary[id] === alias)
          return
        id = primary[id]
      } else
        primary[id] = id

      if (!(id in isAlias))
        isAlias[id] = {}

      if (alias in isDuplicate) {
        isDuplicate[alias][id] = true
        return
      }

      if ((alias in primary) && primary[alias] !== id) {
        var oldPrimary = primary[alias]
        if (conf.mergeDuplicates) {
          var toMerge = Object.keys (isAlias[oldPrimary])
          toMerge.push (oldPrimary)
          toMerge.forEach (function (mergeId) {
            primary[mergeId] = id
            isAlias[id][mergeId] = true
          })
          delete isAlias[oldPrimary]
        } else {
          delete isAlias[oldPrimary][alias]
          isDuplicate[alias] = {}
          isDuplicate[alias][oldPrimary] = true
          isDuplicate[alias][id] = true
          return
        }
      }

      if (id != alias)
        isAlias[id][alias] = 1
      primary[alias] = id
    }

    if (conf.aliases) {
      var stripRegex = /^\s*(.+?)\s*$/
        conf.aliases.split("\n").forEach (function (aliasLine) {
	  var stripMatch = stripRegex.exec(aliasLine)
	  if (stripMatch != null) {
            var a = stripMatch[1].split(/\s+/)
            a.forEach (function (alias) {
              addAlias (a[0], alias)
            })
          }
        })
    }

    var gafString = conf['gaf']
    var useDatabaseID = conf['useDatabaseID']

    var gafs = []
    gafString.split("\n").forEach (function (line) {
      if (!line.match(/^\s*\!/)) {
	var fields = line.split("\t")
	if (fields.length >= 7) {
	  var id = fields[useDatabaseID ? 1 : 2]
	  var alt = fields[useDatabaseID ? 2 : 1]
	  var synonyms = fields[10]
          addAlias (id, alt)
          if (synonyms.length)
            synonyms.split("|").forEach (function (syn) { addAlias (id, syn) })
          gafs.push ({ id: id,
                       qualifier: fields[3],
                       go_id: fields[4] })
        }
      }
    })

    var assocs = {}
    Object.keys(isAlias).forEach (function (id) {
      if (!(id in isDuplicate))
        assocs[id] = []
    })

    gafs.forEach (function (gaf) {
      if (gaf.qualifier != "NOT") {
        if (!(gaf.id in isDuplicate)) {
          var p = primary[gaf.id]
          if (!(p in assocs))
            assocs[p] = []
	  assocs[p].push (gaf.go_id)
        }
      }
    })

    if (Object.keys(isDuplicate).length)
      console.warn ("Warning: the following duplicate aliases were discarded:\n"
                    + Object.keys(isDuplicate).sort().map (function (dup) {
                      return dup + " -> " + Object.keys(isDuplicate[dup]).sort().join(" ") + "\n"
                    }).join(""))

    var idAliasesTermsList = Object.keys(assocs).sort()
        .map (function (id) {
          return [ id, Object.keys(isAlias[id]).sort(), assocs[id] ]
        })
    return { idAliasTerm: idAliasesTermsList }
  }

  function flatfile2list (conf) {

    if (typeof(conf) == 'string')
      conf = { text: conf }

    var text = conf['text']
    var filter = conf.filter || function(line) { return line.length > 0 }

    var list = []
    text.split("\n").forEach (function (line) {
      list.push (line)
    })

    return list.filter (filter)
  }

  module.exports.obo2json = obo2json
  module.exports.gaf2json = gaf2json
  module.exports.flatfile2list = flatfile2list
}) ()
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require foundation
//= require turbolinks
//= require_self

$(function(){ $(document).foundation(); });
<commit_msg>fixing js<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require foundation
//= require_self

$(function(){ $(document).foundation(); });
<|endoftext|>


<commit_before>window.optly                = window.optly || {};
window.optly.mrkt           = window.optly.mrkt || {};
window.optly.mrkt.services  = window.optly.mrkt.services || {};
window.optly.mrkt.user      = window.optly.mrkt.user || {};
window.optly.mrkt.errorQ    = window.optly.mrkt.errorQ || [];

window.optly.mrkt.Optly_Q = function(acctData, expData){
  var objectCreateSupported = typeof Object.create === 'function';

  window.optly.PRELOAD = window.optly.PRELOAD || {token: null};

  if(!objectCreateSupported) {
    var ThrowAway = function (a, e) {
      this.acctData = a;
      this.expData = e;

      window.optly.PRELOAD.token = this.acctData.csrf_token;
    };

    ThrowAway.prototype = window.optly.mrkt.Optly_Q.prototype;

    if(arguments.length > 0) {
      return new ThrowAway(acctData, expData);
    } else{
      return new ThrowAway();
    }
  }

  if(arguments.length > 0 ){
    window.optly.PRELOAD.token = acctData.csrf_token;

    return Object.create(window.optly.mrkt.Optly_Q.prototype, {
      acctData: {
        value: window.optly.mrkt.user.acctData = acctData,
      },
      expData: {
        value: window.optly.mrkt.user.expData = expData
      }
    });
  } else {
    var acctCache, expCache;

    return Object.create(window.optly.mrkt.Optly_Q.prototype, {
      acctData: {
        get: function(){return acctCache;},
        set: function(val){
          if(!acctCache){
            window.optly.PRELOAD.token = val.csrf_token;
            window.optly.mrkt.user.acctData = val;
            acctCache = val;
          }
        }
      },
      expData: {
        get: function(){return expCache;},
        set: function(val){
          if(!expCache){
            window.optly.mrkt.user.expData = val;
            expCache = val;
          }
        }
      }
    });
  }
};

window.optly.mrkt.Optly_Q.prototype = {

  transformQueuedArgs: function(queuedArgs) {
    var funcArgs = [];
    $.each(queuedArgs, function(index, arg) {
      if (this[ arg ] !== undefined && typeof arg !== 'object') {
        funcArgs.push(this[ arg ]);
      } else if(typeof arg === 'object') {
        funcArgs.push(arg);
      }
    }.bind(this));

    return funcArgs;
  },

  parseQ: function(fnQ) {
    var queuedArgs,
      transformedArgs,
      queuedFn = fnQ[0];

    queuedArgs = fnQ.slice(1);

    //if there are no arguments call the function with the object scope
    if(queuedArgs.length === 0) {
      queuedFn.call(this);
    } else {
      transformedArgs = this.transformQueuedArgs(queuedArgs);
      queuedFn.apply( queuedFn, transformedArgs );
    }

  },

  push: function(fnQ) {

    switch(typeof fnQ[0]) {
      case 'function':
        this.parseQ(fnQ);
      break;

      case 'string':
        fnQ[0] = this.fnCache[ fnQ[0] ];
        this.parseQ(fnQ);
      break;

      default:
        for (var i = 0; i < fnQ.length; i += 1) {
          if(typeof fnQ[i][0] === 'function') {
            this.parseQ(fnQ[i]);
          } else if(typeof fnQ[i][0] === 'string') {
            fnQ[i][0] = this.fnCache[ fnQ[i][0] ];
            this.parseQ(fnQ[i]);
          }
        }
      break;
    }
  }

};

window.optly.mrkt.services.xhr = {
  makeRequest: function(request) {
    var deferreds = [], deferredPromise;

    // check if multiple requests are present
    if ( Array.isArray(request) ) {
      for (var i = 0; i < request.length; i += 1) {
        if (typeof request[i] === 'object') {
          deferredPromise = $.ajax({
            type: request[i].type,
            url: request[i].url
          });
          // parameters passed must be objects with a path and properties keys
          if (request[i].properties !== undefined) {
            this.handleErrors( deferredPromise, request[i].url, request[i].properties );
          }

          deferreds.push( deferredPromise );

        }
      }
      this.resolveDeferreds(deferreds);
      return deferreds;
    }
    // If single request, then return the promise directly
    else {
      deferredPromise = $.ajax({
        type: request.type,
        url: request.url
      });
      if (request.properties !== undefined) {
        this.handleErrors( deferredPromise, request.url, request.properties );
      }
      return deferredPromise;
    }
  },

  logSegmentError: function(category, action, label) {
    window.analytics.ready(function() {
      window.analytics.track(action, {
        category: category,
        label: label
      });
    });
  },

  validateTypes: function(resp, properties, url) {
    var errorMessage;
    $.each(properties, function(property, type) {
      // if property is not nested
      if(typeof type !== 'object') {
        if (typeof resp[ property ] !== type) {
          errorMessage = 'resp.' + property + ' is not a ' + type + ': ' + typeof(resp[ property ]);

          this.logSegmentError(url, 'api error', errorMessage);
        }
      }
      // if property is nested
      else {

        this.validateNestedTypes( resp[ property ], properties[ property ], property, type, url );

      }
    }.bind(this)); // end outer .each
  },

  validateNestedTypes: function(data, nestedData, parentProperty, type, url) {
    var errorMessage,
      propertyType;
    // if the property maps to an array
    if ( Array.isArray(data) ) {

      $.each(data, function(index, innerProperties) {

        $.each(nestedData, function(innerProp, innerType) {
          propertyType = typeof innerProperties[ innerProp ];
          if (propertyType !== innerType) {
            errorMessage = 'resp.' + parentProperty + '.' + innerProp + ' is not a ' + innerType + ': ' + propertyType;

            this.logSegmentError(url, 'api error', errorMessage);
          }
        }.bind(this));

      }.bind(this));
    }
    // if the property maps to an object
    else {
      $.each(type, function(innerProp, innerType) {
        propertyType = typeof data[ innerProp ];
        if (propertyType !== innerType) {
          errorMessage = 'resp.' + parentProperty + '.' + innerProp + ' is not a ' + innerType + ': ' + propertyType;

          this.logSegmentError(url, 'api error', errorMessage);
        }
      }.bind(this));
    }
  },

  handleErrors: function(deferred, apiEndpoint, properties) {
    var parsedRes, errorMessage;

    deferred.always(function(data, textStatus, jqXHR) {

        // check if the last argument is a promise, if so the response was successful
        if( this.isPromise(jqXHR) && jqXHR.status === 200 ) {

          //parse JSON and catch any errors -- if error return immediately
          try {
            parsedRes = JSON.parse(jqXHR.responseText);
          } catch (error) {
              window.optly.mrkt.errorQ.push([
                'logError',
                {
                  error: 'Error Parsing the Response of Your Account Data',
                }
              ]);
              this.logSegmentError('api error', apiEndpoint, 'response contains invalid json ' + error);

              // do not check validations if parse error
              return undefined;
          }

          // validate each property type
          this.validateTypes(parsedRes, properties, apiEndpoint);

        }
        // if the http request fails the jqXHR object will not be promise
        else {
          // in this case the data object is a promise so we parse it's response text
          if ( this.isPromise(data) ) {
            try {
              parsedRes = JSON.parse(data.responseText);
            } catch (error) {
                errorMessage = error + ', Response Text: ' + data.responseText + ', Status Text: ' + data.statusText + ', Status: ' + data.status;
                window.optly.mrkt.errorQ.push([
                  'logError',
                  {
                    error: 'Error Parsing the Response of Your Account Data',
                  }
                ]);
            }

            if (errorMessage === undefined && data.status !== 200) {
              errorMessage = 'Response Text: ' + data.responseText + ', Status Text: ' + data.statusText + ', Status: ' + data.status;
              window.optly.mrkt.errorQ.push([
                'logError',
                {
                error: JSON.parse(data.responseText).error,
                'error_id': JSON.parse(data.responseText).id
                }
              ]);
            }

            this.logSegmentError('api error', apiEndpoint, errorMessage);

          }

        }

    }.bind(this));

  },

  isPromise: function(value) {

    if (typeof value.then !== 'function') {
        return false;
    }
    var promiseThenSrc = String($.Deferred().then);
    var valueThenSrc = String(value.then);
    return promiseThenSrc === valueThenSrc;
  },

  resolveDeferreds: function(deferreds) {
    var responses = [], oldQue;
    $.when.apply($, deferreds).then(function() {
      // get all arguments returned from done
      var tranformedArgs = Array.prototype.slice.call(arguments);
      $.each(tranformedArgs, function(index, resp) {
        var respData = resp[0];
        if( !this.isPromise( respData ) && resp[1] === 'success' ) {
          responses.push(respData);
        }
        if (index === tranformedArgs.length - 1) {
          oldQue = window.optly_q;

          window.optly_q = window.optly.mrkt.Optly_Q(responses[0], responses[1]);
          window.optly_q.push(oldQue);
        }
      }.bind(this) );
    }.bind(this), function() {

      deferreds[0].then(function(acctData) {
        //if there is no error in account info instantiate the Q with no exp data
        oldQue = window.optly_q;

        window.optly_q = window.optly.mrkt.Optly_Q(acctData);
        window.optly_q.expDataError = true;
        window.optly_q.push(oldQue);
      }, function() {
        //if acctData error instantiate the Q with no arguments
        window.optly_q = window.optly.mrkt.Optly_Q();
      });
    }.bind(this) );

    return true;
  },

  readCookie: function (name) {
    name = name.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');

    var regex = new RegExp('(?:^|;)\\s?' + name + '=(.*?)(?:;|$)','i'),
        match = document.cookie.match(regex);

    return match && window.unescape(match[1]);
  },

  getLoginStatus: function(requestParams) {
    var deferreds;

    if ( !!this.readCookie('optimizely_signed_in') ) {
      deferreds = this.makeRequest(requestParams);
    } else {
      window.optly_q = window.optly.mrkt.Optly_Q();
    }

    return deferreds;
  }

};

(function() {
  'use strict';

  var acctParams,
    expParams;

  acctParams = {
    type: 'GET',
    url: '/account/info',
    properties: {
      email: 'string',
      account_id: 'number'
    }
  };

  expParams = {
    type: 'GET',
    url: '/experiment/load_recent?max_experiments=5',
    properties: {
      experiments: {
        id: 'number',
        description: 'string',
        has_started: 'boolean',
        can_edit: 'boolean'
      }
    }
  };

  window.optly.mrkt.services.xhr.getLoginStatus([acctParams, expParams]);
}());
<commit_msg>only show error dialog on account info error<commit_after>window.optly                = window.optly || {};
window.optly.mrkt           = window.optly.mrkt || {};
window.optly.mrkt.services  = window.optly.mrkt.services || {};
window.optly.mrkt.user      = window.optly.mrkt.user || {};
window.optly.mrkt.errorQ    = window.optly.mrkt.errorQ || [];

window.optly.mrkt.Optly_Q = function(acctData, expData){
  var objectCreateSupported = typeof Object.create === 'function';

  window.optly.PRELOAD = window.optly.PRELOAD || {token: null};

  if(!objectCreateSupported) {
    var ThrowAway = function (a, e) {
      this.acctData = a;
      this.expData = e;

      window.optly.PRELOAD.token = this.acctData.csrf_token;
    };

    ThrowAway.prototype = window.optly.mrkt.Optly_Q.prototype;

    if(arguments.length > 0) {
      return new ThrowAway(acctData, expData);
    } else{
      return new ThrowAway();
    }
  }

  if(arguments.length > 0 ){
    window.optly.PRELOAD.token = acctData.csrf_token;

    return Object.create(window.optly.mrkt.Optly_Q.prototype, {
      acctData: {
        value: window.optly.mrkt.user.acctData = acctData,
      },
      expData: {
        value: window.optly.mrkt.user.expData = expData
      }
    });
  } else {
    var acctCache, expCache;

    return Object.create(window.optly.mrkt.Optly_Q.prototype, {
      acctData: {
        get: function(){return acctCache;},
        set: function(val){
          if(!acctCache){
            window.optly.PRELOAD.token = val.csrf_token;
            window.optly.mrkt.user.acctData = val;
            acctCache = val;
          }
        }
      },
      expData: {
        get: function(){return expCache;},
        set: function(val){
          if(!expCache){
            window.optly.mrkt.user.expData = val;
            expCache = val;
          }
        }
      }
    });
  }
};

window.optly.mrkt.Optly_Q.prototype = {

  transformQueuedArgs: function(queuedArgs) {
    var funcArgs = [];
    $.each(queuedArgs, function(index, arg) {
      if (this[ arg ] !== undefined && typeof arg !== 'object') {
        funcArgs.push(this[ arg ]);
      } else if(typeof arg === 'object') {
        funcArgs.push(arg);
      }
    }.bind(this));

    return funcArgs;
  },

  parseQ: function(fnQ) {
    var queuedArgs,
      transformedArgs,
      queuedFn = fnQ[0];

    queuedArgs = fnQ.slice(1);

    //if there are no arguments call the function with the object scope
    if(queuedArgs.length === 0) {
      queuedFn.call(this);
    } else {
      transformedArgs = this.transformQueuedArgs(queuedArgs);
      queuedFn.apply( queuedFn, transformedArgs );
    }

  },

  push: function(fnQ) {

    switch(typeof fnQ[0]) {
      case 'function':
        this.parseQ(fnQ);
      break;

      case 'string':
        fnQ[0] = this.fnCache[ fnQ[0] ];
        this.parseQ(fnQ);
      break;

      default:
        for (var i = 0; i < fnQ.length; i += 1) {
          if(typeof fnQ[i][0] === 'function') {
            this.parseQ(fnQ[i]);
          } else if(typeof fnQ[i][0] === 'string') {
            fnQ[i][0] = this.fnCache[ fnQ[i][0] ];
            this.parseQ(fnQ[i]);
          }
        }
      break;
    }
  }

};

window.optly.mrkt.services.xhr = {
  makeRequest: function(request) {
    var deferreds = [], deferredPromise;

    // check if multiple requests are present
    if ( Array.isArray(request) ) {
      for (var i = 0; i < request.length; i += 1) {
        if (typeof request[i] === 'object') {
          deferredPromise = $.ajax({
            type: request[i].type,
            url: request[i].url
          });
          // parameters passed must be objects with a path and properties keys
          if (request[i].properties !== undefined) {
            this.handleErrors( deferredPromise, request[i].url, request[i].properties );
          }

          deferreds.push( deferredPromise );

        }
      }
      this.resolveDeferreds(deferreds);
      return deferreds;
    }
    // If single request, then return the promise directly
    else {
      deferredPromise = $.ajax({
        type: request.type,
        url: request.url
      });
      if (request.properties !== undefined) {
        this.handleErrors( deferredPromise, request.url, request.properties );
      }
      return deferredPromise;
    }
  },

  logSegmentError: function(category, action, label) {
    window.analytics.ready(function() {
      window.analytics.track(action, {
        category: category,
        label: label
      });
    });
  },

  validateTypes: function(resp, properties, url) {
    var errorMessage;
    $.each(properties, function(property, type) {
      // if property is not nested
      if(typeof type !== 'object') {
        if (typeof resp[ property ] !== type) {
          errorMessage = 'resp.' + property + ' is not a ' + type + ': ' + typeof(resp[ property ]);

          this.logSegmentError(url, 'api error', errorMessage);
        }
      }
      // if property is nested
      else {

        this.validateNestedTypes( resp[ property ], properties[ property ], property, type, url );

      }
    }.bind(this)); // end outer .each
  },

  validateNestedTypes: function(data, nestedData, parentProperty, type, url) {
    var errorMessage,
      propertyType;
    // if the property maps to an array
    if ( Array.isArray(data) ) {

      $.each(data, function(index, innerProperties) {

        $.each(nestedData, function(innerProp, innerType) {
          propertyType = typeof innerProperties[ innerProp ];
          if (propertyType !== innerType) {
            errorMessage = 'resp.' + parentProperty + '.' + innerProp + ' is not a ' + innerType + ': ' + propertyType;

            this.logSegmentError(url, 'api error', errorMessage);
          }
        }.bind(this));

      }.bind(this));
    }
    // if the property maps to an object
    else {
      $.each(type, function(innerProp, innerType) {
        propertyType = typeof data[ innerProp ];
        if (propertyType !== innerType) {
          errorMessage = 'resp.' + parentProperty + '.' + innerProp + ' is not a ' + innerType + ': ' + propertyType;

          this.logSegmentError(url, 'api error', errorMessage);
        }
      }.bind(this));
    }
  },

  handleErrors: function(deferred, apiEndpoint, properties) {
    var parsedRes,
      errorMessage,
      isExpEndpoint = /\/experiment/.test(apiEndpoint);

    deferred.always(function(data, textStatus, jqXHR) {

        // check if the last argument is a promise, if so the response was successful
        if( this.isPromise(jqXHR) && jqXHR.status === 200 ) {

          //parse JSON and catch any errors -- if error return immediately
          try {
            parsedRes = JSON.parse(jqXHR.responseText);
          } catch (error) {
              if(!isExpEndpoint) {
                window.optly.mrkt.errorQ.push([
                  'logError',
                  {
                    error: 'There was an error in your account data.',
                  }
                ]);
              }
              this.logSegmentError('api error', apiEndpoint, 'response contains invalid json ' + error);

              // do not check validations if parse error
              return undefined;
          }

          // validate each property type
          this.validateTypes(parsedRes, properties, apiEndpoint);

        }
        // if the http request fails the jqXHR object will not be promise
        else {
          // in this case the data object is a promise so we parse it's response text
          if ( this.isPromise(data) ) {
            try {
              parsedRes = JSON.parse(data.responseText);
            } catch (error) {
                errorMessage = error + ', Response Text: ' + data.responseText + ', Status Text: ' + data.statusText + ', Status: ' + data.status;
                if(!isExpEndpoint) {
                  window.optly.mrkt.errorQ.push([
                    'logError',
                    {
                      error: 'There was an error in your account data.',
                    }
                  ]);
                }
            }

            if (errorMessage === undefined && data.status !== 200) {
              errorMessage = 'Response Text: ' + data.responseText + ', Status Text: ' + data.statusText + ', Status: ' + data.status;
              if(!isExpEndpoint) {
                window.optly.mrkt.errorQ.push([
                  'logError',
                  {
                  error: JSON.parse(data.responseText).error ? JSON.parse(data.responseText).error : 'We were unable to retrieve your account information.',
                  'error_id': JSON.parse(data.responseText).id
                  }
                ]);
              }
            }

            this.logSegmentError('api error', apiEndpoint, errorMessage);

          }

        }

    }.bind(this));

  },

  isPromise: function(value) {

    if (typeof value.then !== 'function') {
        return false;
    }
    var promiseThenSrc = String($.Deferred().then);
    var valueThenSrc = String(value.then);
    return promiseThenSrc === valueThenSrc;
  },

  resolveDeferreds: function(deferreds) {
    var responses = [], oldQue;
    $.when.apply($, deferreds).then(function() {
      // get all arguments returned from done
      var tranformedArgs = Array.prototype.slice.call(arguments);
      $.each(tranformedArgs, function(index, resp) {
        var respData = resp[0];
        if( !this.isPromise( respData ) && resp[1] === 'success' ) {
          responses.push(respData);
        }
        if (index === tranformedArgs.length - 1) {
          oldQue = window.optly_q;

          window.optly_q = window.optly.mrkt.Optly_Q(responses[0], responses[1]);
          window.optly_q.push(oldQue);
        }
      }.bind(this) );
    }.bind(this), function() {

      deferreds[0].then(function(acctData) {
        //if there is no error in account info instantiate the Q with no exp data
        oldQue = window.optly_q;

        window.optly_q = window.optly.mrkt.Optly_Q(acctData);
        window.optly_q.expDataError = true;
        window.optly_q.push(oldQue);
      }, function() {
        //if acctData error instantiate the Q with no arguments
        window.optly_q = window.optly.mrkt.Optly_Q();
      });
    }.bind(this) );

    return true;
  },

  readCookie: function (name) {
    name = name.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');

    var regex = new RegExp('(?:^|;)\\s?' + name + '=(.*?)(?:;|$)','i'),
        match = document.cookie.match(regex);

    return match && window.unescape(match[1]);
  },

  getLoginStatus: function(requestParams) {
    var deferreds;

    if ( !!this.readCookie('optimizely_signed_in') ) {
      deferreds = this.makeRequest(requestParams);
    } else {
      window.optly_q = window.optly.mrkt.Optly_Q();
    }

    return deferreds;
  }

};

(function() {
  'use strict';

  var acctParams,
    expParams;

  acctParams = {
    type: 'GET',
    url: '/account/info',
    properties: {
      email: 'string',
      account_id: 'number'
    }
  };

  expParams = {
    type: 'GET',
    url: '/experiment/load_recent?max_experiments=5',
    properties: {
      experiments: {
        id: 'number',
        description: 'string',
        has_started: 'boolean',
        can_edit: 'boolean'
      }
    }
  };

  window.optly.mrkt.services.xhr.getLoginStatus([acctParams, expParams]);
}());
<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require jquery-ui/datepicker
//= require jquery-ui/autocomplete
//= require cocoon
//= require autocomplete-rails
//= require dataTables/jquery.dataTables
//= require dataTables/bootstrap/2/jquery.dataTables.bootstrap
//= require bootstrap-transition
//= require bootstrap-alert
//= require bootstrap-button
//= require bootstrap-collapse
//= require bootstrap-dropdown
//= require bootstrap-modal
//= require bootstrap-scrollspy
//= require bootstrap-tab
//= require bootstrap-tooltip
//= require bootstrap-popover
//= require variables.js
//= require select2
//= require_tree
//= require_self

function truncate() {
  if ($(".caption_cat").length) {
    $(".caption_cat").dotdotdot({
      height: 150,
      after: ".more_info",
      watch: 'window'
    });
  }

  if ($(".equipment_title").length) {
    $(".equipment_title").dotdotdot({
      height: 27, // must match .equipment_title height
      watch: 'window'
    });
  }

  // TODO: Refactor this so it won't so drastically impact client-side performance.
  // Until it's refactored, it's better off disabled.
  // This code displays a tooltip in the catalog if the equipment model name is truncated.
  //
  // This code was re-enabled on 2014-07-28 and no noticeable
  // performance hit was noted

   $(".equipment_title").each(function(){
     $(this).trigger("isTruncated", function( isTruncated ) {
       if ( isTruncated ) {
         $(this).children(".equipment_title_link").tooltip();
       }
     });
   });
};

// general submit on change class
$(document).on('change', '.autosubmitme', function() {
  // test for cart date fields to toggle cart spinner
  if ( $(this).parents('div:first').is("#cart_dates") ) {
    pause_cart();
  }
  $(this).parents('form:first').submit();
});

$(document).on('railsAutocomplete.select', '#fake_searched_id', function(){
  $(this).parents('form').submit();
});

$(document).ready(function() {

  // For DataTables and Bootstrap
  $('.datatable').dataTable({
    "sDom": "<'row'<'span4'l><'span5'f>r>t<'row'<'span3'i><'span6'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  wideDataTables = $('.datatable-wide').dataTable({
    "sDom": "<'row'<'span5'l><'span7'f>r>t<'row'<'span5'i><'span7'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // ### LOG JS ### //

  // Ugly hack to avoid reinitializing #table_log with the correct order
  try {
    if (wideDataTables[0].id == "table_log") {
      wideDataTables.fnSort([[0, "desc"]]);
    }
  } catch (TypeError) {}

  $('.history_table').dataTable({
    "sDom": "<'row'<l><f>r>t<'row'<'span3'i><p>>",
    "bLengthChange": false,
    "sPaginationType": "bootstrap",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // ### REPORTS JS ### //

  $('.report_table').dataTable({
    "sDom": "<'row'<'span3'l>fr>t<'row'<'span3'i><p>>",
    "sPaginationType": "bootstrap",
    "iDisplayLength" : 25,
    "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
    "aoColumnDefs": [{ "bSortable": false, "aTargets": [ "no_sort" ] }]
  });

  // For fading out flash notices
  $(".alert .close").click( function() {
       $(this).parent().addClass("fade");
  });

  // make the sidebar follow you down the page
  if ($(window).width() > 767) {
    $("#sidebarbottom").sticky({topSpacing: 50, bottomSpacing: 200});
  }

  // truncate catalog descriptions
  truncate();

  $(".btn#modal").tooltip();
  $(".not-qualified-icon").tooltip();
  $(".not-qualified-icon-em").tooltip();

  $('.associated_em_box img').popover({ placement: 'bottom' });
  $("#my_reservations .dropdown-menu a").popover({ placement: 'bottom' });
  $("#my_equipment .dropdown-menu a").popover({ placement: 'bottom' });

  // fix sub nav on scroll
  var $win = $(window)
    , $nav = $('.subnav')
    , navTop = $('.subnav').length && $('.subnav').offset().top - 40
    , isFixed = 0
    , $hiddenName = $('.subnav .hide')

  processScroll()

  // hack sad times - holdover until rewrite for 2.1
  $nav.on('click', function () {
    if (!isFixed) setTimeout(function () {  $win.scrollTop($win.scrollTop() - 47) }, 10)
  })

  $win.on('scroll', processScroll)

  function processScroll() {
    var i, scrollTop = $win.scrollTop()
    if (scrollTop >= navTop && !isFixed) {
      isFixed = 1
      $nav.addClass('subnav-fixed')
      $hiddenName.removeClass('hide')
      if (!$('.subnav li').hasClass('active')) {
        $('.subnav li:eq(1)').addClass('active')
      }
    } else if (scrollTop <= navTop && isFixed) {
      isFixed = 0
      $nav.removeClass('subnav-fixed')
      $hiddenName.addClass('hide')
      $('.subnav li').removeClass('active')
    }
  }

  $('#modal').click(function() {
    $('#userModal div.modal-body').load(new_user, {possible_netid : $('#fake_reserver_id').val() }); // new_user defined in variables.js.erb
  });

  load_datepicker();

  // Select2 - fancy select lists
  $('select#equipment_model_category_id').select2();
  $('select#equipment_model_associated_equipment_model_ids').select2();
  $('select#equipment_model_requirements').select2();
  $('select#equipment_object_equipment_model_id').select2();
  $('select#requirement_equipment_model').select2();
  $('select.dropdown.dropselect').select2();

  // Popup confirmation when editing reservation equipment objects
  $('.reservation_eq_objects').on('change', function() {
    newMsg = ($('.select2-choice > .select2-chosen').text() == $('#equipment_object').attr('placeholder'))
      ? ""
      : "Be aware that changing the reservation equipment item may have an effect on another reservation. If you set this reservation's equipment item to an item that has already been checked out, the reservations will be swapped.";
    $('.form-actions').children('input').data('confirm', newMsg);
  });

});

<commit_msg>commented out broken JS<commit_after>//= require jquery
//= require jquery_ujs
//= require jquery-ui/datepicker
//= require jquery-ui/autocomplete
//= require cocoon
//= require autocomplete-rails
//= require dataTables/jquery.dataTables
//= require dataTables/bootstrap/2/jquery.dataTables.bootstrap
//= require bootstrap-transition
//= require bootstrap-alert
//= require bootstrap-button
//= require bootstrap-collapse
//= require bootstrap-dropdown
//= require bootstrap-modal
//= require bootstrap-scrollspy
//= require bootstrap-tab
//= require bootstrap-tooltip
//= require bootstrap-popover
//= require variables.js
//= require select2
//= require_tree
//= require_self

function truncate() {
  if ($(".caption_cat").length) {
    $(".caption_cat").dotdotdot({
      height: 150,
      after: ".more_info",
      watch: 'window'
    });
  }

  if ($(".equipment_title").length) {
    $(".equipment_title").dotdotdot({
      height: 27, // must match .equipment_title height
      watch: 'window'
    });
  }

  // TODO: Refactor this so it won't so drastically impact client-side performance.
  // Until it's refactored, it's better off disabled.
  // This code displays a tooltip in the catalog if the equipment model name is truncated.
  //
  // This code was re-enabled on 2014-07-28 and no noticeable
  // performance hit was noted

   $(".equipment_title").each(function(){
     $(this).trigger("isTruncated", function( isTruncated ) {
       if ( isTruncated ) {
         $(this).children(".equipment_title_link").tooltip();
       }
     });
   });
};

// general submit on change class
$(document).on('change', '.autosubmitme', function() {
  // test for cart date fields to toggle cart spinner
  if ( $(this).parents('div:first').is("#cart_dates") ) {
    pause_cart();
  }
  $(this).parents('form:first').submit();
});

$(document).on('railsAutocomplete.select', '#fake_searched_id', function(){
  $(this).parents('form').submit();
});

$(document).ready(function() {

  // For DataTables and Bootstrap
  $('.datatable').dataTable({
    "sDom": "<'row'<'span4'l><'span5'f>r>t<'row'<'span3'i><'span6'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  wideDataTables = $('.datatable-wide').dataTable({
    "sDom": "<'row'<'span5'l><'span7'f>r>t<'row'<'span5'i><'span7'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // ### LOG JS ### //

  // commented out on 2014/10/12 since it was giving an error for wideDataTables[0]

  // Ugly hack to avoid reinitializing #table_log with the correct order
  // try {
  //   if (wideDataTables[0].id == "table_log") {
  //     wideDataTables.fnSort([[0, "desc"]]);
  //   }
  // } catch (TypeError) {}

  $('.history_table').dataTable({
    "sDom": "<'row'<l><f>r>t<'row'<'span3'i><p>>",
    "bLengthChange": false,
    "sPaginationType": "bootstrap",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // ### REPORTS JS ### //

  $('.report_table').dataTable({
    "sDom": "<'row'<'span3'l>fr>t<'row'<'span3'i><p>>",
    "sPaginationType": "bootstrap",
    "iDisplayLength" : 25,
    "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
    "aoColumnDefs": [{ "bSortable": false, "aTargets": [ "no_sort" ] }]
  });

  // For fading out flash notices
  $(".alert .close").click( function() {
       $(this).parent().addClass("fade");
  });

  // make the sidebar follow you down the page
  if ($(window).width() > 767) {
    $("#sidebarbottom").sticky({topSpacing: 50, bottomSpacing: 200});
  }

  // truncate catalog descriptions
  truncate();

  $(".btn#modal").tooltip();
  $(".not-qualified-icon").tooltip();
  $(".not-qualified-icon-em").tooltip();

  $('.associated_em_box img').popover({ placement: 'bottom' });
  $("#my_reservations .dropdown-menu a").popover({ placement: 'bottom' });
  $("#my_equipment .dropdown-menu a").popover({ placement: 'bottom' });

  // fix sub nav on scroll
  var $win = $(window)
    , $nav = $('.subnav')
    , navTop = $('.subnav').length && $('.subnav').offset().top - 40
    , isFixed = 0
    , $hiddenName = $('.subnav .hide')

  processScroll()

  // hack sad times - holdover until rewrite for 2.1
  $nav.on('click', function () {
    if (!isFixed) setTimeout(function () {  $win.scrollTop($win.scrollTop() - 47) }, 10)
  })

  $win.on('scroll', processScroll)

  function processScroll() {
    var i, scrollTop = $win.scrollTop()
    if (scrollTop >= navTop && !isFixed) {
      isFixed = 1
      $nav.addClass('subnav-fixed')
      $hiddenName.removeClass('hide')
      if (!$('.subnav li').hasClass('active')) {
        $('.subnav li:eq(1)').addClass('active')
      }
    } else if (scrollTop <= navTop && isFixed) {
      isFixed = 0
      $nav.removeClass('subnav-fixed')
      $hiddenName.addClass('hide')
      $('.subnav li').removeClass('active')
    }
  }

  $('#modal').click(function() {
    $('#userModal div.modal-body').load(new_user, {possible_netid : $('#fake_reserver_id').val() }); // new_user defined in variables.js.erb
  });

  load_datepicker();

  // Select2 - fancy select lists
  $('select#equipment_model_category_id').select2();
  $('select#equipment_model_associated_equipment_model_ids').select2();
  $('select#equipment_model_requirements').select2();
  $('select#equipment_object_equipment_model_id').select2();
  $('select#requirement_equipment_model').select2();
  $('select.dropdown.dropselect').select2();

  // Popup confirmation when editing reservation equipment objects
  $('.reservation_eq_objects').on('change', function() {
    newMsg = ($('.select2-choice > .select2-chosen').text() == $('#equipment_object').attr('placeholder'))
      ? ""
      : "Be aware that changing the reservation equipment item may have an effect on another reservation. If you set this reservation's equipment item to an item that has already been checked out, the reservations will be swapped.";
    $('.form-actions').children('input').data('confirm', newMsg);
  });

});

<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require jquery.ui.datepicker
//= require jquery.ui.autocomplete
//= require jquery.spin
//= require cocoon
//= require autocomplete-rails
//= require dataTables/jquery.dataTables
//= require dataTables/bootstrap/2/jquery.dataTables.bootstrap
//= require bootstrap-transition
//= require bootstrap-alert
//= require bootstrap-button
//= require bootstrap-collapse
//= require bootstrap-dropdown
//= require bootstrap-modal
//= require bootstrap-scrollspy
//= require bootstrap-tab
//= require bootstrap-tooltip
//= require bootstrap-popover
//= require variables.js
//= require select2
//= require_tree
//= require_self

function truncate() {
  if ($(".caption_cat").length) {
    $(".caption_cat").dotdotdot({
      height: 150,
      after: ".more_info",
      watch: 'window'
    });
  }

  if ($(".equipment_title").length) {
    $(".equipment_title").dotdotdot({
      height: 27, // must match .equipment_title height
      watch: 'window'
    });
  }

  // TODO: Refactor this so it won't so drastically impact client-side performance.
  // Until it's refactored, it's better off disabled.
  // This code displays a tooltip in the catalog if the equipment model name is truncated.
  //
  // $(".equipment_title").each(function(){
  //   $(this).trigger("isTruncated", function( isTruncated ) {
  //     if ( isTruncated ) {
  //       $(this).children(".equipment_title_link").tooltip();
  //     }
  //   });
  // });
};

// general submit on change class
$(document).on('change', '.autosubmitme', function() {
  // test for cart date fields to toggle cart spinner
  if ( $(this).parents('div:first').is("#cart_dates") ) {
    pause_cart();
  }
  $(this).parents('form:first').submit();
});

$(document).on('railsAutocomplete.select', '#fake_searched_id', function(){
  $(this).parents('form').submit();
});

$(document).ready(function() {

  // For DataTables and Bootstrap
  $('.datatable').dataTable({
    "sDom": "<'row'<'span4'l><'span5'f>r>t<'row'<'span3'i><'span6'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  wideDataTables = $('.datatable-wide').dataTable({
    "sDom": "<'row'<'span5'l><'span7'f>r>t<'row'<'span5'i><'span7'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // Ugly hack to avoid reinitializing #table_log with the correct order
  try {
    if (wideDataTables[0].id == "table_log") {
      wideDataTables.fnSort([[0, "desc"]]);
    }
  } catch (TypeError) {}

  $('.history_table').dataTable({
    "sDom": "<'row'<l><f>r>t<'row'<'span3'i><p>>",
    "bLengthChange": false,
    "sPaginationType": "bootstrap",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  $('.report_table').dataTable({
    "sDom": "<'row'<'span3'l>fr>t<'row'<'span3'i><p>>",
    "sPaginationType": "bootstrap",
    "iDisplayLength" : 25,
    "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
    "aoColumnDefs": [{ "bSortable": false, "aTargets": [ "no_sort" ] }]
  });

  // For fading out flash notices
  $(".alert .close").click( function() {
       $(this).parent().addClass("fade");
  });

  // make the sidebar follow you down the page
  if ($(window).width() > 767) {
    $("#sidebarbottom").sticky({topSpacing: 50, bottomSpacing: 200});
  }

  truncate();

  $(".btn#modal").tooltip();
  $(".not-qualified-icon").tooltip();
  $(".not-qualified-icon-em").tooltip();

  $('.associated_em_box img').popover({ placement: 'bottom' });
  $("#my_reservations .dropdown-menu a").popover({ placement: 'bottom' });
  $("#my_equipment .dropdown-menu a").popover({ placement: 'bottom' });

  // fix sub nav on scroll
  var $win = $(window)
    , $nav = $('.subnav')
    , navTop = $('.subnav').length && $('.subnav').offset().top - 40
    , isFixed = 0
    , $hiddenName = $('.subnav .hide')

  processScroll()

  // hack sad times - holdover until rewrite for 2.1
  $nav.on('click', function () {
    if (!isFixed) setTimeout(function () {  $win.scrollTop($win.scrollTop() - 47) }, 10)
  })

  $win.on('scroll', processScroll)

  function processScroll() {
    var i, scrollTop = $win.scrollTop()
    if (scrollTop >= navTop && !isFixed) {
      isFixed = 1
      $nav.addClass('subnav-fixed')
      $hiddenName.removeClass('hide')
      if (!$('.subnav li').hasClass('active')) {
        $('.subnav li:eq(1)').addClass('active')
      }
    } else if (scrollTop <= navTop && isFixed) {
      isFixed = 0
      $nav.removeClass('subnav-fixed')
      $hiddenName.addClass('hide')
      $('.subnav li').removeClass('active')
    }
  }

  $('#modal').click(function() {
    $('#userModal div.modal-body').load(new_user, {possible_netid : $('#fake_reserver_id').val() }); // new_user defined in variables.js.erb
  });

  load_datepicker();

  // Select2 - fancy select lists
  $('select#equipment_model_category_id').select2();
  $('select#equipment_model_associated_equipment_model_ids').select2();
  $('select#equipment_model_requirements').select2();
  $('select#equipment_object_equipment_model_id').select2();
  $('select#requirement_equipment_model').select2();
  $('select.dropdown.dropselect').select2();

});

<commit_msg>reenable tooltipping??<commit_after>//= require jquery
//= require jquery_ujs
//= require jquery.ui.datepicker
//= require jquery.ui.autocomplete
//= require jquery.spin
//= require cocoon
//= require autocomplete-rails
//= require dataTables/jquery.dataTables
//= require dataTables/bootstrap/2/jquery.dataTables.bootstrap
//= require bootstrap-transition
//= require bootstrap-alert
//= require bootstrap-button
//= require bootstrap-collapse
//= require bootstrap-dropdown
//= require bootstrap-modal
//= require bootstrap-scrollspy
//= require bootstrap-tab
//= require bootstrap-tooltip
//= require bootstrap-popover
//= require variables.js
//= require select2
//= require_tree
//= require_self

function truncate() {
  if ($(".caption_cat").length) {
    $(".caption_cat").dotdotdot({
      height: 150,
      after: ".more_info",
      watch: 'window'
    });
  }

  if ($(".equipment_title").length) {
    $(".equipment_title").dotdotdot({
      height: 27, // must match .equipment_title height
      watch: 'window'
    });
  }

  // TODO: Refactor this so it won't so drastically impact client-side performance.
  // Until it's refactored, it's better off disabled.
  // This code displays a tooltip in the catalog if the equipment model name is truncated.
  //
  // This code was re-enabled on 2014-07-28 and no noticeable
  // performance hit was noted

   $(".equipment_title").each(function(){
     $(this).trigger("isTruncated", function( isTruncated ) {
       if ( isTruncated ) {
         $(this).children(".equipment_title_link").tooltip();
       }
     });
   });
};

// general submit on change class
$(document).on('change', '.autosubmitme', function() {
  // test for cart date fields to toggle cart spinner
  if ( $(this).parents('div:first').is("#cart_dates") ) {
    pause_cart();
  }
  $(this).parents('form:first').submit();
});

$(document).on('railsAutocomplete.select', '#fake_searched_id', function(){
  $(this).parents('form').submit();
});

$(document).ready(function() {

  // For DataTables and Bootstrap
  $('.datatable').dataTable({
    "sDom": "<'row'<'span4'l><'span5'f>r>t<'row'<'span3'i><'span6'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  wideDataTables = $('.datatable-wide').dataTable({
    "sDom": "<'row'<'span5'l><'span7'f>r>t<'row'<'span5'i><'span7'p>>",
    "sPaginationType": "bootstrap",
    "sScrollX": "100%",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // ### LOG JS ### //

  // Ugly hack to avoid reinitializing #table_log with the correct order
  try {
    if (wideDataTables[0].id == "table_log") {
      wideDataTables.fnSort([[0, "desc"]]);
    }
  } catch (TypeError) {}

  $('.history_table').dataTable({
    "sDom": "<'row'<l><f>r>t<'row'<'span3'i><p>>",
    "bLengthChange": false,
    "sPaginationType": "bootstrap",
    "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ "no_sort" ] }
        ]
  });

  // ### REPORTS JS ### //

  $('.report_table').dataTable({
    "sDom": "<'row'<'span3'l>fr>t<'row'<'span3'i><p>>",
    "sPaginationType": "bootstrap",
    "iDisplayLength" : 25,
    "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
    "aoColumnDefs": [{ "bSortable": false, "aTargets": [ "no_sort" ] }]
  });

  // For fading out flash notices
  $(".alert .close").click( function() {
       $(this).parent().addClass("fade");
  });

  // make the sidebar follow you down the page
  if ($(window).width() > 767) {
    $("#sidebarbottom").sticky({topSpacing: 50, bottomSpacing: 200});
  }

  // truncate catalog descriptions
  truncate();

  $(".btn#modal").tooltip();
  $(".not-qualified-icon").tooltip();
  $(".not-qualified-icon-em").tooltip();

  $('.associated_em_box img').popover({ placement: 'bottom' });
  $("#my_reservations .dropdown-menu a").popover({ placement: 'bottom' });
  $("#my_equipment .dropdown-menu a").popover({ placement: 'bottom' });

  // fix sub nav on scroll
  var $win = $(window)
    , $nav = $('.subnav')
    , navTop = $('.subnav').length && $('.subnav').offset().top - 40
    , isFixed = 0
    , $hiddenName = $('.subnav .hide')

  processScroll()

  // hack sad times - holdover until rewrite for 2.1
  $nav.on('click', function () {
    if (!isFixed) setTimeout(function () {  $win.scrollTop($win.scrollTop() - 47) }, 10)
  })

  $win.on('scroll', processScroll)

  function processScroll() {
    var i, scrollTop = $win.scrollTop()
    if (scrollTop >= navTop && !isFixed) {
      isFixed = 1
      $nav.addClass('subnav-fixed')
      $hiddenName.removeClass('hide')
      if (!$('.subnav li').hasClass('active')) {
        $('.subnav li:eq(1)').addClass('active')
      }
    } else if (scrollTop <= navTop && isFixed) {
      isFixed = 0
      $nav.removeClass('subnav-fixed')
      $hiddenName.addClass('hide')
      $('.subnav li').removeClass('active')
    }
  }

  $('#modal').click(function() {
    $('#userModal div.modal-body').load(new_user, {possible_netid : $('#fake_reserver_id').val() }); // new_user defined in variables.js.erb
  });

  load_datepicker();

  // Select2 - fancy select lists
  $('select#equipment_model_category_id').select2();
  $('select#equipment_model_associated_equipment_model_ids').select2();
  $('select#equipment_model_requirements').select2();
  $('select#equipment_object_equipment_model_id').select2();
  $('select#requirement_equipment_model').select2();
  $('select.dropdown.dropselect').select2();

});

<|endoftext|>


<commit_before>
// require dependencies
const eden      = require ('eden');
const mongorito = require ('mongorito');

/**
 * build model
 */
class Model extends mongorito.Model {
  /**
   * construct model entity
   *
   * @param {*} attrs
   * @param {*} options
   */
  constructor (attrs, options) {
    // run super
    super (attrs, options);

    // bind methods
    this.model = this.model.bind (this);

    // bind private attributes
    this._save = this._save.bind (this);

    // bind super private methods
    this.__model      = this.__model.bind (this);
    this.__attributes = this.__attributes.bind (this);

    // set attributes before save
    this.before ('save',   '_save');
    this.before ('remove', '_remove');
  }

  /**
   * gets model
   *
   * @param key
   * @returns {Promise}
   */
  async model (key) {
    // set let attribute
    let attr  = this.attributes[key];
    let load  = false;
    let Model = false;

    // check if is object
    if (attr === Object (attr) && attr.model && attr.id) {
      // load model
      Model = model (attr.model);

      // await model
      load = await Model.findById (attr.id);

      // set model
      this.set (key, load);
    } else if (Array.isArray (attr)) {
      // set array variable
      let arr = [];

      // loop object array
      for (var i = 0; i < attr.length; i++) {
        // check if is object
        if (attr[i] === Object (attr[i]) && attr[i].model && attr[i].id) {
          // load model
          Model = model (attr[i].model);

          // await model
          load = await Model.findById (attr[i].id);

          // set model
          if (load) arr.push (load);
        } else {
          arr.push (attr[i]);
        }
      }

      // set array
      this.set (key, arr);
    }

    // return
    return this.get (key);
  }

  /**
   * before save function
   *
   * @param next
   *
   * @private
   */
  async _save (next) {
    // check id
    if (!this.get ('_id')) {
      // hook create
      await eden.hook (this.constructor.name + '.create', this, async () => {
        // run attributes
        this.__attributes ();

        // await next
        await next;
      });
    } else {
      // hook update
      await eden.hook (this.constructor.name + '.update', this, async () => {
        // run attributes
        this.__attributes ();

        // await next
        await next;
      });
    }
  }

  /**
   * before remove function
   *
   * @param next
   *
   * @private
   */
  async _remove (next) {
    // hook create
    await eden.hook (this.constructor.name + '.remove', this, async () => {
      // await next
      await next;
    });
  }

  /**
   * check if model
   *
   * @param {*} check
   *
   * @returns {boolean}
   * @private
   */
  __model (check) {
    // check if model
    if (check && check.attributes && check.get) {
      return true;
    }
  }

  /**
   * sets attributes
   *
   * @private
   */
  __attributes () {
    // loop attributes
    for (var key in this.attributes) {
      // set let attribute
      let attr = this.attributes[key];

      // check if entity
      if (this.__model (attr)) {
        // set array for save
        this.attributes[key] = {
          'id'    : attr.get ('_id').toString (),
          'model' : attr.constructor.name
        };
      } else if (Array.isArray (attr)) {
        // set arr variable
        let arr = [];
        // loop object array
        for (var i = 0; i < attr.length; i++) {
          // check if is object
          if (this.__model (attr[i])) {
            // push to attributes array
            arr.push ({
              'id'    : attr[i].get ('_id').toString (),
              'model' : attr[i].constructor.name
            });
          } else {
            // push to attributes array
            arr.push (attr[i]);
          }
        }

        // set array
        this.attributes[key] = arr;
      }
    }
  }
}

/**
 * export default Model class
 *
 * @type {Model}
 */
exports = module.exports = Model;
<commit_msg>amend model hook functionality<commit_after>
// require dependencies
const eden      = require ('eden');
const mongorito = require ('mongorito');

/**
 * build model
 */
class Model extends mongorito.Model {
  /**
   * construct model entity
   *
   * @param {*} attrs
   * @param {*} options
   */
  constructor (attrs, options) {
    // run super
    super (attrs, options);

    // bind methods
    this.model = this.model.bind (this);

    // bind private attributes
    this._save = this._save.bind (this);

    // bind super private methods
    this.__model      = this.__model.bind (this);
    this.__attributes = this.__attributes.bind (this);

    // set attributes before save
    this.before ('save',   '_save');
    this.before ('remove', '_remove');
  }

  /**
   * gets model
   *
   * @param key
   * @returns {Promise}
   */
  async model (key) {
    // set let attribute
    let attr  = this.attributes[key];
    let load  = false;
    let Model = false;

    // check if is object
    if (attr === Object (attr) && attr.model && attr.id) {
      // load model
      Model = model (attr.model);

      // await model
      load = await Model.findById (attr.id);

      // set model
      this.set (key, load);
    } else if (Array.isArray (attr)) {
      // set array variable
      let arr = [];

      // loop object array
      for (var i = 0; i < attr.length; i++) {
        // check if is object
        if (attr[i] === Object (attr[i]) && attr[i].model && attr[i].id) {
          // load model
          Model = model (attr[i].model);

          // await model
          load = await Model.findById (attr[i].id);

          // set model
          if (load) arr.push (load);
        } else {
          arr.push (attr[i]);
        }
      }

      // set array
      this.set (key, arr);
    }

    // return
    return this.get (key);
  }

  /**
   * before save function
   *
   * @param next
   *
   * @private
   */
  async _save (next) {
    // run attributes
    this.__attributes ();

    // check id
    if (!this.get ('_id')) {
      // hook create
      await eden.hook (this.constructor.name + '.create', this, async () => {
        // await next
        await next;
      });
    } else {
      // hook update
      await eden.hook (this.constructor.name + '.update', this, async () => {
        // await next
        await next;
      });
    }
  }

  /**
   * before remove function
   *
   * @param next
   *
   * @private
   */
  async _remove (next) {
    // hook create
    await eden.hook (this.constructor.name + '.remove', this, async () => {
      // await next
      await next;
    });
  }

  /**
   * check if model
   *
   * @param {*} check
   *
   * @returns {boolean}
   * @private
   */
  __model (check) {
    // check if model
    if (check && check.attributes && check.get) {
      return true;
    }
  }

  /**
   * sets attributes
   *
   * @private
   */
  __attributes () {
    // loop attributes
    for (var key in this.attributes) {
      // set let attribute
      let attr = this.attributes[key];

      // check if entity
      if (this.__model (attr)) {
        // set array for save
        this.attributes[key] = {
          'id'    : attr.get ('_id').toString (),
          'model' : attr.constructor.name
        };
      } else if (Array.isArray (attr)) {
        // set arr variable
        let arr = [];
        // loop object array
        for (var i = 0; i < attr.length; i++) {
          // check if is object
          if (this.__model (attr[i])) {
            // push to attributes array
            arr.push ({
              'id'    : attr[i].get ('_id').toString (),
              'model' : attr[i].constructor.name
            });
          } else {
            // push to attributes array
            arr.push (attr[i]);
          }
        }

        // set array
        this.attributes[key] = arr;
      }
    }
  }
}

/**
 * export default Model class
 *
 * @type {Model}
 */
exports = module.exports = Model;
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
<commit_msg>removed line in application.js<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .

alert('foo');<commit_msg>Remove alert<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
<|endoftext|>