<commit_before>
export default {

	PREFIX: /data-o-|o-/,
	ROOT: /^(https?:)?\/?\//,

	DOT: /\.+/,
	PIPE: /\s?\|\s?/,
	PIPES: /\s?,\s?|\s+/,
	VARIABLE_START: '(^|(\\|+|\\,+|\\s))',
	VARIABLE_END: '(?:)',
	// VARIABLE_END: '([^a-zA-z1-9]|$)',

	binderNames (data) {
		data = data.split(this.PREFIX)[1];
		return data ? data.split('-') : [];
	},

	binderValues (data) {
		data = data.split(this.PIPE)[0];
		return data ? data.split('.') : [];
	},

	binderPipes (data) {
		data = data.split(this.PIPE)[1];
		return data ? data.split(this.PIPES) : [];
	},

	ensureElement (data) {
		data.query = data.query || '';
		data.scope = data.scope || document.body;

		let element = data.scope.querySelector(`${data.name}${data.query}`);

		if (!element) {
			element = document.createElement(data.name);

			if (data.position === 'afterbegin') {
				data.scope.insertBefore(element, data.scope.firstChild);
			} else if (data.position === 'beforeend') {
				data.scope.appendChild(element);
			} else {
				data.scope.appendChild(element);
			}

		}

		for (let attribute of data.attributes) {
			element.setAttribute(attribute.name, attribute.value);
		}

		return element;
	},

	formData (form, model) {
		let elements = form.querySelectorAll('[o-value]');
		let data = {};

		for (let i = 0, l = elements.length; i < l; i++) {
			let element = elements[i];

			if (element.nodeName === 'OPTION') continue;

			let value = element.getAttribute('o-value');

			if (!value) continue;

			let values = this.binderValues(value);

			data[values[values.length-1]] = this.getByPath(model, values);
		}

		return data;
	},

	formReset (form, model) {
		let elements = form.querySelectorAll('[o-value]');

		for (let i = 0, l = elements.length; i < l; i++) {
			let element = elements[i];

			if (element.nodeName === 'OPTION') continue;

			let value = element.getAttribute('o-value');

			if (!value) continue;

			let values = this.binderValues(value);

			this.setByPath(model, values, '');
		}

	},

	walker (node, callback) {
		callback(node);
		// node = node.firstElementChild;
		node = node.firstChild;
		while (node) {
		    this.walker(node, callback);
		    // node = node.nextElementSibling;
		    node = node.nextSibling;
		}
	},

	replaceEachVariable (element, variable, path, key) {
		let self = this;
		let pattern = new RegExp(this.VARIABLE_START + variable + this.VARIABLE_END, 'g');

		self.walker(element, function (node) {
			if (node.nodeType === 3) {
				if (node.nodeValue === `$${variable}` || node.nodeValue === '$index') {
					node.nodeValue = key;
				}
			} else if (node.nodeType === 1) {
				for (let i = 0, l = node.attributes.length; i < l; i++) {
					let attribute = node.attributes[i];
					if (attribute.name.indexOf('o-') === 0 || attribute.name.indexOf('data-o-') === 0) {
						attribute.value = attribute.value.replace(pattern, `$1${path}.${key}`);
						// attribute.value = attribute.value.replace(pattern, `$1${path}.${key}$2`);
					}
				}
			}
		});
	},

	traverse (data, path, callback) {
		let keys = typeof path === 'string' ? path.split('.') : path;
		let last = keys.length - 1;

		for (let i = 0; i < last; i++) {
			let key = keys[i];

			if (!(key in data)) {
				if (typeof callback === 'function') {
					callback(data, key, i, keys);
				} else {
					return undefined;
				}
			}

			data = data[key];
		}

		return {
			data: data,
			key: keys[last]
		}
	},

	setByPath (data, path, value) {
		let keys = typeof path === 'string' ? path.split('.') : path;
		let last = keys.length - 1;

		for (let i = 0; i < last; i++) {
			let key = keys[i];

			if (!(key in data)) {

				if (isNaN(keys[i+1])) {
					data[key] = {};
				} else {
					data[key] = [];
				}

			}

			data = data[key];
		}

		return data[keys[last]] = value;
	},

	getByPath (data, path) {
		let keys = typeof path === 'string' ? path.split('.') : path;
		let last = keys.length - 1;

		for (let i = 0; i < last; i++) {
			let key = keys[i];

			if (!(key in data)) {
				return undefined;
			} else {
				data = data[key];
			}

		}

		return data[keys[last]];
	},

	joinDot () {
		return Array.prototype.join
			.call(arguments, '.')
			.replace(/\.{2,}/g, '.');
	},

	// getScope (element) {
	//
	// 	if (!element) {
	// 		return;
	// 	}
	//
	// 	if (element.hasAttribute('o-scope') || element.hasAttribute('data-o-scope')) {
	// 		return element;
	// 	}
	//
	// 	if (element.parentNode) {
	// 		return this.getScope(element.parentNode);
	// 	}
	//
	// 	// console.warn('Oxe.utility - could not find container scope');
	// },

	ready (callback) {
		if (callback) {
			if (document.readyState !== 'interactive' && document.readyState !== 'complete') {
				document.addEventListener('DOMContentLoaded', function _ () {
					callback();
					document.removeEventListener('DOMContentLoaded', _);
				}, true);
			} else {
				callback();
			}
		}
	}

}
<commit_msg>changed to normal for loop<commit_after>
export default {

	PREFIX: /data-o-|o-/,
	ROOT: /^(https?:)?\/?\//,

	DOT: /\.+/,
	PIPE: /\s?\|\s?/,
	PIPES: /\s?,\s?|\s+/,
	VARIABLE_START: '(^|(\\|+|\\,+|\\s))',
	VARIABLE_END: '(?:)',
	// VARIABLE_END: '([^a-zA-z1-9]|$)',

	binderNames (data) {
		data = data.split(this.PREFIX)[1];
		return data ? data.split('-') : [];
	},

	binderValues (data) {
		data = data.split(this.PIPE)[0];
		return data ? data.split('.') : [];
	},

	binderPipes (data) {
		data = data.split(this.PIPE)[1];
		return data ? data.split(this.PIPES) : [];
	},

	ensureElement (data) {
		data.query = data.query || '';
		data.scope = data.scope || document.body;

		let element = data.scope.querySelector(`${data.name}${data.query}`);

		if (!element) {
			element = document.createElement(data.name);

			if (data.position === 'afterbegin') {
				data.scope.insertBefore(element, data.scope.firstChild);
			} else if (data.position === 'beforeend') {
				data.scope.appendChild(element);
			} else {
				data.scope.appendChild(element);
			}

		}

		for (let i = 0, l = data.attributes.length; i < l; i++) {
			let attribute = data.attributes[i];
			element.setAttribute(attribute.name, attribute.value);
		}

		return element;
	},

	formData (form, model) {
		let elements = form.querySelectorAll('[o-value]');
		let data = {};

		for (let i = 0, l = elements.length; i < l; i++) {
			let element = elements[i];

			if (element.nodeName === 'OPTION') continue;

			let value = element.getAttribute('o-value');

			if (!value) continue;

			let values = this.binderValues(value);

			data[values[values.length-1]] = this.getByPath(model, values);
		}

		return data;
	},

	formReset (form, model) {
		let elements = form.querySelectorAll('[o-value]');

		for (let i = 0, l = elements.length; i < l; i++) {
			let element = elements[i];

			if (element.nodeName === 'OPTION') continue;

			let value = element.getAttribute('o-value');

			if (!value) continue;

			let values = this.binderValues(value);

			this.setByPath(model, values, '');
		}

	},

	walker (node, callback) {
		callback(node);
		// node = node.firstElementChild;
		node = node.firstChild;
		while (node) {
		    this.walker(node, callback);
		    // node = node.nextElementSibling;
		    node = node.nextSibling;
		}
	},

	replaceEachVariable (element, variable, path, key) {
		let self = this;
		let pattern = new RegExp(this.VARIABLE_START + variable + this.VARIABLE_END, 'g');

		self.walker(element, function (node) {
			if (node.nodeType === 3) {
				if (node.nodeValue === `$${variable}` || node.nodeValue === '$index') {
					node.nodeValue = key;
				}
			} else if (node.nodeType === 1) {
				for (let i = 0, l = node.attributes.length; i < l; i++) {
					let attribute = node.attributes[i];
					if (attribute.name.indexOf('o-') === 0 || attribute.name.indexOf('data-o-') === 0) {
						attribute.value = attribute.value.replace(pattern, `$1${path}.${key}`);
						// attribute.value = attribute.value.replace(pattern, `$1${path}.${key}$2`);
					}
				}
			}
		});
	},

	traverse (data, path, callback) {
		let keys = typeof path === 'string' ? path.split('.') : path;
		let last = keys.length - 1;

		for (let i = 0; i < last; i++) {
			let key = keys[i];

			if (!(key in data)) {
				if (typeof callback === 'function') {
					callback(data, key, i, keys);
				} else {
					return undefined;
				}
			}

			data = data[key];
		}

		return {
			data: data,
			key: keys[last]
		}
	},

	setByPath (data, path, value) {
		let keys = typeof path === 'string' ? path.split('.') : path;
		let last = keys.length - 1;

		for (let i = 0; i < last; i++) {
			let key = keys[i];

			if (!(key in data)) {

				if (isNaN(keys[i+1])) {
					data[key] = {};
				} else {
					data[key] = [];
				}

			}

			data = data[key];
		}

		return data[keys[last]] = value;
	},

	getByPath (data, path) {
		let keys = typeof path === 'string' ? path.split('.') : path;
		let last = keys.length - 1;

		for (let i = 0; i < last; i++) {
			let key = keys[i];

			if (!(key in data)) {
				return undefined;
			} else {
				data = data[key];
			}

		}

		return data[keys[last]];
	},

	joinDot () {
		return Array.prototype.join
			.call(arguments, '.')
			.replace(/\.{2,}/g, '.');
	},

	// getScope (element) {
	//
	// 	if (!element) {
	// 		return;
	// 	}
	//
	// 	if (element.hasAttribute('o-scope') || element.hasAttribute('data-o-scope')) {
	// 		return element;
	// 	}
	//
	// 	if (element.parentNode) {
	// 		return this.getScope(element.parentNode);
	// 	}
	//
	// 	// console.warn('Oxe.utility - could not find container scope');
	// },

	ready (callback) {
		if (callback) {
			if (document.readyState !== 'interactive' && document.readyState !== 'complete') {
				document.addEventListener('DOMContentLoaded', function _ () {
					callback();
					document.removeEventListener('DOMContentLoaded', _);
				}, true);
			} else {
				callback();
			}
		}
	}

}
<|endoftext|>


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

/**
 * @fileoverview Controllers for the exploration statistics tab in the exploration editor.
 *
 * @author sll@google.com (Sean Lip)
 */

