<commit_before>import { assign } from '@ember/polyfills';
import Component from '@ember/component';
import { getOwner } from '@ember/application';
import { set, getProperties, get, computed } from '@ember/object';
import { run } from '@ember/runloop';
import { setDefaultHighChartOptions } from '../utils/option-loader';
import { getSeriesMap, getSeriesChanges } from '../utils/chart-data';
import layout from 'ember-highcharts/templates/components/high-charts';
import merge from 'deepmerge';

/* Map ember-highcharts modes to Highcharts methods
 * https://api.highcharts.com/class-reference/Highcharts.html
 */
const CHART_TYPES = {
  StockChart: 'stockChart',
  Map: 'mapChart',
  undefined: 'chart'
};

export default Component.extend({
  layout,
  classNames: ['highcharts-wrapper'],
  content: undefined,
  mode: undefined,
  chartOptions: undefined,
  chart: null,
  theme: undefined,
  callback: undefined,

  buildOptions: computed('chartOptions', 'content.[]', function() {
    let theme = get(this, 'theme');
    if (theme === undefined) {
      theme = {};
    }

    let passedChartOptions = get(this, 'chartOptions');
    if (passedChartOptions === undefined) {
      passedChartOptions = {};
    }

    let chartOptions = merge(theme, passedChartOptions);
    let chartContent = get(this, 'content');

    // if 'no-data-to-display' module has been imported, keep empty series and leave it to highcharts to show no data label.
    if (!get(this, 'content.length') && !Highcharts.Chart.prototype.showNoData) {
      chartContent = [{
        id: 'noData',
        data: 0,
        color: '#aaaaaa'
      }];
    }

    let defaults = { series: chartContent };

    return assign(defaults, chartOptions);
  }),

  didReceiveAttrs() {
    this._super(...arguments);

    let { content, chart, mode } = getProperties(this, 'content', 'chart', 'mode');

    if (!content || !chart) {
      return;
    }

    let isStockChart = mode === 'StockChart';

    // create maps to make series data easier to work with
    let contentSeriesMap = getSeriesMap(content);
    let chartSeriesMap = getSeriesMap(chart.series);

    // remove and update current series
    let chartSeriesToRemove = [];

    chart.series.forEach((series) => {
      if (isStockChart && series.name.match(/^Navigator/)) {
        return;
      }

      let contentSeries = contentSeriesMap[series.name];

      if (!contentSeries) {
        return chartSeriesToRemove.push(series);
      }

      let updatedKeys = getSeriesChanges(contentSeries, series);

      // call series.update() when other series attributes like pointStart have changed
      if (updatedKeys.length) {
        series.update(contentSeries, false);
      } else {
        series.setData(contentSeries.data, false);
      }
    });

    chartSeriesToRemove.forEach((series) => series.remove(false));

    // add new series
    content.forEach((contentSeries) => {
      // eslint-disable-next-line no-prototype-builtins
      if (!chartSeriesMap.hasOwnProperty(contentSeries.name)) {
        chart.addSeries(contentSeries, false);
      }
    });

    // reset navigator data
    if (isStockChart && chart.xAxis.length) {
      chart.xAxis[0].setExtremes();
    }

    return chart.redraw();
  },

  drawAfterRender() {
    run.scheduleOnce('afterRender', this, 'draw');
  },

  draw() {
    let element = this.element && this.element.querySelector('.chart-container');
    let modeAttr = get(this, 'mode') || undefined;
    let mode = CHART_TYPES[modeAttr];
    let completeChartOptions = [get(this, 'buildOptions'), get(this, 'callback')];

    if (element) {
      let chart = Highcharts[mode](element, ...completeChartOptions);
      set(this, 'chart', chart);
    }
  },

  didInsertElement() {
    this._super(...arguments);

    this.drawAfterRender();
    setDefaultHighChartOptions(getOwner(this));
  },

  willDestroyElement() {
    this._super(...arguments);

    if (get(this, 'chart')) {
      get(this, 'chart').destroy();
    }
  }
});
<commit_msg>Add Gantt chart<commit_after>import { assign } from '@ember/polyfills';
import Component from '@ember/component';
import { getOwner } from '@ember/application';
import { set, getProperties, get, computed } from '@ember/object';
import { run } from '@ember/runloop';
import { setDefaultHighChartOptions } from '../utils/option-loader';
import { getSeriesMap, getSeriesChanges } from '../utils/chart-data';
import layout from 'ember-highcharts/templates/components/high-charts';
import merge from 'deepmerge';

/* Map ember-highcharts modes to Highcharts methods
 * https://api.highcharts.com/class-reference/Highcharts.html
 */
const CHART_TYPES = {
  StockChart: 'stockChart',
  Map: 'mapChart',
  Gantt: 'ganttChart',
  undefined: 'chart'
};

export default Component.extend({
  layout,
  classNames: ['highcharts-wrapper'],
  content: undefined,
  mode: undefined,
  chartOptions: undefined,
  chart: null,
  theme: undefined,
  callback: undefined,

  buildOptions: computed('chartOptions', 'content.[]', function() {
    let theme = get(this, 'theme');
    if (theme === undefined) {
      theme = {};
    }

    let passedChartOptions = get(this, 'chartOptions');
    if (passedChartOptions === undefined) {
      passedChartOptions = {};
    }

    let chartOptions = merge(theme, passedChartOptions);
    let chartContent = get(this, 'content');

    // if 'no-data-to-display' module has been imported, keep empty series and leave it to highcharts to show no data label.
    if (!get(this, 'content.length') && !Highcharts.Chart.prototype.showNoData) {
      chartContent = [{
        id: 'noData',
        data: 0,
        color: '#aaaaaa'
      }];
    }

    let defaults = { series: chartContent };

    return assign(defaults, chartOptions);
  }),

  didReceiveAttrs() {
    this._super(...arguments);

    let { content, chart, mode } = getProperties(this, 'content', 'chart', 'mode');

    if (!content || !chart) {
      return;
    }

    let isStockChart = mode === 'StockChart';

    // create maps to make series data easier to work with
    let contentSeriesMap = getSeriesMap(content);
    let chartSeriesMap = getSeriesMap(chart.series);

    // remove and update current series
    let chartSeriesToRemove = [];

    chart.series.forEach((series) => {
      if (isStockChart && series.name.match(/^Navigator/)) {
        return;
      }

      let contentSeries = contentSeriesMap[series.name];

      if (!contentSeries) {
        return chartSeriesToRemove.push(series);
      }

      let updatedKeys = getSeriesChanges(contentSeries, series);

      // call series.update() when other series attributes like pointStart have changed
      if (updatedKeys.length) {
        series.update(contentSeries, false);
      } else {
        series.setData(contentSeries.data, false);
      }
    });

    chartSeriesToRemove.forEach((series) => series.remove(false));

    // add new series
    content.forEach((contentSeries) => {
      // eslint-disable-next-line no-prototype-builtins
      if (!chartSeriesMap.hasOwnProperty(contentSeries.name)) {
        chart.addSeries(contentSeries, false);
      }
    });

    // reset navigator data
    if (isStockChart && chart.xAxis.length) {
      chart.xAxis[0].setExtremes();
    }

    return chart.redraw();
  },

  drawAfterRender() {
    run.scheduleOnce('afterRender', this, 'draw');
  },

  draw() {
    let element = this.element && this.element.querySelector('.chart-container');
    let modeAttr = get(this, 'mode') || undefined;
    let mode = CHART_TYPES[modeAttr];
    let completeChartOptions = [get(this, 'buildOptions'), get(this, 'callback')];

    if (element) {
      let chart = Highcharts[mode](element, ...completeChartOptions);
      set(this, 'chart', chart);
    }
  },

  didInsertElement() {
    this._super(...arguments);

    this.drawAfterRender();
    setDefaultHighChartOptions(getOwner(this));
  },

  willDestroyElement() {
    this._super(...arguments);

    if (get(this, 'chart')) {
      get(this, 'chart').destroy();
    }
  }
});
<|endoftext|>


<commit_before>/**
 * @author Marius Runde, Daniel Sawatzky, Thiemo Gaertner
 */
// ---------------------------
// --- Methods for the map ---
// ---------------------------
// Variables for the map, markers and markers bounds
var map,
nrwBounds,
markers = [],
mc,
mcUsedBefore = true,
maxZoomLevelForClusterer = 12,
markersBounds = new google.maps.LatLngBounds(),
geocoder = new google.maps.Geocoder();

/**
 * Initialize the map
 */
function initMap() {
	var mapOptions = {
		// center: new google.maps.LatLng(51.478333, 7.555), // center of North-Rhine-Westphalia
		mapTypeControl: true,
		mapTypeControlOptions: {
			style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
		},
		mapTypeId: google.maps.MapTypeId.ROADMAP,
		minZoom: 8,
		scaleControl: true,
		streetViewControl: false,
		zoomControl: true,
		zoomControlOptions: {
			style: google.maps.ZoomControlStyle.DEFAULT
		}
	};
	map = new google.maps.Map(document.getElementById("map"), mapOptions);

	// Bounds for North-Rhine-Westphalia (NRW)
	nrwBounds = new google.maps.LatLngBounds(
		new google.maps.LatLng(50.3, 5.8), // south west
		new google.maps.LatLng(52.6, 9.5) // north east
	);
	map.fitBounds(nrwBounds);

	// Grey out the rest of the world
	var greyOutPolygon = new google.maps.Polygon({
		clickable: false,
		paths: [nrwBoundaries, everythingElse],
		strokeColor: 'grey',
		strokeOpacity: 0.85,
		strokeWeight: 2,
		fillColor: 'grey',
		fillOpacity: 0.7
	});
	greyOutPolygon.setMap(map);

	// Create the search box and link it to the UI element.
	var input = /** @type {HTMLInputElement} */(document.getElementById('search-input'));
	map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

	var searchBox = new google.maps.places.SearchBox(/** @type {HTMLInputElement} */(input));

	// Listen for the dragend event
	google.maps.event.addListener(map, 'dragend', function() {
		// Is the map still in our bounding box of North-Rhine-Westphalia?
		if (nrwBounds.contains(map.getCenter())) {
			// YES
			return;
		} else {
			// NO
			var c = map.getCenter(),
			x = c.lng(),
			y = c.lat(),
			maxX = nrwBounds.getNorthEast().lng(),
			maxY = nrwBounds.getNorthEast().lat(),
			minX = nrwBounds.getSouthWest().lng(),
			minY = nrwBounds.getSouthWest().lat();

			if (x < minX) x = minX;
			if (x > maxX) x = maxX;
			if (y < minY) y = minY;
			if (y > maxY) y = maxY;

			map.setCenter(new google.maps.LatLng(y, x));
		}
	});

	// Listen for the zoom_changed event to refresh the markers
	google.maps.event.addListener(map, 'zoom_changed', function() {
		refreshMarkers(map.getZoom());
	});

	// Listen for the event fired when the user selects an item from the
	// pick list. Retrieve the matching places for that item.
	google.maps.event.addListener(searchBox, 'places_changed', function() {
		var places = searchBox.getPlaces();
		if (google.maps.geometry.poly.containsLocation(places[0].geometry.location, nrwPolygon)) {
			var bounds = new google.maps.LatLngBounds();
			map.setCenter(places[0].geometry.location);
			map.setZoom(14);
		} else {
			alert('Der gesuchte Ort liegt nicht im erfassten Anwendungsgebiet.');
		}
	});

	// Bias the SearchBox results towards places that are within the bounds of the
	// current map's viewport.
	google.maps.event.addListener(map, 'bounds_changed', function() {
		var bounds = map.getBounds();
		searchBox.setBounds(bounds);
	});
}

/**
 * Show measurements as markers on the map
 * The measurements must be collected within 500ms
 */
function showMarkers(query) {
	try {
		var measurements = query.getMeasurements();
		setTimeout(function() {
			for (var i=0, j=0, k=1,l=2,m=3; i < measurements.length; i++,j=j+4,k=k+4,l=l+4,m=m+4) {
				var marker = new google.maps.Marker({
					position: measurements[i].getPoint(),
					icon: 'img/circle.png'
				});
				markers.push(marker);
				markersBounds.extend(measurements[i].getPoint());

				// Variables for Infowindow
					// Create Variables for values
					var val1 = measurements[i].values[j];
					var val2 = measurements[i].values[k];
					var val3 = measurements[i].values[l];
					var val4 = measurements[i].values[m];
					// Create Variables for Phenomenons
					var phen1 = measurements[i].phenomenons[j];
					var phen2 = measurements[i].phenomenons[k];
					var phen3 = measurements[i].phenomenons[l];
					var phen4 = measurements[i].phenomenons[m];
				// Create InfoWindow with the specific Pheonomenons and values to avoid
				// arrangement problems of arrays and parsing
				buildInfoWindow(marker,map,measurements[i],val1,val2,val3,val4,phen1,phen2,phen3,phen4);
			};
			var mcOptions = {gridSize: 50, maxZoom: maxZoomLevelForClusterer};
			mc = new MarkerClusterer(map, markers, mcOptions);
			map.fitBounds(markersBounds);
		}, 500);
	} catch(e) {
		alert(e.message);
	}
}

/**
 * Refresh the markers on the map depending on the current zoom level:
 * Display markers on map for zoom levels higher than maxZoomLevelForClusterer, otherwise display them via MarkerClusterer
 */
function refreshMarkers(zoom) {
	// Create a MarkerClusterer to display the measurements
	if (zoom > maxZoomLevelForClusterer && mcUsedBefore == false) {
		for (var i=0; i < markers.length; i++) {
			markers[i].setMap(null);
		};
		mcUsedBefore = true;
	}
	// Display the measurements directly via markers on the map
	if (zoom <= maxZoomLevelForClusterer && mcUsedBefore == true) {
		for (var i=0; i < markers.length; i++) {
			markers[i].setMap(map);
		};
		mcUsedBefore = false;
	}
}

/**
 * Show InfoWindows on map
 * Creates InfoWindows for every marker on
 * map and in measurement and adds event Listener
 */
function buildInfoWindow(marker,map,measurements,val1,val2,val3,val4,phen1,phen2,phen3,phen4){
	// Setting Content of Infowindow
	var content = '
'+
						''+"ID: "+ measurements.id +
						'
 '+ measurements.timestamp +'
' +
						phen1+ " Value: " + val1+ " " + '
'+
						phen2+ " Value: " + val2+ " " + '
'+
						phen3+ " Value: " + val3+ " " + '
'+
						phen4+ " Value: " + val4+ " " + '
'+

					''+
				'
';
        // ------------------------------------
        // --- Listener for the InfoWindow ---
        // ------------------------------------
        // Open the InfoWindow when a marker is clicked and
        // closes if user "clicks" into map
        // Function to close infowindow is implemented in smartinfowindow.js
		google.maps.event.addListener(marker, 'click', function(e) {
		//Create a Smart Info Window with options
			new SmartInfoWindow({position: marker.getPosition(),map: map,content: content});
		});
		 // -----------------------------------------
        // --- End of Listener for the InfoWindow ---
        // ------------------------------------------
}
// ----------------------------------
// --- End of methods for the map ---
// ----------------------------------<commit_msg>Deleted center position of map<commit_after>/**
 * @author Marius Runde, Daniel Sawatzky, Thiemo Gaertner
 */
// ---------------------------
// --- Methods for the map ---
// ---------------------------
// Variables for the map, markers and markers bounds
var map,
nrwBounds,
markers = [],
mc,
mcUsedBefore = true,
maxZoomLevelForClusterer = 12,
markersBounds = new google.maps.LatLngBounds(),
geocoder = new google.maps.Geocoder();

/**
 * Initialize the map
 */
function initMap() {
	var mapOptions = {
		mapTypeControl: true,
		mapTypeControlOptions: {
			style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
		},
		mapTypeId: google.maps.MapTypeId.ROADMAP,
		minZoom: 8,
		scaleControl: true,
		streetViewControl: false,
		zoomControl: true,
		zoomControlOptions: {
			style: google.maps.ZoomControlStyle.DEFAULT
		}
	};
	map = new google.maps.Map(document.getElementById("map"), mapOptions);

	// Bounds for North-Rhine-Westphalia (NRW)
	nrwBounds = new google.maps.LatLngBounds(
		new google.maps.LatLng(50.3, 5.8), // south west
		new google.maps.LatLng(52.6, 9.5) // north east
	);
	map.fitBounds(nrwBounds);

	// Grey out the rest of the world
	var greyOutPolygon = new google.maps.Polygon({
		clickable: false,
		paths: [nrwBoundaries, everythingElse],
		strokeColor: 'grey',
		strokeOpacity: 0.85,
		strokeWeight: 2,
		fillColor: 'grey',
		fillOpacity: 0.7
	});
	greyOutPolygon.setMap(map);

	// Create the search box and link it to the UI element.
	var input = /** @type {HTMLInputElement} */(document.getElementById('search-input'));
	map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

	var searchBox = new google.maps.places.SearchBox(/** @type {HTMLInputElement} */(input));

	// Listen for the dragend event
	google.maps.event.addListener(map, 'dragend', function() {
		// Is the map still in our bounding box of North-Rhine-Westphalia?
		if (nrwBounds.contains(map.getCenter())) {
			// YES
			return;
		} else {
			// NO
			var c = map.getCenter(),
			x = c.lng(),
			y = c.lat(),
			maxX = nrwBounds.getNorthEast().lng(),
			maxY = nrwBounds.getNorthEast().lat(),
			minX = nrwBounds.getSouthWest().lng(),
			minY = nrwBounds.getSouthWest().lat();

			if (x < minX) x = minX;
			if (x > maxX) x = maxX;
			if (y < minY) y = minY;
			if (y > maxY) y = maxY;

			map.setCenter(new google.maps.LatLng(y, x));
		}
	});

	// Listen for the zoom_changed event to refresh the markers
	google.maps.event.addListener(map, 'zoom_changed', function() {
		refreshMarkers(map.getZoom());
	});

	// Listen for the event fired when the user selects an item from the
	// pick list. Retrieve the matching places for that item.
	google.maps.event.addListener(searchBox, 'places_changed', function() {
		var places = searchBox.getPlaces();
		if (google.maps.geometry.poly.containsLocation(places[0].geometry.location, nrwPolygon)) {
			var bounds = new google.maps.LatLngBounds();
			map.setCenter(places[0].geometry.location);
			map.setZoom(14);
		} else {
			alert('Der gesuchte Ort liegt nicht im erfassten Anwendungsgebiet.');
		}
	});

	// Bias the SearchBox results towards places that are within the bounds of the
	// current map's viewport.
	google.maps.event.addListener(map, 'bounds_changed', function() {
		var bounds = map.getBounds();
		searchBox.setBounds(bounds);
	});
}

/**
 * Show measurements as markers on the map
 * The measurements must be collected within 500ms
 */
function showMarkers(query) {
	try {
		var measurements = query.getMeasurements();
		setTimeout(function() {
			for (var i=0, j=0, k=1,l=2,m=3; i < measurements.length; i++,j=j+4,k=k+4,l=l+4,m=m+4) {
				var marker = new google.maps.Marker({
					position: measurements[i].getPoint(),
					icon: 'img/circle.png'
				});
				markers.push(marker);
				markersBounds.extend(measurements[i].getPoint());

				// Variables for Infowindow
					// Create Variables for values
					var val1 = measurements[i].values[j];
					var val2 = measurements[i].values[k];
					var val3 = measurements[i].values[l];
					var val4 = measurements[i].values[m];
					// Create Variables for Phenomenons
					var phen1 = measurements[i].phenomenons[j];
					var phen2 = measurements[i].phenomenons[k];
					var phen3 = measurements[i].phenomenons[l];
					var phen4 = measurements[i].phenomenons[m];
				// Create InfoWindow with the specific Pheonomenons and values to avoid
				// arrangement problems of arrays and parsing
				buildInfoWindow(marker,map,measurements[i],val1,val2,val3,val4,phen1,phen2,phen3,phen4);
			};
			var mcOptions = {gridSize: 50, maxZoom: maxZoomLevelForClusterer};
			mc = new MarkerClusterer(map, markers, mcOptions);
			map.fitBounds(markersBounds);
		}, 500);
	} catch(e) {
		alert(e.message);
	}
}

/**
 * Refresh the markers on the map depending on the current zoom level:
 * Display markers on map for zoom levels higher than maxZoomLevelForClusterer, otherwise display them via MarkerClusterer
 */
function refreshMarkers(zoom) {
	// Create a MarkerClusterer to display the measurements
	if (zoom > maxZoomLevelForClusterer && mcUsedBefore == false) {
		for (var i=0; i < markers.length; i++) {
			markers[i].setMap(null);
		};
		mcUsedBefore = true;
	}
	// Display the measurements directly via markers on the map
	if (zoom <= maxZoomLevelForClusterer && mcUsedBefore == true) {
		for (var i=0; i < markers.length; i++) {
			markers[i].setMap(map);
		};
		mcUsedBefore = false;
	}
}

/**
 * Show InfoWindows on map
 * Creates InfoWindows for every marker on
 * map and in measurement and adds event Listener
 */
function buildInfoWindow(marker,map,measurements,val1,val2,val3,val4,phen1,phen2,phen3,phen4){
	// Setting Content of Infowindow
	var content = '
'+
						''+"ID: "+ measurements.id +
						'
 '+ measurements.timestamp +'
' +
						phen1+ " Value: " + val1+ " " + '
'+
						phen2+ " Value: " + val2+ " " + '
'+
						phen3+ " Value: " + val3+ " " + '
'+
						phen4+ " Value: " + val4+ " " + '
'+

					''+
				'
';
        // ------------------------------------
        // --- Listener for the InfoWindow ---
        // ------------------------------------
        // Open the InfoWindow when a marker is clicked and
        // closes if user "clicks" into map
        // Function to close infowindow is implemented in smartinfowindow.js
		google.maps.event.addListener(marker, 'click', function(e) {
		//Create a Smart Info Window with options
			new SmartInfoWindow({position: marker.getPosition(),map: map,content: content});
		});
		 // -----------------------------------------
        // --- End of Listener for the InfoWindow ---
        // ------------------------------------------
}
// ----------------------------------
// --- End of methods for the map ---
// ----------------------------------<|endoftext|>