oppia.controller('ExplorationStatistics', [
    '$scope', '$http', '$modal', 'warningsData', 'explorationStatesService', 'explorationData',
    'graphDataService', 'oppiaDatetimeFormatter',
    function($scope, $http, $modal, warningsData, explorationStatesService, explorationData,
             graphDataService, oppiaDatetimeFormatter) {
  $scope.COMPLETION_RATE_CHART_OPTIONS = {
    chartAreaWidth: 300,
    colors: ['green', 'firebrick'],
    height: 100,
    legendPosition: 'right',
    width: 500
  };

  $scope.getLocaleStringForDatetime = function(millisSinceEpoch) {
    return oppiaDatetimeFormatter.getLocaleString(millisSinceEpoch);
  };

  $scope.hasTabLoaded = false;
  $scope.$on('refreshStatisticsTab', function(evt) {
    $scope.refreshExplorationStatistics();
  });

  $scope.hasExplorationBeenVisited = false;
  $scope.refreshExplorationStatistics = function() {
    $scope.explorationStatisticsUrl = '/createhandler/statistics/' + explorationData.explorationId;
    $http.get($scope.explorationStatisticsUrl).then(function(response) {
      $scope.graphData = graphDataService.getGraphData();

      var data = response.data;
      var numVisits = data.num_starts;
      var numCompletions = data.num_completions;
      var improvements = data.improvements;
      $scope.stateStats = data.state_stats;
      $scope.lastUpdated = data.last_updated;

      if (numVisits > 0) {
        $scope.hasExplorationBeenVisited = true;
      }

      $scope.chartData = [
        ['', 'Completions', 'Non-completions'],
        ['', numCompletions, numVisits - numCompletions]
      ];

      $scope.statsGraphOpacities = {
        legend: 'Students entering state'
      };
      for (var stateName in explorationStatesService.getStates()) {
        var visits = $scope.stateStats[stateName].firstEntryCount;
        $scope.statsGraphOpacities[stateName] = Math.max(
          visits / numVisits, 0.05);
      }
      $scope.statsGraphOpacities[END_DEST] = Math.max(
        numCompletions / numVisits, 0.05);

      $scope.highlightStates = {};
      improvements.forEach(function(impItem) {
        if (impItem.type == 'default') {
          $scope.highlightStates[impItem.state_name] = 'Needs more feedback';
        } else if (impItem.type == 'incomplete') {
          $scope.highlightStates[impItem.state_name] = 'May be confusing';
        }
      });

      $scope.hasTabLoaded = true;
    });
  };

  $scope.onClickStateInStatsGraph = function(stateName) {
    if (stateName !== END_DEST) {
      $scope.showStateStatsModal(stateName, $scope.highlightStates[stateName]);
    }
  };

  $scope.showStateStatsModal = function(stateName, improvementType) {
    warningsData.clear();

    $http.get(
      '/createhandler/state_rules_stats/' + $scope.explorationId + '/' + encodeURIComponent(stateName)
    ).then(function(response) {
      $modal.open({
        templateUrl: 'modals/stateStats',
        backdrop: 'static',
        resolve: {
          stateName: function() {
            return stateName;
          },
          stateStats: function() {
            return $scope.stateStats[stateName];
          },
          improvementType: function() {
            return improvementType;
          },
          rulesStats: function() {
            return response.data.rules_stats;
          }
        },
        controller: [
          '$scope', '$modalInstance', 'stateName',
          'stateStats', 'improvementType', 'rulesStats', function(
             $scope, $modalInstance, stateName,
             stateStats, improvementType, rulesStats) {
          $scope.stateName = stateName;
          $scope.stateStats = stateStats;
          $scope.improvementType = improvementType;
          $scope.rulesStats = rulesStats;

          $scope.getNumTimesString = function(numberOfTimes) {
            var suffix = (numberOfTimes == 1 ? ' time' : ' times');
            return numberOfTimes + suffix;
          };

          $scope.getHumanReadableRuleName = function(ruleName) {
            return ruleName.substring('submit.'.length);
          };

          $scope.isEmpty = function(obj) {
            for (var property in obj) {
              if (obj.hasOwnProperty(property)) {
                return false;
              }
            }
            return true;
          };

          $scope.doesAnswerExist = function() {
            for (var rule in $scope.rulesStats) {
              if ($scope.rulesStats[rule].answers.length > 0) {
                return true;
              }
            }
            return false;
          };

          $scope.cancel = function() {
            $modalInstance.dismiss('cancel');
            warningsData.clear();
          };
        }]
      });
    });
  };
}]);
<commit_msg>Fix merge error.<commit_after>// Copyright 2014 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Controllers for the exploration statistics tab in the exploration editor.
 *
 * @author sll@google.com (Sean Lip)
 */

oppia.controller('ExplorationStatistics', [
    '$scope', '$http', '$modal', 'warningsData', 'explorationStatesService', 'explorationData',
    'graphDataService', 'oppiaDatetimeFormatter',
    function($scope, $http, $modal, warningsData, explorationStatesService, explorationData,
             graphDataService, oppiaDatetimeFormatter) {
  $scope.COMPLETION_RATE_CHART_OPTIONS = {
    chartAreaWidth: 300,
    colors: ['green', 'firebrick'],
    height: 100,
    legendPosition: 'right',
    width: 500
  };

  $scope.getLocaleStringForDatetime = function(millisSinceEpoch) {
    return oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString(millisSinceEpoch);
  };

  $scope.hasTabLoaded = false;
  $scope.$on('refreshStatisticsTab', function(evt) {
    $scope.refreshExplorationStatistics();
  });

  $scope.hasExplorationBeenVisited = false;
  $scope.refreshExplorationStatistics = function() {
    $scope.explorationStatisticsUrl = '/createhandler/statistics/' + explorationData.explorationId;
    $http.get($scope.explorationStatisticsUrl).then(function(response) {
      $scope.graphData = graphDataService.getGraphData();

      var data = response.data;
      var numVisits = data.num_starts;
      var numCompletions = data.num_completions;
      var improvements = data.improvements;
      $scope.stateStats = data.state_stats;
      $scope.lastUpdated = data.last_updated;

      if (numVisits > 0) {
        $scope.hasExplorationBeenVisited = true;
      }

      $scope.chartData = [
        ['', 'Completions', 'Non-completions'],
        ['', numCompletions, numVisits - numCompletions]
      ];

      $scope.statsGraphOpacities = {
        legend: 'Students entering state'
      };
      for (var stateName in explorationStatesService.getStates()) {
        var visits = $scope.stateStats[stateName].firstEntryCount;
        $scope.statsGraphOpacities[stateName] = Math.max(
          visits / numVisits, 0.05);
      }
      $scope.statsGraphOpacities[END_DEST] = Math.max(
        numCompletions / numVisits, 0.05);

      $scope.highlightStates = {};
      improvements.forEach(function(impItem) {
        if (impItem.type == 'default') {
          $scope.highlightStates[impItem.state_name] = 'Needs more feedback';
        } else if (impItem.type == 'incomplete') {
          $scope.highlightStates[impItem.state_name] = 'May be confusing';
        }
      });

      $scope.hasTabLoaded = true;
    });
  };

  $scope.onClickStateInStatsGraph = function(stateName) {
    if (stateName !== END_DEST) {
      $scope.showStateStatsModal(stateName, $scope.highlightStates[stateName]);
    }
  };

  $scope.showStateStatsModal = function(stateName, improvementType) {
    warningsData.clear();

    $http.get(
      '/createhandler/state_rules_stats/' + $scope.explorationId + '/' + encodeURIComponent(stateName)
    ).then(function(response) {
      $modal.open({
        templateUrl: 'modals/stateStats',
        backdrop: 'static',
        resolve: {
          stateName: function() {
            return stateName;
          },
          stateStats: function() {
            return $scope.stateStats[stateName];
          },
          improvementType: function() {
            return improvementType;
          },
          rulesStats: function() {
            return response.data.rules_stats;
          }
        },
        controller: [
          '$scope', '$modalInstance', 'stateName',
          'stateStats', 'improvementType', 'rulesStats', function(
             $scope, $modalInstance, stateName,
             stateStats, improvementType, rulesStats) {
          $scope.stateName = stateName;
          $scope.stateStats = stateStats;
          $scope.improvementType = improvementType;
          $scope.rulesStats = rulesStats;

          $scope.getNumTimesString = function(numberOfTimes) {
            var suffix = (numberOfTimes == 1 ? ' time' : ' times');
            return numberOfTimes + suffix;
          };

          $scope.getHumanReadableRuleName = function(ruleName) {
            return ruleName.substring('submit.'.length);
          };

          $scope.isEmpty = function(obj) {
            for (var property in obj) {
              if (obj.hasOwnProperty(property)) {
                return false;
              }
            }
            return true;
          };

          $scope.doesAnswerExist = function() {
            for (var rule in $scope.rulesStats) {
              if ($scope.rulesStats[rule].answers.length > 0) {
                return true;
              }
            }
            return false;
          };

          $scope.cancel = function() {
            $modalInstance.dismiss('cancel');
            warningsData.clear();
          };
        }]
      });
    });
  };
}]);
<|endoftext|>


<commit_before>// Time is component 3
//lNB: Shape is four dimensional,
// if you draw it moving and not with the front/back in the right time as well as place, it won't be the correct shape.

function extendedObject(X, P, m, options, shape, timeStep)
{
    this.options = options;
    this.isInteresting = true;
    this.shapePoints = [];
    this.pastPoints = [];
    this.pastRadialV = [];

    this.temp = 5000;
    this.stillColor = tempToColor(this.temp);

    if (options.interestingPts) {
        this.interestingPts = options.interestingPts;
    }

    this.COM = new inertialObject(X, P, 1);
    this.COM.init(timeStep);
    this.uDisplacement = quat4.create([0,0,0,0]);
    this.pointPos = [];

    // Make a rectangular prism which, when placed at the position or view pos
    // of COM, must always contain part of the object.
    this.boundingBox = [0, 0, 0, 0, 0, 0];
    this.initialBoost = cBoostMat([-this.COM.V[0],
                                   -this.COM.V[1],
                                   -this.COM.V[2],
                                    this.COM.V[3]], c);

    for (var i = 0; i < (shape.length - 1); i++)
    {
        for(var j = 0; j < 3; j++)
        {
            this.boundingBox[2 * j]     = Math.min(shape[i][j], shape[i+1][1]);
            this.boundingBox[2 * j + 1] = Math.max(shape[i][j], shape[i+1][j]);
        }
        this.shapePoints[i] = quat4.create(mat4.multiplyVec4(this.initialBoost, shape[i], tempQuat4));
        this.pastPoints[i] = quat4.create([0,0,0,0]);
        this.pointPos[i] = quat4.create([0,0,0,0]);
    }

    this.shapePoints[shape.length - 1] = quat4.create(
        mat4.multiplyVec4(this.initialBoost, shape[shape.length - 1], tempQuat4));
    this.pointPos[shape.length - 1] = quat4.create([0,0,0,0]);
    this.pastPoints[shape.length - 1] = quat4.create([0,0,0,0]);
}

/**
 * Update the COM and the surrounding points.
 * This is the most braindead way of doing it, huge amounts of redundant
 * data/calculations, but it saves duplicating code.
 */