<commit_before>/**
 * Module Dependencies
 */

var _ = require('lodash');
var async = require('async');
var strategies = require('./strategies');

/**
 * Default populateBuffers implementation. Should be good to go on most noSql datastores.
 */

module.exports = function populateBuffers(options, cb) {

  var $find = options.$find;
  var $getPK = options.$getPK;
  var parentCollection = options.parentCollection;
  var buffers = options.buffers;
  var instructions = options.instructions;

  var parentRecords = [];
  var cachedChildren = {};

  async.auto({

    // Grab the parent records for the query
    processParent: function(next) {
      var parentCriteria = _.cloneDeep(options.instructions);
      delete parentCriteria.instructions;

      $find(parentCollection, parentCriteria, function(err, results) {
        if(err) return next(err);
        parentRecords = results;
        buffers.parents = parentRecords;
        next();
      });
    },

    // Build child buffers.
    // For each instruction, loop through the parent records and build up a
    // buffer for the record.
    buildChildBuffers: ['processParent', function(next, results) {
      async.each(_.keys(instructions.instructions), function(population, nextPop) {

        var popInstructions = instructions.instructions[population].instructions;
        var pk = $getPK(popInstructions[0].parent);

        // Use eachSeries here to keep ordering
        async.eachSeries(parentRecords, function(parent, nextParent) {
          var buffer = {
            attrName: population,
            parentPK: parent[pk],
            pkAttr: pk
          };

          var strategy = instructions.instructions[population].strategy.strategy;

          if(strategy === strategies.HAS_FK) {
            buffer.parentFK = parent[instructions.instructions[population].instructions[0].parentKey];
          }

          buffers.add(buffer);
          nextParent();
        }, nextPop);

      }, next);
    }],

    // Process the child results and attach to the buffers
    processChildren: ['buildChildBuffers', function(next, results) {

      // For each buffer build a query to populate it's children records.
      async.each(buffers.read(), function (buffer, next) {

        // Get the instruction set
        var instructionSet = instructions.instructions[buffer.attrName];

        // Cache the strategy
        var strategy = instructionSet.strategy.strategy;

        var childIdentity;

        // •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        // NOTE:
        // This step could be optimized by calculating the query function
        // ahead of time since we already know the association strategy it
        // will use before runtime.
        // •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

        // Special case for VIA_JUNCTOR:
        if (strategy === strategies.VIA_JUNCTOR) {

          var junctorIdentity = instructionSet.instructions[0].child;
          var junctorPK = $getPK(instructionSet.instructions[0].child);
          var junctorFKToParent = instructionSet.instructions[0].childKey;
          var junctorFKToChild = instructionSet.instructions[1] && instructionSet.instructions[1].parentKey;

          childIdentity = instructionSet.instructions[1].child;

          // NOTE:
          // (TODO: look at optimizing this later)
          // I think for this strategy we can always find all of the junctor
          // records relating to ANY of the parent records ahead of time, and
          // the `canCombineChildQueries` distinction is really just limited
          // to that third [set of] quer[ies/y].  For now, we just do a separate
          // query to the junctor for each parent record to keep things tight.
          var junctorCriteria = {where:{}};
          junctorCriteria.where[junctorFKToParent] = buffer.belongsToPKValue;

          $find(junctorIdentity, junctorCriteria, function _afterFetchingJunctorRecords(err, junctorRecordsForThisBuffer) {
            if (err) return next(err);

            // Build criteria to find matching child records which are also
            // related to ANY of the junctor records we just fetched.
            var bufferChildCriteria = _.cloneDeep(instructionSet.instructions[1].criteria);
            var whereObj = {};

            whereObj[instructionSet.instructions[1].childKey] = _.pluck(junctorRecordsForThisBuffer, junctorFKToChild);

            var childPK = $getPK(instructionSet.instructions[1].child);

            // Check if the given where contains the primary key. If so pull it out and check that the
            // value exists in the junctoRecords for this buffer. If so set the array to only contain
            // that value.
            if(bufferChildCriteria.where.hasOwnProperty(childPK)) {
              var pkFilter = _.cloneDeep(bufferChildCriteria.where[childPK]);
              delete bufferChildCriteria.where[childPK];

              if(!Array.isArray(pkFilter)) {
                pkFilter = [pkFilter];
              }

              whereObj[instructionSet.instructions[1].childKey] = _.intersection(whereObj[instructionSet.instructions[1].childKey], pkFilter);
            }

            bufferChildCriteria.where = _.assign(whereObj, bufferChildCriteria.where);

            // Now find related child records
            $find(childIdentity, bufferChildCriteria, function _afterFetchingRelatedChildRecords(err, childRecordsForThisBuffer) {
              if (err) return next(err);

              buffer.records = childRecordsForThisBuffer;
              return next();
            });
          });

        }

        // General case for the other strategies:
        else {

          childIdentity = instructionSet.instructions[0].child;
          var criteriaToPopulateBuffer = _.cloneDeep(instructionSet.instructions[0].criteria);
          var whereObj = {};

          switch (strategy) {
            case strategies.HAS_FK:
              whereObj[instructionSet.instructions[0].childKey] = buffer.belongsToFKValue;
              criteriaToPopulateBuffer.where = _.assign(whereObj, criteriaToPopulateBuffer.where);
              break;
            case strategies.VIA_FK:
              whereObj[instructionSet.instructions[0].childKey] = buffer.belongsToPKValue;
              criteriaToPopulateBuffer.where = _.assign(whereObj, criteriaToPopulateBuffer.where);
              break;
          }

          $find(childIdentity, criteriaToPopulateBuffer, function _afterFetchingBufferRecords(err, childRecordsForThisBuffer) {
            if(err) return next(err);
            buffer.records = childRecordsForThisBuffer;
            return next();
          });
        }

      }, next);
    }]

  }, cb);

};
<commit_msg>fix for empty criteria<commit_after>/**
 * Module Dependencies
 */

var _ = require('lodash');
var async = require('async');
var strategies = require('./strategies');

/**
 * Default populateBuffers implementation. Should be good to go on most noSql datastores.
 */

module.exports = function populateBuffers(options, cb) {

  var $find = options.$find;
  var $getPK = options.$getPK;
  var parentCollection = options.parentCollection;
  var buffers = options.buffers;
  var instructions = options.instructions;

  var parentRecords = [];
  var cachedChildren = {};

  async.auto({

    // Grab the parent records for the query
    processParent: function(next) {
      var parentCriteria = _.cloneDeep(options.instructions);
      delete parentCriteria.instructions;

      $find(parentCollection, parentCriteria, function(err, results) {
        if(err) return next(err);
        parentRecords = results;
        buffers.parents = parentRecords;
        next();
      });
    },

    // Build child buffers.
    // For each instruction, loop through the parent records and build up a
    // buffer for the record.
    buildChildBuffers: ['processParent', function(next, results) {
      async.each(_.keys(instructions.instructions), function(population, nextPop) {

        var popInstructions = instructions.instructions[population].instructions;
        var pk = $getPK(popInstructions[0].parent);

        // Use eachSeries here to keep ordering
        async.eachSeries(parentRecords, function(parent, nextParent) {
          var buffer = {
            attrName: population,
            parentPK: parent[pk],
            pkAttr: pk
          };

          var strategy = instructions.instructions[population].strategy.strategy;

          if(strategy === strategies.HAS_FK) {
            buffer.parentFK = parent[instructions.instructions[population].instructions[0].parentKey];
          }

          buffers.add(buffer);
          nextParent();
        }, nextPop);

      }, next);
    }],

    // Process the child results and attach to the buffers
    processChildren: ['buildChildBuffers', function(next, results) {

      // For each buffer build a query to populate it's children records.
      async.each(buffers.read(), function (buffer, next) {

        // Get the instruction set
        var instructionSet = instructions.instructions[buffer.attrName];

        // Cache the strategy
        var strategy = instructionSet.strategy.strategy;

        var childIdentity;

        // •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        // NOTE:
        // This step could be optimized by calculating the query function
        // ahead of time since we already know the association strategy it
        // will use before runtime.
        // •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

        // Special case for VIA_JUNCTOR:
        if (strategy === strategies.VIA_JUNCTOR) {

          var junctorIdentity = instructionSet.instructions[0].child;
          var junctorPK = $getPK(instructionSet.instructions[0].child);
          var junctorFKToParent = instructionSet.instructions[0].childKey;
          var junctorFKToChild = instructionSet.instructions[1] && instructionSet.instructions[1].parentKey;

          childIdentity = instructionSet.instructions[1].child;

          // NOTE:
          // (TODO: look at optimizing this later)
          // I think for this strategy we can always find all of the junctor
          // records relating to ANY of the parent records ahead of time, and
          // the `canCombineChildQueries` distinction is really just limited
          // to that third [set of] quer[ies/y].  For now, we just do a separate
          // query to the junctor for each parent record to keep things tight.
          var junctorCriteria = {where:{}};
          junctorCriteria.where[junctorFKToParent] = buffer.belongsToPKValue;

          $find(junctorIdentity, junctorCriteria, function _afterFetchingJunctorRecords(err, junctorRecordsForThisBuffer) {
            if (err) return next(err);

            // Build criteria to find matching child records which are also
            // related to ANY of the junctor records we just fetched.
            var bufferChildCriteria = _.cloneDeep(instructionSet.instructions[1].criteria);
            var whereObj = {};

            whereObj[instructionSet.instructions[1].childKey] = _.pluck(junctorRecordsForThisBuffer, junctorFKToChild);

            var childPK = $getPK(instructionSet.instructions[1].child);

            // Check if the given where contains the primary key. If so pull it out and check that the
            // value exists in the junctoRecords for this buffer. If so set the array to only contain
            // that value.
            if(bufferChildCriteria.where.hasOwnProperty(childPK)) {
              var pkFilter = _.cloneDeep(bufferChildCriteria.where[childPK]);
              delete bufferChildCriteria.where[childPK];

              if(!Array.isArray(pkFilter)) {
                pkFilter = [pkFilter];
              }

              whereObj[instructionSet.instructions[1].childKey] = _.intersection(whereObj[instructionSet.instructions[1].childKey], pkFilter);
            }

            bufferChildCriteria.where = _.assign(whereObj, bufferChildCriteria.where);

            // Now find related child records
            $find(childIdentity, bufferChildCriteria, function _afterFetchingRelatedChildRecords(err, childRecordsForThisBuffer) {
              if (err) return next(err);

              buffer.records = childRecordsForThisBuffer;
              return next();
            });
          });

        }

        // General case for the other strategies:
        else {

          childIdentity = instructionSet.instructions[0].child;
          var criteriaToPopulateBuffer = _.cloneDeep(instructionSet.instructions[0].criteria || {});
          var whereObj = {};

          switch (strategy) {
            case strategies.HAS_FK:
              whereObj[instructionSet.instructions[0].childKey] = buffer.belongsToFKValue;
              criteriaToPopulateBuffer.where = _.assign(whereObj, criteriaToPopulateBuffer.where);
              break;
            case strategies.VIA_FK:
              whereObj[instructionSet.instructions[0].childKey] = buffer.belongsToPKValue;
              criteriaToPopulateBuffer.where = _.assign(whereObj, criteriaToPopulateBuffer.where);
              break;
          }

          $find(childIdentity, criteriaToPopulateBuffer, function _afterFetchingBufferRecords(err, childRecordsForThisBuffer) {
            if(err) return next(err);
            buffer.records = childRecordsForThisBuffer;
            return next();
          });
        }

      }, next);
    }]

  }, cb);

};
<|endoftext|>