extendedObject.prototype.update = function(timeStep)
{
    this.COM.updateX0(timeStep);
    this.COM.calcPast();
    for (var i = 0; i < (this.shapePoints.length); i++) {
        quat4.add(this.COM.X0, this.shapePoints[i], this.pointPos[i]);
        quat4.scale(this.COM.V, -this.pointPos[i][3] / this.COM.V[3], tempQuat4);
        quat4.add(this.pointPos[i], tempQuat4, this.pointPos[i]);
    }
    this.calcPastPoints();
}

extendedObject.prototype.wasInView2D = function()
{
    return (this.options.showVisualPos &&
            ((this.COM.XView[1] - this.boundingBox[0]) / scene.zoom < (scene.width - scene.origin[0] + 10) &&
             (this.COM.XView[1] - this.boundingBox[1]) / scene.zoom < (- scene.origin[1] - 10) &&
            (this.COM.XView[2] - this.boundingBox[3]) / scene.zoom < (scene.height - scene.origin[0] + 10) &&
             (this.COM.XView[1] - this.boundingBox[1]) / scene.zoom < (- scene.origin[1] - 10)) &&
             (Math.abs(this.boundingBox[0] - this.boundingBox[1]) / zoom > 1    ||
            Math.abs(this.boundingBox[2] - this.boundingBox[3]) / zoom > 1)
            );
}

extendedObject.prototype.isInView2D = function()
{
    return (this.options.showVisualPos &&
            ((this.COM.X0[1] - this.boundingBox[0]) / scene.zoom < (scene.width - scene.origin[0] + 10) &&
             (this.COM.X0[1] - this.boundingBox[1]) / scene.zoom < (- scene.origin[1] - 10) &&
             (this.COM.X0[2] - this.boundingBox[3]) / scene.zoom < (scene.height - scene.origin[0] + 10) &&
             (this.COM.X0[1] - this.boundingBox[1]) / scene.zoom < (- scene.origin[1] - 10)) &&
             (Math.abs(this.boundingBox[0] - this.boundingBox[1]) / zoom > 1    ||
            Math.abs(this.boundingBox[2] - this.boundingBox[3]) / zoom > 1)
            );
}

extendedObject.prototype.changeFrame = function(translation, rotation)
{
    this.COM.changeFrame(translation, rotation);
    for (var i = 0; i < this.shapePoints.length; i++)
    {
        this.shapePoints[i] = mat4.multiplyVec4(rotation, this.shapePoints[i]);
    }
}

extendedObject.prototype.drawNow = function()
{
    if (this.isInteresting || true)
    {
        scene.g.strokeStyle = "#0f0";
        scene.g.fillStyle = "#0f0";
        scene.g.beginPath();
        scene.g.moveTo(this.pointPos[0][0] / scene.zoom + scene.origin[0],
                       this.pointPos[0][1] / scene.zoom + scene.origin[1]);
        for (var i = 0; i < (this.shapePoints.length); i++)
        {
            scene.g.lineTo(this.pointPos[i][0] / scene.zoom + scene.origin[0],
                           this.pointPos[i][1] / scene.zoom + scene.origin[1]);
        }

        scene.g.stroke();

        if (this.options.showVelocities) {
            scene.g.fillText("v = " + (Math.round(1000 * Math.sqrt(1-1/Math.pow(this.COM.V[3] / c, 2)))/1000) + "c", this.COM.X0[0] / scene.zoom + scene.origin[0],
                             this.COM.X0[1] / scene.zoom + scene.origin[1] + 20);
        }
        if (this.options.showGamma) {
            scene.g.fillText("γ = " + (Math.round(1000 * this.COM.V[3] / c)) / 1000, this.COM.X0[0] / scene.zoom + scene.origin[0],
                             this.COM.X0[1] / scene.zoom + scene.origin[1] - 20);
        }
    }
}

/**
 * Note these methods assume no acceleration
 */
extendedObject.prototype.calcPastPoints = function()
{
    var radialV;
    var radialDist;
    var viewTime;
    for (var i = 0; i < (this.shapePoints.length); i++)
    {
        var vDotv = quat4.spaceDot(this.COM.V, this.COM.V) / Math.pow(this.COM.V[3] / c, 2);
        var xDotx = quat4.spaceDot(this.pointPos[i], this.pointPos[i]);
        var vDotx = quat4.spaceDot(this.pointPos[i], this.COM.V) / this.COM.V[3] * c;
        var a = c*c - vDotv;

        viewTime = -(vDotx - Math.sqrt(Math.pow(vDotx, 2) + a * xDotx)) / a;
        quat4.scale(this.COM.V, viewTime / this.COM.V[3] * c, this.uDisplacement);
        quat4.subtract(this.pointPos[i], this.uDisplacement, this.pastPoints[i]);

        this.pastRadialV[i] = (quat4.spaceDot(this.pastPoints[i], this.COM.V) /
                                Math.max(Math.sqrt(Math.abs(quat4.spaceDot(
                                this.pastPoints[i], this.pastPoints[i])
                                )), 1e-16) / this.COM.V[3] * c);
    }
}

extendedObject.prototype.drawPast = function(scene)
{
    if (this.isInteresting || true)
    {
        var doDoppler = (scene.alwaysDoppler ||
                         (!scene.neverDoppler && this.options.showDoppler));
        if(doDoppler) {
            scene.g.strokeStyle = tempToColor(dopplerShiftColor(this.temp,
                                                                this.pastRadialV[0],
                                                                this.COM.V[3] / c));
        } else {
            scene.g.strokeStyle = this.stillColor;
        }

        scene.g.beginPath();
        scene.g.moveTo(this.pastPoints[0][0] / scene.zoom + scene.origin[0],
                       this.pastPoints[0][1] / scene.zoom + scene.origin[1]);

        for (var i = 1; i < (this.pastPoints.length); i++)
        {
            if(doDoppler) {
                scene.g.strokeStyle = tempToColor(dopplerShiftColor(this.temp,
                                                                    this.pastRadialV[i],
                                                                    this.COM.V[3] / c));
            }
            scene.g.beginPath();
            scene.g.moveTo(this.pastPoints[i-1][0] / scene.zoom + scene.origin[0],
                           this.pastPoints[i-1][1] / scene.zoom + scene.origin[1]);
            scene.g.lineTo(this.pastPoints[i][0] / scene.zoom + scene.origin[0],
                           this.pastPoints[i][1] / scene.zoom + scene.origin[1]);
            scene.g.stroke();
        }
    }
}

extendedObject.prototype.draw = function(scene)
{
    if (this.options.showVisualPos)
        this.drawPast(scene);
    if (this.options.showFramePos)
        this.drawNow(scene);
}

extendedObject.prototype.drawXT = function(scene)
{
    var xvis = this.COM.X0[0] / scene.zoom;
    var tvis = this.COM.X0[3] / c / scene.timeScale;
    /* Find dx/dt using chain rule.
       V[0] is dx/dtau, V[3] is dt/dtau
       thus dx/dt is V[0]/V[3].
    */
    var dxdtVis = (this.COM.V[0] ) /
                  (this.COM.V[3] / c);
    scene.h.fillStyle = "rgba(0, 256, 0, 0.5)";
    scene.h.strokeStyle = "rgba(0, 0, 0, 0.5)";

    // A blob at t=0 to represent where the object is.
    scene.h.beginPath();
    scene.h.arc(xvis + scene.origin[0],
                scene.origin[2],
                3, 0, twopi, true);
    scene.h.closePath();
    scene.h.fill();

    // A world line.
    scene.h.beginPath();
    scene.h.moveTo(xvis + scene.origin[0] +
                    scene.origin[2]*dxdtVis,
                   0);
    scene.h.lineTo(xvis + scene.origin[0] -
                    (scene.height - scene.origin[2]) * dxdtVis,
                   scene.height);
    scene.h.stroke();

    // A blob on the light cone.
    xvis = this.COM.XView[0] / scene.zoom;
    tvis = this.COM.XView[3] / c / scene.zoom;
    scene.h.fillStyle = tempToColor(dopplerShiftColor(this.temp,
                                                      this.COM.radialVPast,
                                                      this.COM.V[3] / c));

    scene.h.beginPath();
    scene.h.arc(xvis + scene.origin[0],
                -tvis + scene.origin[2],
                3, 0, twopi, true);
    scene.h.fill();

    // Some world lines of interesting parts of the object
    // Such as front or back.
    for (i in this.interestingPts) {
        xvis = this.pointPos[this.interestingPts[i]][0] / scene.zoom;
        scene.h.beginPath();
        scene.h.moveTo(xvis + scene.origin[0] -
                        scene.origin[2] * dxdtVis,
                       0);
        scene.h.lineTo(xvis + scene.origin[0] +
                        (scene.height - scene.origin[2]) * dxdtVis,
                       scene.height);
        scene.h.stroke();
    }
}
<commit_msg>Tweak for boundingBox, it's now an index. Use pointPos[boundingBox[0][i]] for min along the ith axis and  pointPos[boundingBox[1][i]] for max<commit_after>// Time is component 3
//lNB: Shape is four dimensional,
// if you draw it moving and not with the front/back in the right time as well as place, it won't be the correct shape.

function extendedObject(X, P, m, options, shape, timeStep)
{
    this.options = options;
    this.isInteresting = true;
    this.shapePoints = [];
    this.pastPoints = [];
    this.pastRadialV = [];

    this.temp = 5000;
    this.stillColor = tempToColor(this.temp);

    if (options.interestingPts) {
        this.interestingPts = options.interestingPts;
    }

    this.COM = new inertialObject(X, P, 1);
    this.COM.init(timeStep);
    this.uDisplacement = quat4.create([0,0,0,0]);
    this.pointPos = [];

    // Make a rectangular prism which, when placed at the position or view pos
    // of COM, must always contain part of the object.
    this.boundingBox = [0, 0, 0, 0, 0, 0];
    this.initialBoost = cBoostMat([-this.COM.V[0],
                                   -this.COM.V[1],
                                   -this.COM.V[2],
                                    this.COM.V[3]], c);

    for (var i = 0; i < (shape.length - 1); i++)
    {

        this.shapePoints[i] = quat4.create(mat4.multiplyVec4(this.initialBoost, shape[i], tempQuat4));
        for(var j = 0; j < 3; j++)
        {
            if (this.shapePoints[i][j] < this.boundingBox[0][j]){
                this.boundingBox[0][j] = i;
            }
            if (this.shapePoints[i][j] > this.boundingBox[0][j]){
                this.boundingBox[1][j] = i;
            }
        }
        this.pastPoints[i] = quat4.create([0,0,0,0]);
        this.pointPos[i] = quat4.create([0,0,0,0]);
    }

    this.shapePoints[shape.length - 1] = quat4.create(
        mat4.multiplyVec4(this.initialBoost, shape[shape.length - 1], tempQuat4));
    this.pointPos[shape.length - 1] = quat4.create([0,0,0,0]);
    this.pastPoints[shape.length - 1] = quat4.create([0,0,0,0]);
}