<commit_before>(function ($) {

	$.fn.extend({
        findWithoutAttr: function (query, attr) {
            var
                self = $(this);

            return self.find(query + ":not([" + attr + "])");
        },

        findByAttr: function (query, attr, value) {
            return $(this).find(query + "[" + attr + "=\"" + value + "\"]");
        },

        replaceToggleClass: function (cls1, cls2) {
            var
                self = $(this);

            if (self.get(0).classList.contains(cls1)) {
                // os métodos próprios do jquery mantém o controle da visibilidade e existência
                self.removeClass(cls1);
                self.addClass(cls2);
            } else if (self.get(0).classList.contains(cls2)) {
                self.removeClass(cls2);
                self.addClass(cls1);
            }

            return self;
        },

        centralizeOn: function (obj) {
            var
                self = $(this);

            self.css({
                top: ($(obj).outerHeight() / 2) - (self.outerHeight() / 2) + "px",
                left: ($(obj).outerWidth() / 2) - (self.outerWidth() / 2) + "px"
            });

            return self;
        },

        textsAsArray: function () {
            var
                arr = [];

            $(this).each(function (i, obj) {
                arr.push(obj.textContent.trim());
            });

            return arr;
        },

        findByContent: function (text) {
            return $(this).contents().filter(function () {
                return $(this).text().trim() === text.trim();
            });
        },

        sortByTextContent: function (order) {
            var
                self = $(this),
                arr = [],
                asArr = [];

            order = order.toLocaleLowerCase();
            asArr = $(this).textsAsArray();

            if (order === "asc") {
                asArr = asArr.asc();
            } else if (order === "desc") {
                asArr = asArr.desc();
            }

            asArr.map(function (text) {
                arr.push(self.parent().findByContent(text).get(0));
            });

            return $(arr);
        }

    });

/*$.fn.replaceClass = (sought, substitute, interval)->
  obj = $(this)
  setTimeout ->
    obj.each (i)->
      current = obj.item(i)
      if current.classList.contains(sought)
        # de repentemente é só remover a classe antiga e adicionar a nova através do jquery, ao invés de fazer via proprio método de manipulação de string
        className = current.className.allReplaced "(#{sought}|\\s#{sought}|#{sought}\\s)", " #{substitute} "
        current.className = className.trim().allReplaced("  ", " ")
  , interval || 0

  obj

})(jQuery);
<commit_msg>ajusta jquery<commit_after>(function ($) {

	$.fn.extend({
        findWithoutAttr: function (query, attr) {
            var
                self = $(this);

            return self.find(query + ":not([" + attr + "])");
        },

        findByAttr: function (query, attr, value) {
            return $(this).find(query + "[" + attr + "=\"" + value + "\"]");
        },

        replaceToggleClass: function (cls1, cls2) {
            var
                self = $(this);

            if (self.get(0).classList.contains(cls1)) {
                // os métodos próprios do jquery mantém o controle da visibilidade e existência
                self.removeClass(cls1);
                self.addClass(cls2);
            } else if (self.get(0).classList.contains(cls2)) {
                self.removeClass(cls2);
                self.addClass(cls1);
            }

            return self;
        },

        centralizeOn: function (obj) {
            var
                self = $(this);

            self.css({
                top: ($(obj).outerHeight() / 2) - (self.outerHeight() / 2) + "px",
                left: ($(obj).outerWidth() / 2) - (self.outerWidth() / 2) + "px"
            });

            return self;
        },

        textsAsArray: function () {
            var
                arr = [];

            $(this).each(function (i, obj) {
                arr.push(obj.textContent.trim());
            });

            return arr;
        },

        findByContent: function (text) {
            return $(this).contents().filter(function () {
                return $(this).text().trim() === text.trim();
            });
        },

        sortByTextContent: function (order) {
            var
                self = $(this),
                arr = [],
                asArr = [];

            order = order.toLocaleLowerCase();
            asArr = $(this).textsAsArray();

            if (order === "asc") {
                asArr = asArr.asc();
            } else if (order === "desc") {
                asArr = asArr.desc();
            }

            asArr.map(function (text) {
                arr.push(self.parent().findByContent(text).get(0));
            });

            return $(arr);
        }

    });

// $.fn.replaceClass = (sought, substitute, interval)->
//   obj = $(this)
//   setTimeout ->
//     obj.each (i)->
//       current = obj.item(i)
//       if current.classList.contains(sought)
//         # de repentemente é só remover a classe antiga e adicionar a nova através do jquery, ao invés de fazer via proprio método de manipulação de string
//         className = current.className.allReplaced "(#{sought}|\\s#{sought}|#{sought}\\s)", " #{substitute} "
//         current.className = className.trim().allReplaced("  ", " ")
//   , interval || 0

//   obj

})(jQuery);
<|endoftext|>


<commit_before>/**
 * Rating control for Swat
 *
 * Copyright (c) 2007 silverorange
 *
 *  Swat is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA  02110-1301  USA
 *
 * This file incorporates work covered by the following copyright and
 * permission notices:
 *
 *     Copyright (c) 2007 Ville Säävuori <Ville@Unessa.net>
 *        http://www.unessa.net/en/hoyci/projects/yui-star-rating/
 *
 *     Copyright (c) 2006 Wil Stuckeys
 *        http://sandbox.wilstuckey.com/jquery-ratings/
 *
 *    Permission is hereby granted, free of charge, to any person
 *    obtaining a copy of this software and associated documentation
 *    files (the "Software"), to deal in the Software without
 *    restriction, including without limitation the rights to use,
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 *    copies of the Software, and to permit persons to whom the
 *    Software is furnished to do so, subject to the following
 *    conditions:
 *
 *    The above copyright notice and this permission notice shall be
 *    included in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *    OTHER DEALINGS IN THE SOFTWARE.
 */

function SwatRating(id, max_value)
{
	this.id        = id;
	this.max_value = max_value;

	this.flydown   = document.getElementById(this.id + '_flydown');
	this.ratingdiv = document.getElementById(this.id);
	this.stardiv   = document.createElement('div');

	YAHOO.util.Event.onDOMReady(this.init, this, true);
}

SwatRating.prototype.init = function()
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Dom.setStyle(this.flydown, 'display', 'none');

	for (var i = 1; i <= this.max_value; i++) {
		var star = document.createElement('div');
		star.id  = this.id + '_star' + i;

		Dom.addClass(star, 'swat-rating-star');
		if (i <= parseInt(this.flydown.value)) {
			Dom.addClass(star, 'swat-rating-selected');
		}

		var anchor  = document.createElement('a');
		anchor.href = '#';

		star.appendChild(anchor);
		this.stardiv.appendChild(star);

		Event.on(star, 'mouseover', this.handleFocus, i, this);
		Event.on(star, 'mouseout', this.handleBlur, this, true);
		Event.on(star, 'click', this.handleClick, i, this);
	}

	var clear = document.createElement('div');
	Dom.setStyle(clear, 'clear', 'both');

	this.ratingdiv.appendChild(this.stardiv);
	this.ratingdiv.appendChild(clear);
}

SwatRating.prototype.handleFocus = function(event, focus_star)
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Event.preventDefault(event);

	// code to handle the focus on the star
	for (var i = 1; i <= focus_star; i++) {
		Dom.addClass(Dom.get(this.id + '_star' + i), 'swat-rating-hover');
	}
}

SwatRating.prototype.handleBlur = function(event)
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Event.preventDefault(event);

	// code to handle movement away from the star
	for (var i = 1; i <= this.max_value; i++) {
		Dom.removeClass(Dom.get(this.id + '_star' + i), 'swat-rating-hover');
	}
}

SwatRating.prototype.handleClick = function(event, clicked_star)
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Event.preventDefault(event);

	// this resets the on style for each star
	for (var i = 1; i <= this.max_value; i++) {
		Dom.removeClass(Dom.get(this.id + '_star' + i), 'swat-rating-selected');
	}

	if (this.flydown.value === clicked_star.toString()) {
		this.flydown.value = null;
		for (var i = 1; i <= this.max_value; i++) {
			Dom.removeClass(Dom.get(this.id + '_star' + i),
				'swat-rating-hover');
		}
		return;
	}

	// this will set the current value of the flydown
	for (var i = 0; i < this.flydown.childNodes.length; i++) {
		var option = this.flydown.childNodes[i];
		if (option.value == clicked_star.toString()) {
			this.flydown.value = clicked_star;
			break;
		}
	}

	// cycle through stars
	for (var i = 1; i <= clicked_star; i++) {
		Dom.addClass(Dom.get(this.id + '_star' + i), 'swat-rating-selected');
	}
}
<commit_msg>Fix flydown clear so you can reset the star rating properly.<commit_after>/**
 * Rating control for Swat
 *
 * Copyright (c) 2007 silverorange
 *
 *  Swat is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA  02110-1301  USA
 *
 * This file incorporates work covered by the following copyright and
 * permission notices:
 *
 *     Copyright (c) 2007 Ville Säävuori <Ville@Unessa.net>
 *        http://www.unessa.net/en/hoyci/projects/yui-star-rating/
 *
 *     Copyright (c) 2006 Wil Stuckeys
 *        http://sandbox.wilstuckey.com/jquery-ratings/
 *
 *    Permission is hereby granted, free of charge, to any person
 *    obtaining a copy of this software and associated documentation
 *    files (the "Software"), to deal in the Software without
 *    restriction, including without limitation the rights to use,
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 *    copies of the Software, and to permit persons to whom the
 *    Software is furnished to do so, subject to the following
 *    conditions:
 *
 *    The above copyright notice and this permission notice shall be
 *    included in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *    OTHER DEALINGS IN THE SOFTWARE.
 */

function SwatRating(id, max_value)
{
	this.id        = id;
	this.max_value = max_value;

	this.flydown   = document.getElementById(this.id + '_flydown');
	this.ratingdiv = document.getElementById(this.id);
	this.stardiv   = document.createElement('div');

	YAHOO.util.Event.onDOMReady(this.init, this, true);
}