/**
 * Update the COM and the surrounding points.
 * This is the most braindead way of doing it, huge amounts of redundant
 * data/calculations, but it saves duplicating code.
 */
extendedObject.prototype.update = function(timeStep)
{
    this.COM.updateX0(timeStep);
    this.COM.calcPast();
    for (var i = 0; i < (this.shapePoints.length); i++) {
        quat4.add(this.COM.X0, this.shapePoints[i], this.pointPos[i]);
        quat4.scale(this.COM.V, -this.pointPos[i][3] / this.COM.V[3], tempQuat4);
        quat4.add(this.pointPos[i], tempQuat4, this.pointPos[i]);
    }
    this.calcPastPoints();
}

extendedObject.prototype.changeFrame = function(translation, rotation)
{
    this.COM.changeFrame(translation, rotation);
    for (var i = 0; i < this.shapePoints.length; i++)
    {
        this.shapePoints[i] = mat4.multiplyVec4(rotation, this.shapePoints[i]);
    }
}

extendedObject.prototype.drawNow = function()
{
    if (this.isInteresting || true)
    {
        scene.g.strokeStyle = "#0f0";
        scene.g.fillStyle = "#0f0";
        scene.g.beginPath();
        scene.g.moveTo(this.pointPos[0][0] / scene.zoom + scene.origin[0],
                       this.pointPos[0][1] / scene.zoom + scene.origin[1]);
        for (var i = 0; i < (this.shapePoints.length); i++)
        {
            scene.g.lineTo(this.pointPos[i][0] / scene.zoom + scene.origin[0],
                           this.pointPos[i][1] / scene.zoom + scene.origin[1]);
        }

        scene.g.stroke();

        if (this.options.showVelocities) {
            scene.g.fillText("v = " + (Math.round(1000 * Math.sqrt(1-1/Math.pow(this.COM.V[3] / c, 2)))/1000) + "c", this.COM.X0[0] / scene.zoom + scene.origin[0],
                             this.COM.X0[1] / scene.zoom + scene.origin[1] + 20);
        }
        if (this.options.showGamma) {
            scene.g.fillText("γ = " + (Math.round(1000 * this.COM.V[3] / c)) / 1000, this.COM.X0[0] / scene.zoom + scene.origin[0],
                             this.COM.X0[1] / scene.zoom + scene.origin[1] - 20);
        }
    }
}

/**
 * Note these methods assume no acceleration
 */
extendedObject.prototype.calcPastPoints = function()
{
    var radialV;
    var radialDist;
    var viewTime;
    for (var i = 0; i < (this.shapePoints.length); i++)
    {
        var vDotv = quat4.spaceDot(this.COM.V, this.COM.V) / Math.pow(this.COM.V[3] / c, 2);
        var xDotx = quat4.spaceDot(this.pointPos[i], this.pointPos[i]);
        var vDotx = quat4.spaceDot(this.pointPos[i], this.COM.V) / this.COM.V[3] * c;
        var a = c*c - vDotv;

        viewTime = -(vDotx - Math.sqrt(Math.pow(vDotx, 2) + a * xDotx)) / a;
        quat4.scale(this.COM.V, viewTime / this.COM.V[3] * c, this.uDisplacement);
        quat4.subtract(this.pointPos[i], this.uDisplacement, this.pastPoints[i]);

        this.pastRadialV[i] = (quat4.spaceDot(this.pastPoints[i], this.COM.V) /
                                Math.max(Math.sqrt(Math.abs(quat4.spaceDot(
                                this.pastPoints[i], this.pastPoints[i])
                                )), 1e-16) / this.COM.V[3] * c);
    }
}

extendedObject.prototype.drawPast = function(scene)
{
    if (this.isInteresting || true)
    {
        var doDoppler = (scene.alwaysDoppler ||
                         (!scene.neverDoppler && this.options.showDoppler));
        if(doDoppler) {
            scene.g.strokeStyle = tempToColor(dopplerShiftColor(this.temp,
                                                                this.pastRadialV[0],
                                                                this.COM.V[3] / c));
        } else {
            scene.g.strokeStyle = this.stillColor;
        }

        scene.g.beginPath();
        scene.g.moveTo(this.pastPoints[0][0] / scene.zoom + scene.origin[0],
                       this.pastPoints[0][1] / scene.zoom + scene.origin[1]);

        for (var i = 1; i < (this.pastPoints.length); i++)
        {
            if(doDoppler) {
                scene.g.strokeStyle = tempToColor(dopplerShiftColor(this.temp,
                                                                    this.pastRadialV[i],
                                                                    this.COM.V[3] / c));
            }
            scene.g.beginPath();
            scene.g.moveTo(this.pastPoints[i-1][0] / scene.zoom + scene.origin[0],
                           this.pastPoints[i-1][1] / scene.zoom + scene.origin[1]);
            scene.g.lineTo(this.pastPoints[i][0] / scene.zoom + scene.origin[0],
                           this.pastPoints[i][1] / scene.zoom + scene.origin[1]);
            scene.g.stroke();
        }
    }
}

extendedObject.prototype.draw = function(scene)
{
    if (this.options.showVisualPos)
        this.drawPast(scene);
    if (this.options.showFramePos)
        this.drawNow(scene);
}

extendedObject.prototype.drawXT = function(scene)
{
    var xvis = this.COM.X0[0] / scene.zoom;
    var tvis = this.COM.X0[3] / c / scene.timeScale;
    /* Find dx/dt using chain rule.
       V[0] is dx/dtau, V[3] is dt/dtau
       thus dx/dt is V[0]/V[3].
    */
    var dxdtVis = (this.COM.V[0] ) /
                  (this.COM.V[3] / c);
    scene.h.fillStyle = "rgba(0, 256, 0, 0.5)";
    scene.h.strokeStyle = "rgba(0, 0, 0, 0.5)";

    // A blob at t=0 to represent where the object is.
    scene.h.beginPath();
    scene.h.arc(xvis + scene.origin[0],
                scene.origin[2],
                3, 0, twopi, true);
    scene.h.closePath();
    scene.h.fill();

    // A world line.
    scene.h.beginPath();
    scene.h.moveTo(xvis + scene.origin[0] +
                    scene.origin[2]*dxdtVis,
                   0);
    scene.h.lineTo(xvis + scene.origin[0] -
                    (scene.height - scene.origin[2]) * dxdtVis,
                   scene.height);
    scene.h.stroke();

    // A blob on the light cone.
    xvis = this.COM.XView[0] / scene.zoom;
    tvis = this.COM.XView[3] / c / scene.zoom;
    scene.h.fillStyle = tempToColor(dopplerShiftColor(this.temp,
                                                      this.COM.radialVPast,
                                                      this.COM.V[3] / c));

    scene.h.beginPath();
    scene.h.arc(xvis + scene.origin[0],
                -tvis + scene.origin[2],
                3, 0, twopi, true);
    scene.h.fill();

    // Some world lines of interesting parts of the object
    // Such as front or back.
    for (i in this.interestingPts) {
        xvis = this.pointPos[this.interestingPts[i]][0] / scene.zoom;
        scene.h.beginPath();
        scene.h.moveTo(xvis + scene.origin[0] -
                        scene.origin[2] * dxdtVis,
                       0);
        scene.h.lineTo(xvis + scene.origin[0] +
                        (scene.height - scene.origin[2]) * dxdtVis,
                       scene.height);
        scene.h.stroke();
    }
}
<|endoftext|>


<commit_before>var ExportManager = function (o) {
    var self = this;
    self.selected_exports = ko.observableArray();
    self.export_type = o.export_type || "form";
    self.is_custom = o.is_custom || false;

    self.format = o.format || "csv";
    self.domain = o.domain;
    self.downloadUrl = o.downloadUrl;
    self.bulkDownloadUrl = o.bulkDownloadUrl;
    self.exportFilters = o.exportFilters;

    self.exportModal = o.modal || "#export-download-status";
    self.$modal = $(self.exportModal);
    self.exportModalLoading = o.loadingIndicator || '.loading-indicator';
    self.exportModalLoadedData = o.loadedData || '.loaded-data';

    self.bulk_download_notice_text = (self.is_custom) ?
        "Custom Form Exports" :
        "Full Form Exports";

    self.xmlns_formdesigner = o.xmlns_formdesigner || 'formdesigner';

    self.sheet_names = ko.observable(new Object());

    var resetModal = function (modal_title, newLine) {
            self.$modal.find(self.exportModalLoading).removeClass('hide');
            self.$modal.find(self.exportModalLoadedData).empty();

            var $title = self.$modal.find('.modal-header h3 span');
            $title.text(modal_title);
            if (newLine)
                $title.attr('style', 'display: block;');
            else
                $title.attr('style', '');
        },
        updateModal = function(d) {
            var autoRefresh = '';
            var pollDownloader = function () {
                if ($('#ready_'+d.download_id).length == 0) {
                    $.get(d.download_url, function(data) {
                        self.$modal.find(self.exportModalLoadedData).html(data);
                    }).error(function () {
                        self.$modal.find(self.exportModalLoading).addClass('hide');
                        self.$modal.find(self.exportModalLoadedData).html('
Oh no! Your download was unable to be completed. We have been notified and are already hard at work solving this issue.
');
                        clearInterval(autoRefresh);
                    });
                } else {
                    self.$modal.find(self.exportModalLoading).addClass('hide');
                    clearInterval(autoRefresh);
                }
            };
            $(self.exportModal).on('hide', function () {
                clearInterval(autoRefresh);
            });
            autoRefresh = setInterval(pollDownloader, 2000);
        },
        displayModalError = function(error_text) {
            var $error = $('
');
            $error.text(error_text);
            self.$modal.find(self.exportModalLoadedData).html($error);
            self.$modal.find(self.exportModalLoading).addClass('hide');
        },
        getSheetName = function(module, form, xmlns) {
            var a = module,
                b = form;
            if (!(a && b)) {
                var parts = xmlns.split('/');
                a = parts[parts.length-2];
                b = parts[parts.length-1];
                if (a===self.xmlns_formdesigner || a.indexOf('.org') > 0)
                    return b.substring(0,31);
            }
            return getFormattedSheetName(a,b);
        };

    self.updateSelectedExports = function (data, event) {
        var $checkbox = $(event.srcElement || event.currentTarget);
        var add_to_list = ($checkbox.attr('checked') === 'checked'),
            downloadButton = $checkbox.parent().parent().parent().find('.dl-export');
        if (add_to_list) {
            $checkbox.parent().find('.label').removeClass('label-info').addClass('label-success');
            self.selected_exports.push(downloadButton);
        } else {
            $checkbox.parent().find('.label').removeClass('label-success').addClass('label-info');
            self.selected_exports.splice(self.selected_exports().indexOf(downloadButton), 1);
        }
    };

    self.downloadExport = function(downloadUrl) {
        var displayDownloadError = function (response) {
            displayModalError('Sorry, something unexpected went wrong and your download ' +
                'could not be completed. Please try again and report an issue if the problem ' +
                'persists.'
            );
        };
        $.ajax({
            dataType: 'json',
            url: downloadUrl,
            success: updateModal,
            error: displayDownloadError
        });
    };
    self.requestBulkDownload = function(data, event) {
        resetModal("Bulk "+self.bulk_download_notice_text, false);
        var prepareExport = new Object();
        if (self.is_custom)
            prepareExport = new Array();

        for (var i in self.selected_exports()) {
            var curExpButton = self.selected_exports()[i];

            var _id = curExpButton.data('appid') || curExpButton.data('exportid'),
                xmlns = curExpButton.data('xmlns'),
                module = curExpButton.data('modulename'),
                export_type = curExpButton.data('exporttype'),
                form = curExpButton.data('formname');

            var sheetName = "sheet";
            if (self.is_custom) {
                var $sheetNameElem = curExpButton.parent().parent().find('.sheetname');
                if($sheetNameElem.data('duplicate'))
                    break;
                sheetName = curExpButton.parent().parent().find('.sheetname').val();
            } else
                sheetName = getSheetName(module, form, xmlns);

            var export_tag;
            if (self.is_custom)
                export_tag = {
                    domain: self.domain,
                    xmlns: xmlns,
                    sheet_name: sheetName,
                    export_id: _id,
                    export_type: export_type
                };
            else
                export_tag = [self.domain, xmlns, sheetName];

            if (!_id)
                _id = "unknown_application";

            if (self.is_custom)
                prepareExport.push(export_tag);
            else {
                if (!prepareExport.hasOwnProperty(_id))
                    prepareExport[_id] = new Array();
                prepareExport[_id].push(export_tag);
            }
        }

        if (self.is_custom && prepareExport.length == 0) {
            displayModalError('No valid sheets were available for Custom Bulk Export. Please check for duplicate sheet names.');
            return;
        }

        var downloadUrl = self.bulkDownloadUrl +
            "?"+self.exportFilters +
            "&export_tags="+encodeURIComponent(JSON.stringify(prepareExport)) +
            "&is_custom="+self.is_custom +
            "&async=true";

        self.downloadExport(downloadUrl);
    };

    self._requestDownload = function(options) {
        var $button = $(event.srcElement || event.currentTarget);
        var downloadUrl = self.downloadUrl || $button.data('dlocation');
        resetModal("'" + options.modalTitle + "'", true);
        downloadUrl = downloadUrl +
            "?" + self.exportFilters +
            '&async=true' +
            '&format=' + self.format +
            '&export_tag=["'+self.domain+'","'+$button.data('xmlns')+'","'+$button.data('formname')+'"]' +
            '&filename='+$button.data('formname');

        for (var k in options.downloadParams) {
            if (options.downloadParams.hasOwnProperty(k)) {
                var v = options.downloadParams[k];
                downloadUrl += '&' + k + '=' + v;
            }
        }
        self.downloadExport(downloadUrl);
    };

    self.requestDownload = function(data, event) {
        var $button = $(event.srcElement || event.currentTarget);
        var modalTitle = $button.data('formname') || $button.data('xmlns');
        if ($button.data('modulename')) {
            modalTitle  = $button.data('modulename') + " > " + modalTitle;
        }
        var downloadParams = {
            export_tag: ["'+self.domain+'","'+$button.data('xmlns')+'","'+$button.data('formname')+'"],
            filename: $button.data('formname')
        }
        if (!self.is_custom) {
            downloadParams.app_id = $button.data('appid');
        }
        return self._requestDownload({
            modalTitle: modalTitle,
            downloadParams: downloadParams
        });
    };

    self.requestCaseDownload = function(data, event) {
        return self._requestDownload({
            modalTitle: "Case List",
            downloadParams: {
                include_closed: $('#include-closed-select').val()
            }
        });
    };

    self.checkCustomSheetNameLength = function(data, event) {
        var src = event.srcElement || event.currentTarget;
        var $input = $(src);
        var valLength = $input.val().length;
        return (valLength < 31 || event.keyCode == 8 || (src.selectionEnd-src.selectionStart) > 0);
    };

    self.updateCustomSheetNameCharacterCount = function (data, event) {
        var $input = $(event.srcElement || event.currentTarget);
        if ($input.data('exportid')) {
            var new_names = self.sheet_names();
            new_names[$input.data('exportid')] = $input.val();
            self.sheet_names(new_names);
        }
        $input.parent().find('.sheetname-count').text($input.val().length);
        return true;
    };

    self.toggleSelectAllExports = function (data, event) {
        var $toggleBtn = $(event.srcElement || event.currentTarget),
            check_class = (self.is_custom) ? '.select-custom' : '.select-bulk';
        if ($toggleBtn.data('all'))
            $.each($(check_class), function () {
                $(this).attr('checked', true);
                self.updateSelectedExports({}, {srcElement: this})
            });
        else
            $.each($(check_class), function () {
                $(this).attr('checked', false);
                self.updateSelectedExports({}, {srcElement: this})
            });
    };

},
    getFormattedSheetName = function (a, b) {
        b = b.substr(0, 14);
        a = a.substr(0,28-b.length);
        return a+" > "+b;
    };

ko.bindingHandlers.showBulkExportNotice = {
    update: function(element, valueAccessor) {
        var value = valueAccessor()();
        if (value.length > 0)
            $(element).fadeIn();
        else
            $(element).fadeOut();
    }
};

ko.bindingHandlers.checkForUniqueSheetName = {
    update: function(element, valueAccessor) {
        var value = valueAccessor()(),
            current_name = $(element).val(),
            $dupeNotice = $(element).parent().find('.sheetname-duplicate'),
            $parentCol = $(element).parent().parent();
        var all_names = _.toArray(value);
        if( (_.lastIndexOf(all_names, current_name) - _.indexOf(all_names, current_name)) > 0) {
            $dupeNotice.removeClass('hide');
            $parentCol.addClass('error');
            $(element).data('duplicate', true);
        } else {
            $dupeNotice.addClass('hide');
            $parentCol.removeClass('error');
            $(element).data('duplicate', false);
        }
    }
};

ko.bindingHandlers.updateCustomSheetName = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor()(),
            originalName = $(element).val(),
            MAX_LENGTH = 31,
            SPLIT_CHAR = '>';

        if (originalName.indexOf(SPLIT_CHAR) > 0 && originalName.length > MAX_LENGTH) {
            // intelligently generate a sheetname
            var splitName = originalName.split(SPLIT_CHAR);
            var formname = splitName[splitName.length-1].trim(),
                modulename = splitName[splitName.length-2].trim();
            originalName = getFormattedSheetName(modulename, formname);
            $(element).val(originalName);
        }

        if (originalName.length > MAX_LENGTH) {
            $(element).val(originalName.substring(Math.max(0, originalName.length-MAX_LENGTH),originalName.length));
        } else {
            $(element).parent().find('.sheetname-count').text(originalName.length);
        }

    },
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor()(),
            allSheetNames = allBindingsAccessor().checkForUniqueSheetName;
        var $parentRow = $(element).parent().parent().parent(),
            exportID = $(element).data('exportid');
        if($parentRow.find('.select-custom').attr('checked') === 'checked') {
            $(element).parent().fadeIn();
            if(exportID)
                allSheetNames()[exportID] = $(element).val();
        } else {
            $(element).parent().fadeOut();
            if(exportID)
                delete allSheetNames()[exportID];
        }
    }
};
<commit_msg>remove unused duplicate download params<commit_after>var ExportManager = function (o) {
    var self = this;
    self.selected_exports = ko.observableArray();
    self.export_type = o.export_type || "form";
    self.is_custom = o.is_custom || false;

    self.format = o.format || "csv";
    self.domain = o.domain;
    self.downloadUrl = o.downloadUrl;
    self.bulkDownloadUrl = o.bulkDownloadUrl;
    self.exportFilters = o.exportFilters;

    self.exportModal = o.modal || "#export-download-status";
    self.$modal = $(self.exportModal);
    self.exportModalLoading = o.loadingIndicator || '.loading-indicator';
    self.exportModalLoadedData = o.loadedData || '.loaded-data';

    self.bulk_download_notice_text = (self.is_custom) ?
        "Custom Form Exports" :
        "Full Form Exports";

    self.xmlns_formdesigner = o.xmlns_formdesigner || 'formdesigner';

    self.sheet_names = ko.observable(new Object());

    var resetModal = function (modal_title, newLine) {
            self.$modal.find(self.exportModalLoading).removeClass('hide');
            self.$modal.find(self.exportModalLoadedData).empty();

            var $title = self.$modal.find('.modal-header h3 span');
            $title.text(modal_title);
            if (newLine)
                $title.attr('style', 'display: block;');
            else
                $title.attr('style', '');
        },
        updateModal = function(d) {
            var autoRefresh = '';
            var pollDownloader = function () {
                if ($('#ready_'+d.download_id).length == 0) {
                    $.get(d.download_url, function(data) {
                        self.$modal.find(self.exportModalLoadedData).html(data);
                    }).error(function () {
                        self.$modal.find(self.exportModalLoading).addClass('hide');
                        self.$modal.find(self.exportModalLoadedData).html('
Oh no! Your download was unable to be completed. We have been notified and are already hard at work solving this issue.
');
                        clearInterval(autoRefresh);
                    });
                } else {
                    self.$modal.find(self.exportModalLoading).addClass('hide');
                    clearInterval(autoRefresh);
                }
            };
            $(self.exportModal).on('hide', function () {
                clearInterval(autoRefresh);
            });
            autoRefresh = setInterval(pollDownloader, 2000);
        },
        displayModalError = function(error_text) {
            var $error = $('
');
            $error.text(error_text);
            self.$modal.find(self.exportModalLoadedData).html($error);
            self.$modal.find(self.exportModalLoading).addClass('hide');
        },
        getSheetName = function(module, form, xmlns) {
            var a = module,
                b = form;
            if (!(a && b)) {
                var parts = xmlns.split('/');
                a = parts[parts.length-2];
                b = parts[parts.length-1];
                if (a===self.xmlns_formdesigner || a.indexOf('.org') > 0)
                    return b.substring(0,31);
            }
            return getFormattedSheetName(a,b);
        };

    self.updateSelectedExports = function (data, event) {
        var $checkbox = $(event.srcElement || event.currentTarget);
        var add_to_list = ($checkbox.attr('checked') === 'checked'),
            downloadButton = $checkbox.parent().parent().parent().find('.dl-export');
        if (add_to_list) {
            $checkbox.parent().find('.label').removeClass('label-info').addClass('label-success');
            self.selected_exports.push(downloadButton);
        } else {
            $checkbox.parent().find('.label').removeClass('label-success').addClass('label-info');
            self.selected_exports.splice(self.selected_exports().indexOf(downloadButton), 1);
        }
    };

    self.downloadExport = function(downloadUrl) {
        var displayDownloadError = function (response) {
            displayModalError('Sorry, something unexpected went wrong and your download ' +
                'could not be completed. Please try again and report an issue if the problem ' +
                'persists.'
            );
        };
        $.ajax({
            dataType: 'json',
            url: downloadUrl,
            success: updateModal,
            error: displayDownloadError
        });
    };
    self.requestBulkDownload = function(data, event) {
        resetModal("Bulk "+self.bulk_download_notice_text, false);
        var prepareExport = new Object();
        if (self.is_custom)
            prepareExport = new Array();

        for (var i in self.selected_exports()) {
            var curExpButton = self.selected_exports()[i];

            var _id = curExpButton.data('appid') || curExpButton.data('exportid'),
                xmlns = curExpButton.data('xmlns'),
                module = curExpButton.data('modulename'),
                export_type = curExpButton.data('exporttype'),
                form = curExpButton.data('formname');

            var sheetName = "sheet";
            if (self.is_custom) {
                var $sheetNameElem = curExpButton.parent().parent().find('.sheetname');
                if($sheetNameElem.data('duplicate'))
                    break;
                sheetName = curExpButton.parent().parent().find('.sheetname').val();
            } else
                sheetName = getSheetName(module, form, xmlns);

            var export_tag;
            if (self.is_custom)
                export_tag = {
                    domain: self.domain,
                    xmlns: xmlns,
                    sheet_name: sheetName,
                    export_id: _id,
                    export_type: export_type
                };
            else
                export_tag = [self.domain, xmlns, sheetName];

            if (!_id)
                _id = "unknown_application";

            if (self.is_custom)
                prepareExport.push(export_tag);
            else {
                if (!prepareExport.hasOwnProperty(_id))
                    prepareExport[_id] = new Array();
                prepareExport[_id].push(export_tag);
            }
        }

        if (self.is_custom && prepareExport.length == 0) {
            displayModalError('No valid sheets were available for Custom Bulk Export. Please check for duplicate sheet names.');
            return;
        }

        var downloadUrl = self.bulkDownloadUrl +
            "?"+self.exportFilters +
            "&export_tags="+encodeURIComponent(JSON.stringify(prepareExport)) +
            "&is_custom="+self.is_custom +
            "&async=true";

        self.downloadExport(downloadUrl);
    };

    self._requestDownload = function(options) {
        var $button = $(event.srcElement || event.currentTarget);
        var downloadUrl = self.downloadUrl || $button.data('dlocation');
        resetModal("'" + options.modalTitle + "'", true);
        downloadUrl = downloadUrl +
            "?" + self.exportFilters +
            '&async=true' +
            '&format=' + self.format +
            '&export_tag=["'+self.domain+'","'+$button.data('xmlns')+'","'+$button.data('formname')+'"]' +
            '&filename='+$button.data('formname');

        for (var k in options.downloadParams) {
            if (options.downloadParams.hasOwnProperty(k)) {
                var v = options.downloadParams[k];
                downloadUrl += '&' + k + '=' + v;
            }
        }
        self.downloadExport(downloadUrl);
    };

    self.requestDownload = function(data, event) {
        var $button = $(event.srcElement || event.currentTarget);
        var modalTitle = $button.data('formname') || $button.data('xmlns');
        if ($button.data('modulename')) {
            modalTitle  = $button.data('modulename') + " > " + modalTitle;
        }
        var downloadParams = {};
        if (!self.is_custom) {
            downloadParams.app_id = $button.data('appid');
        }
        return self._requestDownload({
            modalTitle: modalTitle,
            downloadParams: downloadParams
        });
    };

    self.requestCaseDownload = function(data, event) {
        return self._requestDownload({
            modalTitle: "Case List",
            downloadParams: {
                include_closed: $('#include-closed-select').val()
            }
        });
    };

    self.checkCustomSheetNameLength = function(data, event) {
        var src = event.srcElement || event.currentTarget;
        var $input = $(src);
        var valLength = $input.val().length;
        return (valLength < 31 || event.keyCode == 8 || (src.selectionEnd-src.selectionStart) > 0);
    };

    self.updateCustomSheetNameCharacterCount = function (data, event) {
        var $input = $(event.srcElement || event.currentTarget);
        if ($input.data('exportid')) {
            var new_names = self.sheet_names();
            new_names[$input.data('exportid')] = $input.val();
            self.sheet_names(new_names);
        }
        $input.parent().find('.sheetname-count').text($input.val().length);
        return true;
    };

    self.toggleSelectAllExports = function (data, event) {
        var $toggleBtn = $(event.srcElement || event.currentTarget),
            check_class = (self.is_custom) ? '.select-custom' : '.select-bulk';
        if ($toggleBtn.data('all'))
            $.each($(check_class), function () {
                $(this).attr('checked', true);
                self.updateSelectedExports({}, {srcElement: this})
            });
        else
            $.each($(check_class), function () {
                $(this).attr('checked', false);
                self.updateSelectedExports({}, {srcElement: this})
            });
    };

},
    getFormattedSheetName = function (a, b) {
        b = b.substr(0, 14);
        a = a.substr(0,28-b.length);
        return a+" > "+b;
    };

ko.bindingHandlers.showBulkExportNotice = {
    update: function(element, valueAccessor) {
        var value = valueAccessor()();
        if (value.length > 0)
            $(element).fadeIn();
        else
            $(element).fadeOut();
    }
};

ko.bindingHandlers.checkForUniqueSheetName = {
    update: function(element, valueAccessor) {
        var value = valueAccessor()(),
            current_name = $(element).val(),
            $dupeNotice = $(element).parent().find('.sheetname-duplicate'),
            $parentCol = $(element).parent().parent();
        var all_names = _.toArray(value);
        if( (_.lastIndexOf(all_names, current_name) - _.indexOf(all_names, current_name)) > 0) {
            $dupeNotice.removeClass('hide');
            $parentCol.addClass('error');
            $(element).data('duplicate', true);
        } else {
            $dupeNotice.addClass('hide');
            $parentCol.removeClass('error');
            $(element).data('duplicate', false);
        }
    }
};

ko.bindingHandlers.updateCustomSheetName = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor()(),
            originalName = $(element).val(),
            MAX_LENGTH = 31,
            SPLIT_CHAR = '>';

        if (originalName.indexOf(SPLIT_CHAR) > 0 && originalName.length > MAX_LENGTH) {
            // intelligently generate a sheetname
            var splitName = originalName.split(SPLIT_CHAR);
            var formname = splitName[splitName.length-1].trim(),
                modulename = splitName[splitName.length-2].trim();
            originalName = getFormattedSheetName(modulename, formname);
            $(element).val(originalName);
        }

        if (originalName.length > MAX_LENGTH) {
            $(element).val(originalName.substring(Math.max(0, originalName.length-MAX_LENGTH),originalName.length));
        } else {
            $(element).parent().find('.sheetname-count').text(originalName.length);
        }

    },
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor()(),
            allSheetNames = allBindingsAccessor().checkForUniqueSheetName;
        var $parentRow = $(element).parent().parent().parent(),
            exportID = $(element).data('exportid');
        if($parentRow.find('.select-custom').attr('checked') === 'checked') {
            $(element).parent().fadeIn();
            if(exportID)
                allSheetNames()[exportID] = $(element).val();
        } else {
            $(element).parent().fadeOut();
            if(exportID)
                delete allSheetNames()[exportID];
        }
    }
};
<|endoftext|>