SwatRating.prototype.init = function()
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Dom.setStyle(this.flydown, 'display', 'none');

	for (var i = 1; i <= this.max_value; i++) {
		var star = document.createElement('div');
		star.id  = this.id + '_star' + i;

		Dom.addClass(star, 'swat-rating-star');
		if (i <= parseInt(this.flydown.value)) {
			Dom.addClass(star, 'swat-rating-selected');
		}

		var anchor  = document.createElement('a');
		anchor.href = '#';

		star.appendChild(anchor);
		this.stardiv.appendChild(star);

		Event.on(star, 'mouseover', this.handleFocus, i, this);
		Event.on(star, 'mouseout', this.handleBlur, this, true);
		Event.on(star, 'click', this.handleClick, i, this);
	}

	var clear = document.createElement('div');
	Dom.setStyle(clear, 'clear', 'both');

	this.ratingdiv.appendChild(this.stardiv);
	this.ratingdiv.appendChild(clear);
}

SwatRating.prototype.handleFocus = function(event, focus_star)
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Event.preventDefault(event);

	// code to handle the focus on the star
	for (var i = 1; i <= focus_star; i++) {
		Dom.addClass(Dom.get(this.id + '_star' + i), 'swat-rating-hover');
	}
}

SwatRating.prototype.handleBlur = function(event)
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Event.preventDefault(event);

	// code to handle movement away from the star
	for (var i = 1; i <= this.max_value; i++) {
		Dom.removeClass(Dom.get(this.id + '_star' + i), 'swat-rating-hover');
	}
}

SwatRating.prototype.handleClick = function(event, clicked_star)
{
	var Dom   = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

	Event.preventDefault(event);

	// this resets the on style for each star
	for (var i = 1; i <= this.max_value; i++) {
		Dom.removeClass(Dom.get(this.id + '_star' + i), 'swat-rating-selected');
	}

	if (this.flydown.value === clicked_star.toString()) {
		this.flydown.value = '';
		for (var i = 1; i <= this.max_value; i++) {
			Dom.removeClass(Dom.get(this.id + '_star' + i),
				'swat-rating-hover');
		}
		return;
	}

	// this will set the current value of the flydown
	for (var i = 0; i < this.flydown.childNodes.length; i++) {
		var option = this.flydown.childNodes[i];
		if (option.value == clicked_star.toString()) {
			this.flydown.value = clicked_star;
			break;
		}
	}

	// cycle through stars
	for (var i = 1; i <= clicked_star; i++) {
		Dom.addClass(Dom.get(this.id + '_star' + i), 'swat-rating-selected');
	}
}
<|endoftext|>


<commit_before>(function() {
  'use strict';
  return {
    boomerang: window.BOOMR ? window.BOOMR.version : false,
    newrelic: window.newrelic ? true : false,
    jquery: window.jQuery ? window.jQuery.fn.jquery : false,
    gtm: window.google_tag_manager ? true : false,
    ga: window.ga ? true : false,
    piwik: window.Piwik ? true : false
  };
})();
<commit_msg>alphabetic order<commit_after>(function() {
  'use strict';
  return {
    boomerang: window.BOOMR ? window.BOOMR.version : false,
    gtm: window.google_tag_manager ? true : false,
    ga: window.ga ? true : false,
    jquery: window.jQuery ? window.jQuery.fn.jquery : false,
    newrelic: window.newrelic ? true : false,
    piwik: window.Piwik ? true : false
  };
})();
<|endoftext|>


<commit_before>
"use strict";

import ListController from '../controllers/ListController';
import CrudController from '../controllers/CrudController';

let defaults = {
    list: {
        options: {
            controller: ListController,
            controllerAs: 'list'
        }
    },
    create: {
        options: {
            controller: CrudController,
            controllerAs: 'crud'
        },
        resolve: {$mapping: {item: 'Manager'}}
    },
    update: {
        options: {
            controller: CrudController,
            controllerAs: 'crud'
        },
        resolve: {$mapping: {item: 'Manager'}}
    }
};
let interfacer = angular.module('monad.interface', []);

/**
 * Class for objects representing a Monad Component. Usually not instantiated
 * directly but rather via `Monad.component`.
 */
export default class Component {

    /**
     * Class constructor.
     *
     * @param string name The name of this component.
     * @param array dependencies Optional array of Angular dependencies.
     * @param function configFn Optional configuration function.
     * @return self
     */
    constructor(name, dependencies = [], configFn = undefined) {
        /**
         * The name of this Component.
         */
        this.name = name;
        /**
         * This Component's Manager.
         */
        this.$manager = undefined;
        /**
         * Optional Angular dependencies.
         */
        this.dependencies = dependencies;
        /**
         * Optional Angular configuration function.
         */
        this.configFn = configFn;
        /**
         * Internally used array of queued actions to perform on bootstrapping.
         */
        this.queued = [];
        /**
         * Boolean indicating if bootstrap has run for this Component.
         */
        this.$bootstrapped = false;
        /**
         * Default settings for this Component.
         */
        this.defaults = angular.extend({}, defaults);
        /**
         * Actual settings for this Component.
         */
        this.settings = {};
        /**
         * Pointer to the actual Angular module.
         */
        this.ngmod = undefined;

        for (let prop in interfacer) {
            if (typeof interfacer[prop] == 'function') {
                /**
                 * Proxy all Angular methods on angular.module.
                 */
                this[prop] = (...args) => {
                    this.queued.push([prop].concat(args));
                    return this;
                };
            }
        }
    }

    /**
     * Bootstrap this component. Usually called automatically.
     *
     * @return void
     */
    bootstrap() {
        if (this.$bootstrapped) {
            return;
        }
        this.$bootstrapped = true;
        let deps = [];
        this.dependencies.map(dep => {
            if (typeof dep == 'string' && monad.exists(dep)) {
                dep = monad.component(dep);
            }
            if (typeof dep == 'object' && dep instanceof Component) {
                dep.bootstrap();
                deps.push(dep.name);
            } else {
                deps.push(dep);
            }
        });
        this.ngmod = angular.module(this.name, deps, this.configFn);
        this.queued.map(proxy => {
            let fn = proxy.shift();
            if (typeof fn == 'string') {
                this.ngmod[fn](...proxy);
            } else {
                fn.apply(this, proxy);
            }
        });
    }

    /**
     * Let this Component extend other Components.
     *
     * When extending, all properties from Components extended upon are merged
     * into the current Component, unless it specifies an override.
     *
     * @param string|Component component, ... One or more components to extend.
     *  Components can be specified either by their name, or as a Component
     *  object. Components _must_ already exist.
     * @return self
     */
    extend(...components) {
        components.map(component => {
            this.dependencies.push(component);
            if (typeof component == 'string') {
                if (monad.exists(component)) {
                    component = monad.component(component);
                } else {
                    throw `Component ${component} is undefined and cannot be extended upon.`;
                }
            }
            this.defaults = merge(this.defaults, component.defaults);
        });
        return this;
    }

    /**
     * Specify a custom authentication handler for this Component.
     *
     * @param mixed auth An authentication class.
     * @return self
     */
    authentication(auth) {
        this.defaults = merge(this.defaults, {
            list: {resolve: {Authentication: auth}},
            create: {resolve: {Authentication: auth}},
            update: {resolve: {Authentication: auth}}
        });
        return this;
    }

    /**
     * Register a `list` action for this Component.
     *
     * @param string url The URL. `:language` is automatically prepended.
     * @param object options Optional options object.
     * @param object resolve Optional resolve object.
     * @return self
     */
    list(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/list.html';
        // It's easier if we can specify 'columns' on the options:
        if ('columns' in options) {
            let columns = options.columns;
            resolve.columns = () => columns;
            delete options.columns;
        }

        this.settings.list = {url, options, resolve};
        this.queued.push([addTarget, 'list']);
        return this;
    }

    /**
     * Register a `create` action for this Component.
     *
     * @param string url The URL. `:language` is automatically prepended.
     * @param object options Optional options object.
     * @param object resolve Optional resolve object.
     * @return self
     */
    create(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/schema.html';
        delete options.create;
        this.settings.create = {url, options, resolve};
        this.queued.push([addTarget, 'create']);
        return this;
    }

    /**
     * Register an `update` action for this Component. The optional `create`
     * option can specifcy a create-URL as a shorthand (typically create and
     * update will be more or less the same).
     *
     * @param string url The URL. `:language` is automatically prepended.
     * @param object options Optional options object.
     * @param object resolve Optional resolve object.
     * @return self
     */
    update(url, options = {}, resolve = {}) {
        options.templateUrl = options.templateUrl || this.name + '/schema.html';
        if (options.create) {
            this.create(options.create, options, resolve);
            delete options.create;
        }
        this.settings.update = {url, options, resolve};
        this.queued.push([addTarget, 'update']);
        return this;
    }

    /**
     * Register the Manager class for this Component.
     *
     * @param mixed Manager The Manager class to use.
     */
    manager(Manager) {
        this.$manager = {name: normalize(this.name) + 'Manager', obj: Manager};
        this.service(this.$manager.name, this.$manager.obj);
        return this;
    }

};

/**
 * Private helper-functions:
 * {{{
 */
function addTarget(type) {
    let settings = merge(this.defaults[type], this.settings[type]);
    settings.resolve = settings.resolve || {};
    settings.resolve.Manager = settings.resolve.Manager || [normalize(this.name) + 'Manager', Manager => Manager];
    settings.resolve.component = () => this;
    if ('$mapping' in settings.resolve) {
        let $mapping = angular.copy(settings.resolve.$mapping);
        settings.resolve.$mapping = () => $mapping;
    }
    if (type == 'create') {
        settings.resolve.item = [this.$manager.name, Manager => new Manager.constructor.Model];
    } else if (type == 'update' && !settings.resolve.item) {
        settings.resolve.item = ['$route', this.$manager.name, ($route, Manager) => Manager.find($route.current.params)]
    }
    let name;
    if ('Authentication' in settings.resolve) {
        name = normalize(this.name) + '_' + type + 'Authentication';
        this.ngmod.service(name, settings.resolve.Authentication);
    } else {
        name = 'Authentication';
    }
    settings.resolve.Authentication = [name, Authentication => Authentication];
    settings.options.resolve = settings.resolve;
    delete settings.options.template; // Don't do this.
    if (settings.url) {
        this.ngmod.config(['$routeProvider', $routeProvider => {
            $routeProvider.when('/:language' + settings.url, settings.options);
        }]);
    }
};

function normalize(name, replace = undefined) {
    if (replace == undefined) {
        replace = match => match.substring(1).toUpperCase();
    }
    return name.replace(/\/(\w)/g, replace);
};

function merge(...args) {
    let merged = {};
    args.map(arg => {
        if (arg == undefined || arg == null || typeof arg != 'object') {
            return;
        }
        for (let prop in arg) {
            if (!(prop in merged)) {
                merged[prop] = arg[prop];
                continue;
            }
            if (typeof merged[prop] != typeof arg[prop]) {
                merged[prop] = arg[prop];
                continue;
            }
            if (angular.isArray(merged[prop]) != angular.isArray(arg[prop])) {
                merged[prop] = arg[prop];
                continue;
            }
            if (angular.isArray(merged[prop]) && angular.isArray(arg[prop])) {
                arg[prop].map(elem => {
                    if (merged[prop].indexOf(elem) == -1) {
                        merged[prop].push(elem);
                    }
                });
                continue;
            }
            if (typeof arg[prop] != 'object') {
                merged[prop] = arg[prop];
                continue;
            }
            merged[prop] = merge(merged[prop], arg[prop]);
        }
    });
    return merged;
};

/** }}} */

<commit_msg>can go<commit_after><|endoftext|>


<commit_before>import path from 'path';
import webpack from 'webpack';
import Dotenv from 'dotenv-webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';
import TerserWebpackPlugin from 'terser-webpack-plugin';

import {
  includePaths,
  excludePaths,
  nodeModulesPaths,
  loadEnv,
  getBabelRuntimePath,
} from '../config/utils';
import { getPreviewHeadHtml, getPreviewBodyHtml } from '../utils/template';

export default ({
  configDir,
  babelOptions,
  entries,
  outputDir = path.join('.', 'public'),
  quiet,
  packageJson,
  configType,
}) => {
  const { raw, stringified } = loadEnv({ production: true });
  const isProd = configType === 'PRODUCTION';

  return {
    mode: isProd ? 'production' : 'development',
    bail: isProd,
    devtool: '#cheap-module-source-map',
    entry: entries,
    output: {
      path: path.join(process.cwd(), outputDir),
      filename: '[name].[hash].bundle.js',
      publicPath: '',
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: `iframe.html`,
        chunksSortMode: 'none',
        alwaysWriteToDisk: true,
        inject: false,
        templateParameters: (compilation, files, options) => ({
          compilation,
          files,
          options,
          version: packageJson.version,
          headHtmlSnippet: getPreviewHeadHtml(configDir, process.env),
          bodyHtmlSnippet: getPreviewBodyHtml(),
        }),
        template: require.resolve(`../templates/index.ejs`),
      }),
      new webpack.DefinePlugin({ 'process.env': stringified }),
      isProd ? null : new WatchMissingNodeModulesPlugin(nodeModulesPaths),
      isProd ? null : new webpack.HotModuleReplacementPlugin(),
      new CaseSensitivePathsPlugin(),
      quiet ? null : new webpack.ProgressPlugin(),
      new Dotenv({ silent: true }),
    ].filter(Boolean),
    module: {
      rules: [
        {
          test: /\.(mjs|jsx?)$/,
          use: [
            {
              loader: 'babel-loader',
              options: babelOptions,
            },
          ],
          include: includePaths,
          exclude: excludePaths,
        },
        {
          test: /\.md$/,
          use: [
            {
              loader: require.resolve('raw-loader'),
            },
          ],
        },
      ],
    },
    resolve: {
      extensions: ['.mjs', '.js', '.jsx', '.json'],
      modules: ['node_modules'].concat(raw.NODE_PATH || []),
      mainFields: ['browser', 'main', 'module'],
      alias: {
        '@babel/runtime': getBabelRuntimePath(),
      },
    },
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
      runtimeChunk: true,
      minimizer: [
        new TerserWebpackPlugin({
          cache: true,
          parallel: true,
          terserOptions: {
            mangle: false,
          },
        }),
      ],
    },
    performance: {
      hints: isProd ? 'warning' : false,
    },
  };
};
<commit_msg>Set sourceMap for minimizer.<commit_after>import path from 'path';
import webpack from 'webpack';
import Dotenv from 'dotenv-webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';
import TerserWebpackPlugin from 'terser-webpack-plugin';

import {
  includePaths,
  excludePaths,
  nodeModulesPaths,
  loadEnv,
  getBabelRuntimePath,
} from '../config/utils';
import { getPreviewHeadHtml, getPreviewBodyHtml } from '../utils/template';

export default ({
  configDir,
  babelOptions,
  entries,
  outputDir = path.join('.', 'public'),
  quiet,
  packageJson,
  configType,
}) => {
  const { raw, stringified } = loadEnv({ production: true });
  const isProd = configType === 'PRODUCTION';

  return {
    mode: isProd ? 'production' : 'development',
    bail: isProd,
    devtool: '#cheap-module-source-map',
    entry: entries,
    output: {
      path: path.join(process.cwd(), outputDir),
      filename: '[name].[hash].bundle.js',
      publicPath: '',
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: `iframe.html`,
        chunksSortMode: 'none',
        alwaysWriteToDisk: true,
        inject: false,
        templateParameters: (compilation, files, options) => ({
          compilation,
          files,
          options,
          version: packageJson.version,
          headHtmlSnippet: getPreviewHeadHtml(configDir, process.env),
          bodyHtmlSnippet: getPreviewBodyHtml(),
        }),
        template: require.resolve(`../templates/index.ejs`),
      }),
      new webpack.DefinePlugin({ 'process.env': stringified }),
      isProd ? null : new WatchMissingNodeModulesPlugin(nodeModulesPaths),
      isProd ? null : new webpack.HotModuleReplacementPlugin(),
      new CaseSensitivePathsPlugin(),
      quiet ? null : new webpack.ProgressPlugin(),
      new Dotenv({ silent: true }),
    ].filter(Boolean),
    module: {
      rules: [
        {
          test: /\.(mjs|jsx?)$/,
          use: [
            {
              loader: 'babel-loader',
              options: babelOptions,
            },
          ],
          include: includePaths,
          exclude: excludePaths,
        },
        {
          test: /\.md$/,
          use: [
            {
              loader: require.resolve('raw-loader'),
            },
          ],
        },
      ],
    },
    resolve: {
      extensions: ['.mjs', '.js', '.jsx', '.json'],
      modules: ['node_modules'].concat(raw.NODE_PATH || []),
      mainFields: ['browser', 'main', 'module'],
      alias: {
        '@babel/runtime': getBabelRuntimePath(),
      },
    },
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
      runtimeChunk: true,
      minimizer: [
        new TerserWebpackPlugin({
          cache: true,
          parallel: true,
          sourceMap: true,
          terserOptions: {
            mangle: false,
          },
        }),
      ],
    },
    performance: {
      hints: isProd ? 'warning' : false,
    },
  };
};
<|endoftext|>


<commit_before>/* Using the OAB API */

var oab = {

  test : false, // this sends requests with the test parameter set
  debug : true, // this puts the button in debug mode, issues debug warnings

  api_address : 'https://dev.api.openaccessbutton.org', // 'https://api.openaccessbutton.org',

  site_address : 'https://oab.test.cottagelabs.com', // 'https://openaccessbutton.org',

  howto_address : '/howto',

  register_address : '/account',

  bug_address : '/bug',

  messages: 'message', // a div ID name to put error messages etc

  // Tell the API which plugin version is in use for each POST
  signPluginVersion: function(data) {
    // Add the debug key if turned on
    try {
      var manifest = chrome.runtime.getManifest();
      data.plugin = manifest.version_name;
    } catch (err) {
      data.plugin = 'oab_test_page';
    }
    if (oab.test || oab.debug) data.test = true;
    return data;
  },

  sendAvailabilityQuery: function(api_key, url, success_callback, failure_callback) {
    oab.postLocated('/availability', api_key, { url: url }, success_callback, failure_callback)
  },

  sendRequestPost: function(api_key, data, success_callback, failure_callback) {
    var request_id = data._id ? data._id : '';
    oab.postLocated('/request/' + request_id, api_key, data, success_callback, failure_callback)
  },

  sendSupportPost: function(api_key, data, success_callback, failure_callback) {
    var request_id = data._id ? data._id : undefined;
    if ( request_id ) {
      oab.postLocated('/support/' + request_id, api_key, data, success_callback, failure_callback);
    } else {
      // refuse to send
      oab.debugLog('Not sending support post without request ID');
    }
  },

  // try to append location to the data object before POST
  postLocated: function(request_type,key,data,success_callback,error_callback) {
    try {
      if (navigator.geolocation) {
        var opts = {timeout: 5000};
        navigator.geolocation.getCurrentPosition(function (position) {
          data.location = {geo: {lat: position.coords.latitude, lon: position.coords.longitude}};
          oab.postToAPI(request_type,key,data,success_callback,error_callback);
        }, function (error) {
          oab.debugLog(error.message);
          oab.postToAPI(request_type,key,data,success_callback,error_callback);
        }, opts);
      } else {
        // Browser does not support location
        oab.debugLog('GeoLocation is unsupported.');
        oab.postToAPI(request_type,key,data,success_callback,error_callback);
      }
    } catch (e) {
      oab.debugLog("A location error has occurred.");
      oab.postToAPI(request_type,key,data,success_callback,error_callback);
    }
  },

  postToAPI: function(request_type, api_key, data, success_callback, failure_callback) {
    var http = new XMLHttpRequest();
    var url = oab.api_address + request_type;
    http.open("POST", url, true);
    http.setRequestHeader("Content-type", "application/json; charset=utf-8");
    if (api_key !== undefined) http.setRequestHeader("x-apikey", api_key);
    http.onreadystatechange = function() {
      if (http.readyState == XMLHttpRequest.DONE) {
        http.status === 200 ? success_callback(JSON.parse(http.response)) : failure_callback(http);
      }
    }
    http.send(JSON.stringify(this.signPluginVersion(data)));
    oab.debugLog('POST to ' + request_type + ' ' + JSON.stringify(data));
  },

  displayMessage: function(msg, div, type) {
    if (div === undefined) div = document.getElementById(oab.messages);
    if (type === undefined) {
      type = '';
    } else if ( type === 'error' ) {
      type = 'alert-danger';
    }
    div.innerHTML = '
' + msg + '
';
  },

  handleAPIError: function(data, displayError) {
    var error_text = '';
    if (data.status === 400) {
      error_text = 'Sorry, the page you are on is not one that we can check availability for. See the instructions for help.';
    } else if (data.status === 401) {
      error_text = "Unauthorised - check your API key is valid. Go to ";
      error_text += '';
      error_text += oab.site_address + oab.register_address + " and sign up if you have not already done so. Once you are signed in the plugin should find your API key for you.";
    } else if (data.status === 403) {
      error_text = "Forbidden - please file a bug.";
    } else {
      error_text = data.status + ". Sorry, unknown error, perhaps the system is offline, or you are offline. Please file a bug including this code: " + data.status;
    }
    if (error_text !== '') {
      error_text = '

' + error_text;
      document.getElementById('loading_area').className = 'row collapse';
      oab.displayMessage(error_text, undefined, 'error');
      if (chrome && chrome.tabs) {
        if ( document.getElementById('goto_instructions') ) {
          document.getElementById('goto_instructions').onclick = function () {
            chrome.tabs.create({'url': oab.site_address + oab.howto_address});
          };
        }
        if ( document.getElementById('goto_register') ) {
          document.getElementById('goto_register').onclick = function () {
            chrome.tabs.create({'url': oab.site_address + oab.register_address});
          };
        }
      }
    }
  },

  debugLog : function(message) {
    if (oab.debug) {
      console.log(message)
    }
  }
};<commit_msg>set dev url wrong, fixing<commit_after>/* Using the OAB API */