<commit_before>"use strict";

// libraries
const chokidar = require("chokidar");
const glob = require("glob");
const path = require("path");
const fs = require("fs-extra");
const Promise = require("bluebird");
const writeOutputFile = require("../../lib/file-writer");
const chalk = require("chalk");

const ScssDependencyResolver = require("./scss-dependency-resolver");
const ScssLinter = require("./scss-linter");
const Logger = require("../../lib/logger");
const ScssDirectoryTask = require("./scss-directory-task");

module.exports = class ScssTask
{
    /**
     *
     * @param {ScssTaskConfig} config
     */
    constructor (config)
    {
        /**
         * @private
         * @type {ScssTaskConfig}
         */
        this.config = config;

        /**
         * @private
         * @type {ScssDependencyResolver}
         */
        // this.dependencyResolver = new ScssDependencyResolver(path.dirname(config.input));

        /**
         * @private
         * @type {ScssLinter}
         */
        this.linter = new ScssLinter(config);
    }

    /**
     * Runs the task
     *
     * @param {function} done
     * @param {Boolean} debug Flag, whether the task should run in debug mode
     */
    run (done, debug)
    {
        if (debug)
        {
            this.watchProject()
                .then(done);
        }
        else
        {
            this.compileProject()
                .then(done);
        }
    }

    /**
     * Compiles the complete project
     *
     * @private
     */
    compileProject ()
    {
        return new Promise(
            (resolve, reject) => {
                glob(this.config.input,
                    (error, directories) => {
                        let tasks = [];

                        directories.forEach(
                            (dir) => {
                                let task = new ScssDirectoryTask(dir, this.config);
                                tasks.push(task.compile(false));
                            }
                        );

                        Promise.all(tasks)
                            .then(resolve);
                    }
                )
            }
        );
    }

    /**
     * Watches the complete project
     *
     * @private
     */
    watchProject ()
    {
        return new Promise(
            (resolve, reject) => {
                glob(this.config.input,
                    (error, directories) => {

                        if (error)
                        {
                            reject(error);
                        }

                        directories.forEach(
                            (dir) => {
                                let task = new ScssDirectoryTask(dir, this.config);
                                task.watch();
                            }
                        );

                        process
                            .on("SIGINT", () => {
                                resolve();
                                setTimeout(process.exit, 1);
                            });
                    }
                )
            }
        );
    }
};
<commit_msg>Compile project before starting the watchers<commit_after>"use strict";

// libraries
const chokidar = require("chokidar");
const glob = require("glob");
const path = require("path");
const fs = require("fs-extra");
const Promise = require("bluebird");
const writeOutputFile = require("../../lib/file-writer");
const chalk = require("chalk");

const ScssDependencyResolver = require("./scss-dependency-resolver");
const ScssLinter = require("./scss-linter");
const Logger = require("../../lib/logger");
const ScssDirectoryTask = require("./scss-directory-task");

module.exports = class ScssTask
{
    /**
     *
     * @param {ScssTaskConfig} config
     */
    constructor (config)
    {
        /**
         * @private
         * @type {ScssTaskConfig}
         */
        this.config = config;

        /**
         * @private
         * @type {ScssDependencyResolver}
         */
        // this.dependencyResolver = new ScssDependencyResolver(path.dirname(config.input));

        /**
         * @private
         * @type {ScssLinter}
         */
        this.linter = new ScssLinter(config);
    }

    /**
     * Runs the task
     *
     * @param {function} done
     * @param {Boolean} debug Flag, whether the task should run in debug mode
     */
    run (done, debug)
    {
        if (debug)
        {
            // compile project and start watchers
            // the watchers ignore the initial events, as otherwise all dependencies would repeatedly
            // issue a recompile on the main file
            this.compileProject();

            this.watchProject()
                .then(done);
        }
        else
        {
            this.compileProject()
                .then(done);
        }
    }

    /**
     * Compiles the complete project
     *
     * @private
     */
    compileProject ()
    {
        return new Promise(
            (resolve, reject) => {
                glob(this.config.input,
                    (error, directories) => {
                        let tasks = [];

                        directories.forEach(
                            (dir) => {
                                let task = new ScssDirectoryTask(dir, this.config);
                                tasks.push(task.compile(false));
                            }
                        );

                        Promise.all(tasks)
                            .then(resolve);
                    }
                )
            }
        );
    }

    /**
     * Watches the complete project
     *
     * @private
     */
    watchProject ()
    {
        return new Promise(
            (resolve, reject) => {
                glob(this.config.input,
                    (error, directories) => {

                        if (error)
                        {
                            reject(error);
                        }

                        directories.forEach(
                            (dir) => {
                                let task = new ScssDirectoryTask(dir, this.config);
                                task.watch();
                            }
                        );

                        process
                            .on("SIGINT", () => {
                                resolve();
                                setTimeout(process.exit, 1);
                            });
                    }
                )
            }
        );
    }
};
<|endoftext|>