var oab = {

  test : false, // this sends requests with the test parameter set
  debug : true, // this puts the button in debug mode, issues debug warnings

  api_address : 'https://dev.api.cottagelabs.com', // 'https://api.openaccessbutton.org',

  site_address : 'https://oab.test.cottagelabs.com', // 'https://openaccessbutton.org',

  howto_address : '/howto',

  register_address : '/account',

  bug_address : '/bug',

  messages: 'message', // a div ID name to put error messages etc

  // Tell the API which plugin version is in use for each POST
  signPluginVersion: function(data) {
    // Add the debug key if turned on
    try {
      var manifest = chrome.runtime.getManifest();
      data.plugin = manifest.version_name;
    } catch (err) {
      data.plugin = 'oab_test_page';
    }
    if (oab.test || oab.debug) data.test = true;
    return data;
  },

  sendAvailabilityQuery: function(api_key, url, success_callback, failure_callback) {
    oab.postLocated('/availability', api_key, { url: url }, success_callback, failure_callback)
  },

  sendRequestPost: function(api_key, data, success_callback, failure_callback) {
    var request_id = data._id ? data._id : '';
    oab.postLocated('/request/' + request_id, api_key, data, success_callback, failure_callback)
  },

  sendSupportPost: function(api_key, data, success_callback, failure_callback) {
    var request_id = data._id ? data._id : undefined;
    if ( request_id ) {
      oab.postLocated('/support/' + request_id, api_key, data, success_callback, failure_callback);
    } else {
      // refuse to send
      oab.debugLog('Not sending support post without request ID');
    }
  },

  // try to append location to the data object before POST
  postLocated: function(request_type,key,data,success_callback,error_callback) {
    try {
      if (navigator.geolocation) {
        var opts = {timeout: 5000};
        navigator.geolocation.getCurrentPosition(function (position) {
          data.location = {geo: {lat: position.coords.latitude, lon: position.coords.longitude}};
          oab.postToAPI(request_type,key,data,success_callback,error_callback);
        }, function (error) {
          oab.debugLog(error.message);
          oab.postToAPI(request_type,key,data,success_callback,error_callback);
        }, opts);
      } else {
        // Browser does not support location
        oab.debugLog('GeoLocation is unsupported.');
        oab.postToAPI(request_type,key,data,success_callback,error_callback);
      }
    } catch (e) {
      oab.debugLog("A location error has occurred.");
      oab.postToAPI(request_type,key,data,success_callback,error_callback);
    }
  },

  postToAPI: function(request_type, api_key, data, success_callback, failure_callback) {
    var http = new XMLHttpRequest();
    var url = oab.api_address + request_type;
    http.open("POST", url, true);
    http.setRequestHeader("Content-type", "application/json; charset=utf-8");
    if (api_key !== undefined) http.setRequestHeader("x-apikey", api_key);
    http.onreadystatechange = function() {
      if (http.readyState == XMLHttpRequest.DONE) {
        http.status === 200 ? success_callback(JSON.parse(http.response)) : failure_callback(http);
      }
    }
    http.send(JSON.stringify(this.signPluginVersion(data)));
    oab.debugLog('POST to ' + request_type + ' ' + JSON.stringify(data));
  },

  displayMessage: function(msg, div, type) {
    if (div === undefined) div = document.getElementById(oab.messages);
    if (type === undefined) {
      type = '';
    } else if ( type === 'error' ) {
      type = 'alert-danger';
    }
    div.innerHTML = '
' + msg + '
';
  },

  handleAPIError: function(data, displayError) {
    var error_text = '';
    if (data.status === 400) {
      error_text = 'Sorry, the page you are on is not one that we can check availability for. See the instructions for help.';
    } else if (data.status === 401) {
      error_text = "Unauthorised - check your API key is valid. Go to ";
      error_text += '';
      error_text += oab.site_address + oab.register_address + " and sign up if you have not already done so. Once you are signed in the plugin should find your API key for you.";
    } else if (data.status === 403) {
      error_text = "Forbidden - please file a bug.";
    } else {
      error_text = data.status + ". Sorry, unknown error, perhaps the system is offline, or you are offline. Please file a bug including this code: " + data.status;
    }
    if (error_text !== '') {
      error_text = '

' + error_text;
      document.getElementById('loading_area').className = 'row collapse';
      oab.displayMessage(error_text, undefined, 'error');
      if (chrome && chrome.tabs) {
        if ( document.getElementById('goto_instructions') ) {
          document.getElementById('goto_instructions').onclick = function () {
            chrome.tabs.create({'url': oab.site_address + oab.howto_address});
          };
        }
        if ( document.getElementById('goto_register') ) {
          document.getElementById('goto_register').onclick = function () {
            chrome.tabs.create({'url': oab.site_address + oab.register_address});
          };
        }
      }
    }
  },

  debugLog : function(message) {
    if (oab.debug) {
      console.log(message)
    }
  }
};<|endoftext|>


<commit_before>//removes the player and resets him if he dies
//adds gold
//manages creeps
game.GameTimerManager = Object.extend({
	init: function(x, y, settings){
		this.now = new Date().getTime();
		this.lastCreep = new Date().getTime();
		//creepe cannot pause at all
		this.paused = false;
		this.alwaysUpdate = true;
	},

	update: function(){
		this.now = new Date().getTime();
		this.goldTimerCheck();
		this.creepTimerCheck();

		return true;
	},
	//organizes code above
	goldTimerCheck: function(){
		//controls when the creep spons
		if(Math.round(this.now/1000)%20 ===0 && (this.now - this.lastCreep >= 1000)){
			game.data.gold += (game.data.exp1+1);
			console.log("Current gold: " + game.data.gold);

		}
	},
	creepTimerCheck: function(){
		//controls when the creep spons
		if(Math.round(this.now/1000)%10 ===0 && (this.now - this.lastCreep >= 1000)){
			//controls when the creep spons
			this.lastCreep = this.now;
			//bulids a creep and puts it into the world
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			me.game.world.addChild(creepe, 5);

			//var creepe1 = me.pool.pull("Player2", 1000, 0, {});
			//me.game.world.addChild(creepe, 5);

		}
	}
});

//manages the players death
//oragnizes the code
game.HeroDeathManager = Object.extend({
	init: function(x, y, settings){
		this.alwaysUpdate = true;

	},

	update: function(){
		//dead function in game manager
		if(game.data.player.dead){
			me.game.world.removeChild(game.data.player);
			me.state.current().resetPlayer(10, 0);
		}
		return true;
	}
});

//gains the player expeience if they win
game.ExperienceManager = Object.extend({
	init: function (x, y, settings) {
		this.alwaysUpdate = true;
		this.gameover = false;
	},

	update: function(){
		if(game.data.win === true && !this.gameover){
			//the game is over when the player dies
			this.gameOver(true);
		}else if(game.data.win === false && !this.gameover){
			this.gameOver(false);
			//this.gameOver = true;
			//saves current game variable
			//me.save.exp = game.data.exp;
		}
		console.log(game.data.exp);

		return true;
	},
	//organizes update function
	//game over function
	gameOver: function(win){
		if(win){
			game.data.exp += 10;
		}else{
			game.data.exp += 1;
		}
		    console.log(game.data.exp);
			this.gameover = true;
			//saves the 5 exp variables in game.js
			me.save.exp = game.data.exp;

	}
});

game.SpendGold = Object.extend({
	init: function (x, y, settings){
		this.now = new Date().getTime();
		this.lastBuy = new Date().getTime();
		//creepe cannot pause at all
		this.paused = false;
		this.alwaysUpdate = true;
		this.updateWhenPaused = true;
		this.buying = false;
	},

	update: function(){
		this.now = new Date().getTime();

		if(me.input.isKeyPressed("buy") && this.now-this.lastBuy >=1000){
			this.lastBuy = this.now;
			if(!this.buying){
				this.startBuying();
			}else{
				this.stopBuying();
			}
		}

		//checks the buy keys below
		this.checkBuyKeys();

		return true;

	},

//enables player to buy certain level ups by pussing f keys
	startBuying: function(){
		this.buying = true;
		me.state.pause(me.state.PLAY);
		game.data.pausePos = me.game.viewport.localToWorld(0, 0);
		game.data.buyscreen = new me.Sprite(game.data.pausePos.x, game.data.pausePos.y, me.loader.getImage('gold-screen'));
		game.data.buyscreen.updateWhenPaused = true;
		game.data.buyscreen.setOpacity(0.8);
		me.game.world.addChild(game.data.buyscreen, 34);
		game.data.player.body.setVelocity(0, 0);
		me.state.pause(me.state.PLAY);
		me.input.bindKey(me.input.KEY.F1, "F1", true);
		me.input.bindKey(me.input.KEY.F2, "F2", true);
		me.input.bindKey(me.input.KEY.F3, "F3", true);
		me.input.bindKey(me.input.KEY.F4, "F4", true);
		me.input.bindKey(me.input.KEY.F5, "F5", true);
		me.input.bindKey(me.input.KEY.F6, "F6", true);
		this.setBuyText();
	},

	setBuyText: function(){
		//adds the word awesomenauts to the game
		game.data.buytext = new (me.Renderable.extend({
			init: function(){
				this._super(me.Renderable, 'init', [game.data.pausePos.x, game.data.pausePos.y, 300, 50]);
				this.font = new me.Font("Arial", 26, "white");
				this.updateWhenPaused = true;
				this.alwaysUpdate = true;
				//me.input.registerPointerEvent('pointerdown', this, this.newGame.bind(this), true);
			},

			//function renderer tells the font size of the words in quotations
			draw: function(renderer){
				this.font.draw(renderer.getContext(), "PRESS F1-F6 TO BUY, B TO EXIT. Current Gold: " + game.data.gold, this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "Skill 1: Increase Damage. Current Level: " + game.data.skill1 + " Cost: " + ((game.data.exp1+1)*10);
				this.font.draw(renderer.getContext(), "Skill 2: Run Faster! Current Level: " + game.data.skill2 + " Cost: " + ((game.data.exp2+1)*10), this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "Skill 3: Increase Health. Current Level:  " + game.data.skill3 + " Cost: " + ((game.data.exp1+1)*10), this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "O Ability: Speed Burst. Current Level: " + game.data.ability1 + " Cost: " + ((game.data.ability4+1)*10), this.pos.y);
				this.font.draw(renderer.getContext(), "W Ability: Eat Your Creep for Health: " + game.data.ability2 + " Cost: " + ((game.data.ability5+1)*10), this.pos.y);
				this.font.draw(renderer.getContext(), "E Ability: Throw Your Spear: " + game.data.ability3 + " Cost: " + ((game.data.ability6+1)*10), this.pos.y);

			}

		})));
		me.game.world.addChild(game.data.buytext, 35);
	},

//reverse function. enables the player to not buy or undo the buy
	stopBuying: function(){
		this.buying = false;
		me.state.resume(me.state.PLAY);
		game.data.player.body.setVelocity(game.data.playerMoveSpeed, 20);
		me.game.world.removeChild(game.data.buyscreen);
		me.input.unbindKey(me.input.KEY.F1, "F1", true);
		me.input.unbindKey(me.input.KEY.F2, "F2", true);
		me.input.unbindKey(me.input.KEY.F3, "F3", true);
		me.input.unbindKey(me.input.KEY.F4, "F4", true);
		me.input.unbindKey(me.input.KEY.F5, "F5", true);
		me.input.unbindKey(me.input.KEY.F6, "F6", true);
		me.game.world.removeChild(game.data.buytext);
	}

//check that the buy keys are working
checkBuyKeys: function(){
	if(me.input.isKeyPressed("F1")){
		//checks the cost of the key pressed
		if(this.checkCost(1)){

		}
	}else if(me.input.isKeyPressed("F2")){

	}else if(me.input.isKeyPressed("F3")){

	}else if(me.input.isKeyPressed("F4")){

	}else if(me.input.isKeyPressed("F5")){

	}else if(me.input.isKeyPressed("F6")){

	}
},
//checks the cost of the key pressed
checkCost: function(){

}

});
// video 50,
<commit_msg>video 50 coded and commented<commit_after>//removes the player and resets him if he dies
//adds gold
//manages creeps
game.GameTimerManager = Object.extend({
	init: function(x, y, settings){
		this.now = new Date().getTime();
		this.lastCreep = new Date().getTime();
		//creepe cannot pause at all
		this.paused = false;
		this.alwaysUpdate = true;
	},

	update: function(){
		this.now = new Date().getTime();
		this.goldTimerCheck();
		this.creepTimerCheck();

		return true;
	},
	//organizes code above
	goldTimerCheck: function(){
		//controls when the creep spons
		if(Math.round(this.now/1000)%20 ===0 && (this.now - this.lastCreep >= 1000)){
			game.data.gold += (game.data.exp1+1);
			console.log("Current gold: " + game.data.gold);

		}
	},
	creepTimerCheck: function(){
		//controls when the creep spons
		if(Math.round(this.now/1000)%10 ===0 && (this.now - this.lastCreep >= 1000)){
			//controls when the creep spons
			this.lastCreep = this.now;
			//bulids a creep and puts it into the world
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			me.game.world.addChild(creepe, 5);

			//var creepe1 = me.pool.pull("Player2", 1000, 0, {});
			//me.game.world.addChild(creepe, 5);

		}
	}
});