<commit_before>/* jslint node: true, esnext: true */

const yaml = require('js-yaml');

export default function (target, template, options = {}) {
  const yml = yaml.safeLoad(target);
  const tyml = yaml.safeLoad(template);

  Object.keys(tyml).forEach(name => {
    yml[name] = tyml[name];
  });

  return yaml.safeDump(yml);
}
<commit_msg>fix: handle empty target<commit_after>/* jslint node: true, esnext: true */

const yaml = require('js-yaml');

export default function (target, template, options = {}) {
  const yml = yaml.safeLoad(target) || {};
  const tyml = yaml.safeLoad(template);

  Object.keys(tyml).forEach(name => {
    yml[name] = tyml[name];
  });

  return yaml.safeDump(yml);
}
<|endoftext|>


<commit_before>var galleryAPI = {
    getAlbums: function(successCallback, errorCallback) {
        cordova.exec(
            successCallback, // success callback function
            errorCallback, // error callback function
            'GalleryAPI', // mapped to our native Java class called "CalendarPlugin"
            'getAlbums', // with this action name
            []
        );
     }
};
<commit_msg>Update gallery-api.js<commit_after>function GalleryAPI()
{

}

GalleryAPI.prototype.getAlbums = function(successCallback, errorCallback) {
        cordova.exec(
            successCallback,
            errorCallback,
            'GalleryAPI',
            'getAlbums',
            []
        );
     }
};

GalleryAPI.prototype.getMedia = function(albumName, successCallback, errorCallback) {
        cordova.exec(
            successCallback,
            errorCallback,
            'GalleryAPI',
            'getMedia',
            [albumName]
        );
     }
};

module.exports = new GalleryAPI();
<|endoftext|>


<commit_before>(function() {
  /**
   * @ngInject
   */
  function ius($q, $ionicLoading, $cordovaFile) {
    var service = {};
    service.uploadImage = uploadImage;
    return service;
    function uploadImage(imageURI) {
      var deferred = $q.defer();
      var fileSize;
      var percentage;
      // Find out how big the original file is
      window.resolveLocalFileSystemURL(imageURI, function(fileEntry) {
        fileEntry.file(function(fileObj) {
          fileSize = fileObj.size;
          // Display a loading indicator reporting the start of the upload
          $ionicLoading.show({template : 'Uploading Picture : ' + 0 + '%'});
          // Trigger the upload
          uploadFile();
        });
      });
      function uploadFile() {
        // Add the Cloudinary "upload preset" name to the headers
        var uploadOptions = {
          params : { 'upload_preset': "ckpnun3d"}
        };
        $cordovaFile
          // Your Cloudinary URL will go here
          .uploadFile("https://api.cloudinary.com/v1_1/djuhhyhgt/image/upload", imageURI, uploadOptions)

          .then(function(result) {
            // Let the user know the upload is completed
            $ionicLoading.show({template : 'Upload Completed', duration: 1000});
            // Result has a "response" property that is escaped
            // FYI: The result will also have URLs for any new images generated with
            // eager transformations
            var response = JSON.parse(decodeURIComponent(result.response));
            deferred.resolve(response);
          }, function(err) {
            // Uh oh!
            $ionicLoading.show({template : 'Upload Failed', duration: 3000});
            deferred.reject(err);
          }, function (progress) {
            // The upload plugin gives you information about how much data has been transferred
            // on some interval.  Use this with the original file size to show a progress indicator.
            percentage = Math.floor(progress.loaded / fileSize * 100);
            $ionicLoading.show({template : 'Uploading Picture : ' + percentage + '%'});
          });
      }
      return deferred.promise;
    }
  }

	angular.module('loseYourWayServices', [])

	.factory('ImageUploadService', ius)

	.factory('Route', function($resource) {
	  return $resource('http://loseyourway.herokuapp.com/routes/:id');
	  //return $resource('http://192.168.1.85:3000/routes/:id');
	})
	.factory('RouteResult', function($resource) {
		return $resource('http://loseyourway.herokuapp.com/routeresults/:id');
		//return $resource('http://192.168.1.85:3000/routeresults/:id');
	})
	.factory('Camera', ['$q', function($q) {

	  return {
		getPicture: function(options) {
		  var q = $q.defer();

		  navigator.camera.getPicture(function(result) {
			// Do any magic you need
			q.resolve(result);
		  }, function(err) {
			q.reject(err);
		  }, options);

		  return q.promise;
		}
	  }
	}])
	.factory('$localstorage', ['$window', function($window) {
	  return {
		set: function(key, value) {
		  $window.localStorage[key] = value;
		},
		get: function(key, defaultValue) {
		  return $window.localStorage[key] || defaultValue;
		},
		setObject: function(key, value) {
		  $window.localStorage[key] = JSON.stringify(value);
		},
		getObject: function(key) {
		  return JSON.parse($window.localStorage[key] || '{}');
		}
	  }
	}]);

})();<commit_msg>Update server address to loseourway<commit_after>(function() {
  /**
   * @ngInject
   */
  function ius($q, $ionicLoading, $cordovaFile) {
    var service = {};
    service.uploadImage = uploadImage;
    return service;
    function uploadImage(imageURI) {
      var deferred = $q.defer();
      var fileSize;
      var percentage;
      // Find out how big the original file is
      window.resolveLocalFileSystemURL(imageURI, function(fileEntry) {
        fileEntry.file(function(fileObj) {
          fileSize = fileObj.size;
          // Display a loading indicator reporting the start of the upload
          $ionicLoading.show({template : 'Uploading Picture : ' + 0 + '%'});
          // Trigger the upload
          uploadFile();
        });
      });
      function uploadFile() {
        // Add the Cloudinary "upload preset" name to the headers
        var uploadOptions = {
          params : { 'upload_preset': "ckpnun3d"}
        };
        $cordovaFile
          // Your Cloudinary URL will go here
          .uploadFile("https://api.cloudinary.com/v1_1/djuhhyhgt/image/upload", imageURI, uploadOptions)

          .then(function(result) {
            // Let the user know the upload is completed
            $ionicLoading.show({template : 'Upload Completed', duration: 1000});
            // Result has a "response" property that is escaped
            // FYI: The result will also have URLs for any new images generated with
            // eager transformations
            var response = JSON.parse(decodeURIComponent(result.response));
            deferred.resolve(response);
          }, function(err) {
            // Uh oh!
            $ionicLoading.show({template : 'Upload Failed', duration: 3000});
            deferred.reject(err);
          }, function (progress) {
            // The upload plugin gives you information about how much data has been transferred
            // on some interval.  Use this with the original file size to show a progress indicator.
            percentage = Math.floor(progress.loaded / fileSize * 100);
            $ionicLoading.show({template : 'Uploading Picture : ' + percentage + '%'});
          });
      }
      return deferred.promise;
    }
  }

	angular.module('loseYourWayServices', [])

	.factory('ImageUploadService', ius)

	.factory('Route', function($resource) {
	  return $resource('http://loseourway.herokuapp.com/routes/:id');
	  //return $resource('http://192.168.1.85:3000/routes/:id');
	})
	.factory('RouteResult', function($resource) {
		return $resource('http://loseourway.herokuapp.com/routeresults/:id');
		//return $resource('http://192.168.1.85:3000/routeresults/:id');
	})
	.factory('Camera', ['$q', function($q) {

	  return {
		getPicture: function(options) {
		  var q = $q.defer();

		  navigator.camera.getPicture(function(result) {
			// Do any magic you need
			q.resolve(result);
		  }, function(err) {
			q.reject(err);
		  }, options);

		  return q.promise;
		}
	  }
	}])
	.factory('$localstorage', ['$window', function($window) {
	  return {
		set: function(key, value) {
		  $window.localStorage[key] = value;
		},
		get: function(key, defaultValue) {
		  return $window.localStorage[key] || defaultValue;
		},
		setObject: function(key, value) {
		  $window.localStorage[key] = JSON.stringify(value);
		},
		getObject: function(key) {
		  return JSON.parse($window.localStorage[key] || '{}');
		}
	  }
	}]);

})();<|endoftext|>


<commit_before>// const Module = require('module')
const path = require('path')
const withCSS = require('@zeit/next-css')
const withImages = require('next-images')
const resolveFrom = require('resolve-from')

const node_modules = path.resolve(__dirname, 'node_modules')

// const originalRequire = Module.prototype.require

// // The following ensures that there is always only a single (and same)
// // copy of React in an app at any given moment.
// Module.prototype.require = function(modulePath) {
//   // Only redirect resolutions to non-relative and non-absolute modules
//   if (['/react/', '/react-dom/'].some(d => {
//     try {
//       return require.resolve(modulePath).includes(d)
//     } catch (err) {
//       return false
//     }
//   })) {
//     console.log(modulePath)
//     try {
//       modulePath = resolveFrom(
//         node_modules,
//         modulePath
//       )
//       console.log('New: ', modulePath)
//     } catch (err) {
//       //
//     }
//   }

//   return originalRequire.call(this, modulePath)
// }

const baseConfig = {
  // target: 'serverless',
  pageExtensions: ['js', 'jsx'],
  webpack(config) {
    config.resolve.modules = [...config.resolve.modules, path.resolve('./src')]
    config.resolve.alias = {
      ...config.resolve.alias,
      react$: path.resolve(resolveFrom(node_modules, 'react'), '..'),
      'react-dom$': path.resolve(resolveFrom(node_modules, 'react-dom'), '..')
    }
    return config
  }
}

module.exports = [
  withCSS,
  withImages
].reduce(
  (a, b) => b(a),
  baseConfig
)
<commit_msg>Update next.config.js<commit_after>const Module = require('module')
const path = require('path')
const withCSS = require('@zeit/next-css')
const withImages = require('next-images')
const resolveFrom = require('resolve-from')

const node_modules = path.resolve(__dirname, 'node_modules')

const originalRequire = Module.prototype.require