//manages the players death
//oragnizes the code
game.HeroDeathManager = Object.extend({
	init: function(x, y, settings){
		this.alwaysUpdate = true;

	},

	update: function(){
		//dead function in game manager
		if(game.data.player.dead){
			me.game.world.removeChild(game.data.player);
			me.state.current().resetPlayer(10, 0);
		}
		return true;
	}
});

//gains the player expeience if they win
game.ExperienceManager = Object.extend({
	init: function (x, y, settings) {
		this.alwaysUpdate = true;
		this.gameover = false;
	},

	update: function(){
		if(game.data.win === true && !this.gameover){
			//the game is over when the player dies
			this.gameOver(true);
		}else if(game.data.win === false && !this.gameover){
			this.gameOver(false);
			//this.gameOver = true;
			//saves current game variable
			//me.save.exp = game.data.exp;
		}
		console.log(game.data.exp);

		return true;
	},
	//organizes update function
	//game over function
	gameOver: function(win){
		if(win){
			game.data.exp += 10;
		}else{
			game.data.exp += 1;
		}
		    console.log(game.data.exp);
			this.gameover = true;
			//saves the 5 exp variables in game.js
			me.save.exp = game.data.exp;

	}
});

game.SpendGold = Object.extend({
	init: function (x, y, settings){
		this.now = new Date().getTime();
		this.lastBuy = new Date().getTime();
		//creepe cannot pause at all
		this.paused = false;
		this.alwaysUpdate = true;
		this.updateWhenPaused = true;
		this.buying = false;
	},

	update: function(){
		this.now = new Date().getTime();

		if(me.input.isKeyPressed("buy") && this.now-this.lastBuy >=1000){
			this.lastBuy = this.now;
			if(!this.buying){
				this.startBuying();
			}else{
				this.stopBuying();
			}
		}

		//checks the buy keys below
		this.checkBuyKeys();

		return true;

	},

//enables player to buy certain level ups by pussing f keys
	startBuying: function(){
		this.buying = true;
		me.state.pause(me.state.PLAY);
		game.data.pausePos = me.game.viewport.localToWorld(0, 0);
		game.data.buyscreen = new me.Sprite(game.data.pausePos.x, game.data.pausePos.y, me.loader.getImage('gold-screen'));
		game.data.buyscreen.updateWhenPaused = true;
		game.data.buyscreen.setOpacity(0.8);
		me.game.world.addChild(game.data.buyscreen, 34);
		game.data.player.body.setVelocity(0, 0);
		me.state.pause(me.state.PLAY);
		me.input.bindKey(me.input.KEY.F1, "F1", true);
		me.input.bindKey(me.input.KEY.F2, "F2", true);
		me.input.bindKey(me.input.KEY.F3, "F3", true);
		me.input.bindKey(me.input.KEY.F4, "F4", true);
		me.input.bindKey(me.input.KEY.F5, "F5", true);
		me.input.bindKey(me.input.KEY.F6, "F6", true);
		this.setBuyText();
	},

	setBuyText: function(){
		//adds the word awesomenauts to the game
		game.data.buytext = new (me.Renderable.extend({
			init: function(){
				this._super(me.Renderable, 'init', [game.data.pausePos.x, game.data.pausePos.y, 300, 50]);
				this.font = new me.Font("Arial", 26, "white");
				this.updateWhenPaused = true;
				this.alwaysUpdate = true;
				//me.input.registerPointerEvent('pointerdown', this, this.newGame.bind(this), true);
			},

			//function renderer tells the font size of the words in quotations
			draw: function(renderer){
				this.font.draw(renderer.getContext(), "PRESS F1-F6 TO BUY, B TO EXIT. Current Gold: " + game.data.gold, this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "Skill 1: Increase Damage. Current Level: " + game.data.skill1 + " Cost: " + ((game.data.skill1+1)*10), this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "Skill 2: Run Faster! Current Level: " + game.data.skill2 + " Cost: " + ((game.data.skill2+1)*10), this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "Skill 3: Increase Health. Current Level:  " + game.data.skill3 + " Cost: " + ((game.data.skill3+1)*10), this.pos.x, this.pos.y);
				this.font.draw(renderer.getContext(), "O Ability: Speed Burst. Current Level: " + game.data.ability1 + " Cost: " + ((game.data.ability1+1)*10), this.pos.y);
				this.font.draw(renderer.getContext(), "W Ability: Eat Your Creep for Health: " + game.data.ability2 + " Cost: " + ((game.data.ability2+1)*10), this.pos.y);
				this.font.draw(renderer.getContext(), "E Ability: Throw Your Spear: " + game.data.ability3 + " Cost: " + ((game.data.ability3+1)*10), this.pos.x, this.pos.y);

			}

		})));
		me.game.world.addChild(game.data.buytext, 35);
	},

//reverse function. enables the player to not buy or undo the buy
	stopBuying: function(){
		this.buying = false;
		me.state.resume(me.state.PLAY);
		game.data.player.body.setVelocity(game.data.playerMoveSpeed, 20);
		me.game.world.removeChild(game.data.buyscreen);
		me.input.unbindKey(me.input.KEY.F1, "F1", true);
		me.input.unbindKey(me.input.KEY.F2, "F2", true);
		me.input.unbindKey(me.input.KEY.F3, "F3", true);
		me.input.unbindKey(me.input.KEY.F4, "F4", true);
		me.input.unbindKey(me.input.KEY.F5, "F5", true);
		me.input.unbindKey(me.input.KEY.F6, "F6", true);
		me.game.world.removeChild(game.data.buytext);
	}

//check that the buy keys are working
checkBuyKeys: function(){
	if(me.input.isKeyPressed("F1")){
		//checks the cost of the key pressed
		if(this.checkCost(1)){
			//checks if the player bought the upgrade
			this.makePurchase(1);
		}
	}else if(me.input.isKeyPressed("F2")){
		//checks the cost of the key pressed
		if(this.checkCost(2)){
			//checks if the player bought the upgrade
			this.makePurchase(2);
		}
	}else if(me.input.isKeyPressed("F3")){
		//checks the cost of the key pressed
		if(this.checkCost(3)){
			//checks if the player bought the upgrade
			this.makePurchase(3);
		}
	}else if(me.input.isKeyPressed("F4")){
		//checks the cost of the key pressed
		if(this.checkCost(4)){
			//checks if the player bought the upgrade
			this.makePurchase(4);
		}
	}else if(me.input.isKeyPressed("F5")){
		//checks the cost of the key pressed
		if(this.checkCost(5)){
			//checks if the player bought the upgrade
			this.makePurchase(5);
		}
	}else if(me.input.isKeyPressed("F6")){
		//checks the cost of the key pressed
		if(this.checkCost(6)){
			//checks if the player bought the upgrade
			this.makePurchase(6);
		}
	}
},
//checks the cost of the key pressed
checkCost: function(skill){
	//if the key is pressed and if the player has the money the skill will be achieved
	if(skill===1 && (game.data.gold >= ((game.data.skill1+1)*10))){
		return true;
	}//if the key is pressed and if the player has the money the skill will be achieved
	else if(skill===2 && (game.data.gold >= ((game.data.skill2+1)*10))){
		return true;
	}//if the key is pressed and if the player has the money the skill will be achieved
	else if(skill===3 && (game.data.gold >= ((game.data.skill3+1)*10))){
		return true;
	}//if the key is pressed and if the player has the money the skill will be achieved
	else if(skill===4 && (game.data.gold >= ((game.data.ability1+1)*10))){
		return true;
	}//if the key is pressed and if the player has the money the skill will be achieved
	else if(skill===5 && (game.data.gold >= ((game.data.ability2+1)*10))){
		return true;
	}//if the key is pressed and if the player has the money the skill will be achieved
	else if(skill===6 && (game.data.gold >= ((game.data.ability3+1)*10))){
		return true;
		//if the player does not have the money they will not get the skill
	}else{
		return false;
	}
},
//enables the purchase to be made
makePurchase: function(skill){
	if(skill === 1){
		game.data.gold -= ((game.data.skill1 + 1)* 10);
		game.data.skill += 1;
		game.data.player.attack += 1;
	}else if(skill ===2){
		game.data.gold -= ((game.data.skill2 + 1)* 10);
		game.data.skill2 += 1;
	}else if(skill ===3){
		game.data.gold -= ((game.data.skill3 + 1)* 10);
		game.data.skill3 += 1;
	}else if(skill ===4){
		game.data.gold -= ((game.data.ability1 + 1)* 10);
		game.data.ability1 += 1;
	}else if(skill ===5){
		game.data.gold -= ((game.data.ability2 + 1)* 10);
		game.data.ability2 += 1;
	}else if(skill ===6){
		game.data.gold -= ((game.data.ability3 + 1)* 10);
		game.data.ability3 += 1;
	}
}

});

<|endoftext|>