// The following ensures that there is always only a single (and same)
// copy of React in an app at any given moment.
Module.prototype.require = function(modulePath) {
  // Only redirect resolutions to non-relative and non-absolute modules
  if (['/react/', '/react-dom/'].some(d => {
    try {
      return require.resolve(modulePath).includes(d)
    } catch (err) {
      return false
    }
  })) {
    console.log(modulePath)
    try {
      modulePath = resolveFrom(
        node_modules,
        modulePath
      )
      console.log('New: ', modulePath)
    } catch (err) {
      //
    }
  }

  return originalRequire.call(this, modulePath)
}

const baseConfig = {
  // target: 'serverless',
  pageExtensions: ['js', 'jsx'],
  webpack(config) {
    config.resolve.modules = [...config.resolve.modules, path.resolve('./src')]
    config.resolve.alias = {
      ...config.resolve.alias,
      react$: path.resolve(resolveFrom(node_modules, 'react'), '..'),
      'react-dom$': path.resolve(resolveFrom(node_modules, 'react-dom'), '..')
    }
    return config
  }
}

module.exports = [
  withCSS,
  withImages
].reduce(
  (a, b) => b(a),
  baseConfig
)
<|endoftext|>


<commit_before>import React from 'react';
import {List} from 'immutable';
import {shallow, mount} from 'enzyme';
import {isEqual} from 'lodash';
import sinon from 'sinon';
import {MultiSelect} from '../MultiSelect';

const options = [
    {value: 'Pash', label: 'Pash'},
    {value: 'Wolf', label: 'Wolf'},
    {value: 'Hunter', label: 'Hunter'},
    {value: 'Mouse', label: 'Mouse'},
    {value: 'Millenial', label: 'Millenial'},
];

const value = ['Pash', 'Hunter'];

const allMultiSelectProps = {
    options: List(options),
    value: List(value),
    className: 'MultiSelectClass',
    name: 'MultiSelectName',
    label: 'MultiSelect Label',
    labelPrefix: 'Label Prefix',
    labelPostfix: 'Label Postfix',
    inputChanged: values => ({}),
    placeholder: 'Please make a selection',
    noResultsText: 'There are no options to choose from'
};

const inputWrapperPropsNotList = {
    ...allMultiSelectProps,
    options: options
};

const {name, label, labelPrefix, labelPostfix} = allMultiSelectProps;
const multi = true;

const inputWrapperProps = {
    name,
    label,
    labelPrefix,
    labelPostfix,
    className: 'MultiSelectClass input',
};

const removeChildren = props => {
    const {children, ...remainingProps} = props;
    return remainingProps;
}

describe('<MultiSelect />', () => {
    const wrapper = shallow(<MultiSelect {...allMultiSelectProps} />);
    const InputWrapperProps = removeChildren(wrapper.props());
    const {options: Options, value: Value, multi: Multi} = wrapper.find('Select').props();

    it('should have all the required props for <InputWrapper />', () => {
        expect(isEqual(InputWrapperProps, inputWrapperProps)).toBe(true);
    });

    it('should have all the passed in props for <Select />(from react-select)', () => {
        expect(isEqual(options, Options)).toBe(true);
        expect(isEqual(value, Value)).toBe(true);
        expect(isEqual(multi, Multi)).toBe(true);
    });

    it('should render a Select)', () => {
        expect(wrapper.find('Select')).toHaveLength(1);
    });

    /**
     * Not testing the 'Select'(from react-select) component as its
     * an external package and assuming it to be tested
     * by its developer
     */
});

describe('Bad <MultiSelect />', () => {
    it("should throw if options are not an Immutable List", () => {
      expect(() => {
        mount(<MultiSelect {...inputWrapperPropsNotList} />)
      }).toThrow();

      expect(() => {
        mount(<MultiSelect {...allMultiSelectProps} />)
      }).not.toThrow();
    })
});<commit_msg>A few more tests for MultiSelect<commit_after>import React from 'react';
import {List} from 'immutable';
import {shallow, mount} from 'enzyme';
import {isEqual} from 'lodash';
import sinon from 'sinon';
import {MultiSelect} from '../MultiSelect';

const options = [
    {value: 'Pash', label: 'Pash'},
    {value: 'Wolf', label: 'Wolf'},
    {value: 'Hunter', label: 'Hunter'},
    {value: 'Mouse', label: 'Mouse'},
    {value: 'Millenial', label: 'Millenial'},
];

const value = ['Pash', 'Hunter'];

const allMultiSelectProps = {
    options: List(options),
    value: List(value),
    className: 'MultiSelectClass',
    name: 'MultiSelectName',
    label: 'MultiSelect Label',
    labelPrefix: 'Label Prefix',
    labelPostfix: 'Label Postfix',
    inputChanged: values => ({}),
    placeholder: 'Please make a selection',
    noResultsText: 'There are no options to choose from'
};

const inputWrapperPropsNotList = {
    ...allMultiSelectProps,
    options: options
};

const {name, label, labelPrefix, labelPostfix} = allMultiSelectProps;
const multi = true;

const inputWrapperProps = {
    name,
    label,
    labelPrefix,
    labelPostfix,
    className: 'MultiSelectClass input',
};

const removeChildren = props => {
    const {children, ...remainingProps} = props;
    return remainingProps;
}

describe('<MultiSelect /> shallow', () => {
    const wrapper = shallow(<MultiSelect {...allMultiSelectProps} />);
    const InputWrapperProps = removeChildren(wrapper.props());
    const {options: Options, value: Value, multi: Multi} = wrapper.find('Select').props();

    it('should have all the required props for <InputWrapper />', () => {
        expect(isEqual(InputWrapperProps, inputWrapperProps)).toBe(true);
    });

    it('should have all the passed in props for <Select />(from react-select)', () => {
        expect(isEqual(options, Options)).toBe(true);
        expect(isEqual(value, Value)).toBe(true);
        expect(isEqual(multi, Multi)).toBe(true);
    });

    it('should render a Select)', () => {
        expect(wrapper.find('Select')).toHaveLength(1);
    });

    /**
     * Not testing the 'Select'(from react-select) component as its
     * an external package and assuming it to be tested
     * by its developer
     */
});

describe('<MultiSelect /> mount', () => {
    const wrapper = mount(<MultiSelect {...allMultiSelectProps} />);
    const label = wrapper.find('label');
    const select = wrapper.find('.Select-control');

    it('renders a label', () => {
        expect(label.exists()).toBe(true);
    });

    it('renders a select', () => {
        expect(select.exists()).toBe(true);
    });

    it('should set the labelPrefix', () => {
        expect(wrapper.find(".input-label-prefix").text() === allMultiSelectProps.labelPrefix).toBe(true);
    });

    it('should set the labelPostfix', () => {
        expect(wrapper.find(".input-label-postfix").text() === allMultiSelectProps.labelPostfix).toBe(true);
    });
});

describe('<MultiSelect /> mount no default value', () => {
    const noDefaultValue = {
        ...allMultiSelectProps,
        value: null
    }

    const wrapper = mount(<MultiSelect {...noDefaultValue} />);

    it('should set the placeholder', () => {
        expect(wrapper.find(".Select-placeholder").text() === allMultiSelectProps.placeholder).toBe(true);
    });
});

describe('<MultiSelect /> failure', () => {
    it("should throw if options are not an Immutable List", () => {
      expect(() => {
        mount(<MultiSelect {...inputWrapperPropsNotList} />)
      }).toThrow();

      expect(() => {
        mount(<MultiSelect {...allMultiSelectProps} />)
      }).not.toThrow();
    })
});<|endoftext|>


<commit_before>//app.js
App({
  onLaunch: function () {
    //调用API从本地缓存中获取数据
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
  },
  getUserInfo:function(cb){
    var that = this
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //调用登录接口
      wx.login({
        success: function (res) {
          //换取openid & session_key
          wx.request({
            url: 'https://sdk.weixin.senparc.com/WxOpen/OnLogin',
            method: 'POST',
            data: {
              code: res.code
            },
            success:function(json){
              var result = json.data;
              if(result.success)
              {
                wx.setStorageSync('sessionId', result.sessionId);

                //获取userInfo并校验
                wx.getUserInfo({
                  success: function (userInfoRes) {
                    console.log('get userinfo',userInfoRes);
                    that.globalData.userInfo = userInfoRes.userInfo
                    typeof cb == "function" && cb(that.globalData.userInfo)

                    //校验
                    wx.request({
                      url: 'https://sdk.weixin.senparc.com/WxOpen/CheckWxOpenSignature',
                      method: 'POST',
                      data: {
                        sessionId: wx.getStorageSync('sessionId'),
                        rawData:userInfoRes.rawData,
                        signature:userInfoRes.signature
                      },
                      success:function(json){
                        //console.log(json.data);
                      }
                    });

                    //解密数据（建议放到校验success回调函数中，此处仅为演示）
                    wx.request({
                      url: 'https://sdk.weixin.senparc.com/WxOpen/DecodeEncryptedData',
                      method: 'POST',
                      data: {
                        'type':"userInfo",
                        sessionId: wx.getStorageSync('sessionId'),
                        encryptedData:userInfoRes.encryptedData,
                        iv:userInfoRes.iv
                      },
                      success:function(json){
                        console.log(json.data);
                      }
                    });
                  }
                })
        }else{
          console.log('储存session失败！',json);
        }
      }
    })
  }
})
    }
  },
  globalData:{
    userInfo:null
  }
})<commit_msg>修改模板消息单元测试<commit_after>//app.js
App({
  onLaunch: function () {
    //调用API从本地缓存中获取数据
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
  },
  getUserInfo:function(cb){
    var that = this
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //调用登录接口
      wx.login({
        success: function (res) {
          //换取openid & session_key
          wx.request({
            url: 'https://sdk.weixin.senparc.com/WxOpen/OnLogin',
            method: 'POST',
            data: {
              code: res.code
            },
            success:function(json){
              var result = json.data;
              if(result.success)
              {
                wx.setStorageSync('sessionId', result.sessionId);

                //获取userInfo并校验
                wx.getUserInfo({
                  success: function (userInfoRes) {
                    console.log('get userinfo',userInfoRes);
                    that.globalData.userInfo = userInfoRes.userInfo
                    typeof cb == "function" && cb(that.globalData.userInfo)

                    //校验
                    wx.request({
                      url: 'https://sdk.weixin.senparc.com/WxOpen/CheckWxOpenSignature',
                      method: 'POST',
                      data: {
                        sessionId: wx.getStorageSync('sessionId'),
                        rawData:userInfoRes.rawData,
                        signature:userInfoRes.signature
                      },
                      success:function(json){
                        console.log(json.data);
                      }
                    });

                    //解密数据（建议放到校验success回调函数中，此处仅为演示）
                    wx.request({
                      url: 'https://sdk.weixin.senparc.com/WxOpen/DecodeEncryptedData',
                      method: 'POST',
                      data: {
                        'type':"userInfo",
                        sessionId: wx.getStorageSync('sessionId'),
                        encryptedData:userInfoRes.encryptedData,
                        iv:userInfoRes.iv
                      },
                      success:function(json){
                        console.log(json.data);
                      }
                    });
                  }
                })
        }else{
          console.log('储存session失败！',json);
        }
      }
    })
  }
})
    }
  },
  globalData:{
    userInfo:null
  }
})<|endoftext|>