<commit_before>// (C) Copyright 2014-2015 Hewlett Packard Enterprise Development LP

var React = require('react');
var Leaflet = require('leaflet');
var Section = require('grommet/components/Section');
var Rest = require('grommet/utils/Rest');

var Map = React.createClass({

  propTypes: {
    city: React.PropTypes.string,
    country: React.PropTypes.string,
    latitude: React.PropTypes.string,
    longitude: React.PropTypes.string,
    postalCode: React.PropTypes.string,
    state: React.PropTypes.string,
    street: React.PropTypes.string,
    title: React.PropTypes.string
  },

  getInitialState: function () {
    return {
      busy: false,
      latitude: this.props.latitude,
      longitude: this.props.longitude
    };
  },

  componentDidMount: function () {
    if (! this.state.map) {
      var mapElement = this.refs.map;
      var options = {
        touchZoom: false,
        scrollWheelZoom: false
      };
      var map = Leaflet.map(mapElement, options);
      this.setState({map: map});
    }

    if (! this.state.latitude || ! this.state.longitude) {
      this._getGeocode(this.props);
    } else {
      this._setMap();
    }
  },

  componentWillReceiveProps: function (newProps) {
    this.setState({latitude: newProps.latitude, longitude: newProps.longitude}, function () {
      if (! this.state.latitude || ! this.state.longitude) {
        this._getGeocode(newProps);
      } else {
        this._setMap();
      }
    });
  },

  _setMap: function () {
    var map = this.state.map;
    map.setView([this.state.latitude, this.state.longitude], 14);
    Leaflet.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 19,
      attribution: '© OpenStreetMap'
    }).addTo(map);
    var circle = Leaflet.circleMarker([this.state.latitude, this.state.longitude], {
      color: '#FF8D6D',
      opacity: 0.8,
      fillOpacity: 0.8
    }).addTo(map);
    var address = '
' + this.props.title + '
' + this._renderAddress().join('
');
    circle.bindPopup(address).openPopup();
  },

  _onGeocodeResponse: function (err, res) {
    if (! err && res.ok && res.body && res.body[0]) {
      var place = res.body[0];
      this.setState({latitude: place.lat, longitude: place.lon}, this._setMap);
    } else {
      console.log('!!! geocode response error', err, res);
      if (this.state.map) {
        this.state.map.remove();
        this.refs.map.className = "";
      }
      this.setState({map: null});
    }
    this.setState({busy: false});
  },

  _getGeocode: function (props) {
    if (props.street) {
      this.setState({busy: true, place: null});
      var params = {
        street: props.street.replace(/.+? \$ /g, '').replace('  BP1220', ''),
        city: props.city,
        state: props.state,
        country: props.country,
        format: 'json'
      };
      Rest
        .get("http://nominatim.openstreetmap.org/search", params)
        .end(this._onGeocodeResponse);
    }
  },

  _renderAddress: function () {
    return [this.props.street, this.props.city, this.props.state, this.props.postalCode, this.props.country];
  },

  render: function() {
    var address;
    if (! this.state.busy && ! this.state.latitude) {
      address = (

          {this._renderAddress().map(function (e, i) {
            return
{e}
;
          })}

      );
    }
    return (

        {address}

    );
  }

});

module.exports = Map;
<commit_msg>Added 4 atempts to find addresses.<commit_after>// (C) Copyright 2014-2015 Hewlett Packard Enterprise Development LP

var React = require('react');
var Leaflet = require('leaflet');
var Section = require('grommet/components/Section');
var Rest = require('grommet/utils/Rest');

var Map = React.createClass({

  propTypes: {
    city: React.PropTypes.string,
    country: React.PropTypes.string,
    latitude: React.PropTypes.string,
    longitude: React.PropTypes.string,
    postalCode: React.PropTypes.string,
    state: React.PropTypes.string,
    street: React.PropTypes.string,
    title: React.PropTypes.string
  },

  getInitialState: function () {
    return {
      busy: false,
      latitude: this.props.latitude,
      longitude: this.props.longitude
    };
  },

  componentDidMount: function () {
    if (! this.state.map) {
      var mapElement = this.refs.map;
      var options = {
        touchZoom: false,
        scrollWheelZoom: false
      };
      var map = Leaflet.map(mapElement, options);
      this.setState({map: map});
    }

    if (! this.state.latitude || ! this.state.longitude) {
      this._getGeocode(this.props);
    } else {
      this._setMap();
    }
  },

  componentWillReceiveProps: function (newProps) {
    this.setState({latitude: newProps.latitude, longitude: newProps.longitude}, function () {
      if (! this.state.latitude || ! this.state.longitude) {
        this._getGeocode(newProps);
      } else {
        this._setMap();
      }
    });
  },

  _setMap: function (mapSize) {
    var map = this.state.map;
    map.setView([this.state.latitude, this.state.longitude], mapSize || 14);
    Leaflet.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 19,
      attribution: '© OpenStreetMap'
    }).addTo(map);
    var circle = Leaflet.circleMarker([this.state.latitude, this.state.longitude], {
      color: '#FF8D6D',
      opacity: 0.8,
      fillOpacity: 0.8
    }).addTo(map);
    var address = '
' + this.props.title + '
' + this._renderAddress().join('
');
    circle.bindPopup(address).openPopup();
  },

  _getGeocode: function (props, atempts) {
    if (props.country) {
      var params = {
        state: props.state,
        country: props.country,
        format: 'json'
      };

      if (!atempts) {
        atempts = 1;
        this.setState({busy: true, place: null});

        if (props.street) {
          params.street = props.street.replace(/.+? \$ /g, '').replace('  BP1220', '');
        }

        if (props.postalCode) {
          params.postalcode = props.postalCode.split('-')[0];
        }
      } else if (atempts === 3) {
        params = {
          city: props.city,
          country: props.country,
          format: 'json'
        };
      } else if (atempts === 4) {
        params = {
          country: props.country,
          format: 'json'
        };
      }

      // need to change map zoom depending on the number of atempts
      var mapSize = {
        1: 14,
        2: 10,
        3: 10,
        4: 5
      };

      Rest
        .get("http://nominatim.openstreetmap.org/search", params)
        .end(function (err, res) {
          if (! err && res.ok && res.body && res.body[0]) {
            var place = res.body[0];
            console.log(atempts);
            this.setState(
              {latitude: place.lat, longitude: place.lon, busy: false},
              this._setMap.bind(this, mapSize[atempts])
            );
          } else if (atempts < 4) {
            this._getGeocode(props, ++atempts);
          } else {
            console.log('!!! geocode response error', err, res);
            if (this.state.map) {
              this.state.map.remove();
              this.refs.map.className = "";
            }
            this.setState({map: null, busy: false});
          }
        }.bind(this));
    }
  },

  _renderAddress: function () {
    return [this.props.street, this.props.city, this.props.state, this.props.postalCode, this.props.country];
  },

  render: function() {
    var address;
    if (! this.state.busy && ! this.state.latitude) {
      address = (

          {this._renderAddress().map(function (e, i) {
            return
{e}
;
          })}

      );
    }
    return (

        {address}

    );
  }

});

module.exports = Map;
<|endoftext|>


<commit_before>(function($) {
	$.entwine('ss.zenvalidator', function($) {

		$('form.parsley').entwine({
			onmatch: function() {
					// Fix validation for optionset based class (attributes not set on child options)
					$(this).find('.optionset').each(function() {
						var attrs = $.makeArray(this.attributes);
						var parsley = {};
						for(var i=0; i < attrs.length; i++) {
							var att = attrs[i];
							if(att.name.indexOf('parsley-') !== -1) {
								parsley[att.name] = att.value;
							}
						}
						$(this).find('input').attr(parsley);

						// Clean attributes
						var attributes = this.attributes;
						var keys = $.map(attributes , function(key, value) {
							return key.name;
						});
						for(var i = 0; i < keys.length; i++) {
							if (keys[i].indexOf('data-parsley') === 0) {
								$(this).removeAttr(keys[i]);
							}
						}
						$(this).removeData();
					});

        			$(this).parsley({
            				excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], .ignore-validation',
							errorsContainer: function (el) {
								return el.$element.closest(".field");
							}
        			});
			}
		});

		// Listen for error message when doing remote validation
		// See issue https://github.com/guillaumepotier/Parsley.js/issues/560
		$.listen('parsley:field:error', function(fieldInstance) {
			if(!fieldInstance._xhr) {
				return;
			}
			if(fieldInstance._xhr.status < 400 || fieldInstance._xhr.status > 499) {
				return;
			}
			fieldInstance.options['remoteMessage'] = fieldInstance._xhr.responseText;
		});

		// Add action to submitted form for parsley.remote
		// See issue https://github.com/guillaumepotier/Parsley.js/issues/826
		var submitActor = null;
		$('form.parsley [type=submit]').click(function() {
			submitActor = $(this);
		});
		$.listen('parsley:form:success', function(formInstance) {
			if(submitActor) {
				formInstance.$element.find('input.parsley-submit-actor').remove();
				formInstance.$element.append('<input class="parsley-submit-actor" type="hidden" name="'+submitActor.attr('name')+'" value="'+submitActor.attr('value')+'" />');
			}
			// If no action is specified, default action (the first) is used by Silverstripe (eg: if form is submitted with enter)
		});

		// Bypass validation on :hidden fields
		$.listen('parsley:field:validated', function(fieldInstance){
		    if (fieldInstance.$element.is(":hidden")) {
		        fieldInstance._ui.$errorsWrapper.css('display', 'none');
		        fieldInstance.validationResult = true;
		    }
		});

		$('.field').entwine({

			getFormField: function() {
				return this.find('[name='+this.getFieldName()+'], [name="'+this.getFieldName()+'[]"]');
			},

			getFieldName: function() {
				return this.attr('id');
			},

			getFieldValue: function() {
				return this.getFormField().val();
			},

			evaluateEqualTo: function(val) {
				return this.getFieldValue() === val;
			},

			evaluateNotEqualTo: function(val) {
				return this.getFieldValue() !== val;
			},

			evaluateLessThan: function(val) {
				num = parseFloat(val);
				return this.getFieldValue() < num;
			},

			evaluateGreaterThan: function(val) {
				num = parseFloat(val);
				return parseFloat(this.getFieldValue()) > num;
			},

			evaluateContains: function(val) {
				return this.getFieldValue().match(val) !== null;
			},

			evaluateEmpty: function() {
				return $.trim(this.getFieldValue()).length === 0;
			},

			evaluateNotEmpty: function() {
				return !this.evaluateEmpty();
			},

			evaluateChecked: function() {
				return this.getFormField().is(":checked");
			}

		});

		$('.field.validation-logic').entwine({
			onmatch: function () {
				masters = this.getMasters();
				for(m in masters) {
					this.closest('form').find('#'+masters[m]).addClass("validation-logic-master");
				}
			},

			getLogic: function() {
				return $.trim(this.getFormField().data('validation-logic-eval'));
			},

			parseLogic: function() {
				js = this.getLogic();
				result = eval(js);
				return result;
			},

			getMasters: function() {
				var field = this.getFormField();
				if(!field.length) {
					return new Array();
				}
				return field.data('validation-logic-masters').split(",");
			}

		});

		$('.field.optionset').entwine({

			getFormField: function() {
				f = this._super().filter(":checked");
				return f;
			}

		});

		$('.field.optionset.checkboxset').entwine({

			evaluateHasCheckedOption: function(val) {
				this.find(':checkbox').filter(':checked').each(function() {
					return $(this).val() === val || $(this).getLabel() === val;
				});
			},

			evaluateHasCheckedAtLeast: function(num) {
				return this.find(':checked').length >= num;
			},

			evaluateHasCheckedLessThan: function(num) {
				return this.find(':checked').length <= num;
			}
		});

		$('.field input[type=checkbox]').entwine({
			getLabel: function() {
				return this.closest('form').find('label[for='+this.attr('id')+']');
			}
		});

		$('.field.validation-logic.validation-logic-validate').entwine({
			testLogic: function() {
				this.getFormField().toggleClass('ignore-validation', this.parseLogic());
			}
		});

		$('.field.validation-logic.validation-logic-exclude').entwine({
			testLogic: function() {
				if(!this.parseLogic()){
					this.find('ul.parsley-errors-list').hide();
				}else{
					this.find('ul.parsley-errors-list').show();
				}
				this.getFormField().toggleClass('ignore-validation', !this.parseLogic());
			}
		});

		$('.field.validation-logic-master :text, .field.validation-logic-master select').entwine({
			onmatch: function() {
				this.closest(".field").notify();
			},

			onchange: function() {
				this.closest(".field").notify();
			}
		});

		$('.field.validation-logic-master :checkbox, .field.validation-logic-master :radio').entwine({
			onmatch: function() {
				this.closest(".field").notify();
			},

			onclick: function() {
				this.closest(".field").notify();
			}
		});

		$('.field.validation-logic-master').entwine({
			Listeners: null,

			notify: function() {
				$.each(this.getListeners(), function() {
					$(this).testLogic();
				});
			},

			getListeners: function() {
				if(l = this._super()) {
					return l;
				}
				var self = this;
				var listeners = [];
				this.closest("form").find('.validation-logic').each(function() {
					masters = $(this).getMasters();
					for(m in masters) {
						if(masters[m] == self.attr('id')) {
							listeners.push($(this));
							break;
						}
					}
				});
				this.setListeners(listeners);
				return this.getListeners();
			}
		});
	});

})(jQuery);
<commit_msg>improve bypass when remote validation is used<commit_after>(function($) {
	$.entwine('ss.zenvalidator', function($) {

		$('form.parsley').entwine({
			onmatch: function() {
					// Fix validation for optionset based class (attributes not set on child options)
					$(this).find('.optionset').each(function() {
						var attrs = $.makeArray(this.attributes);
						var parsley = {};
						for(var i=0; i < attrs.length; i++) {
							var att = attrs[i];
							if(att.name.indexOf('parsley-') !== -1) {
								parsley[att.name] = att.value;
							}
						}
						$(this).find('input').attr(parsley);

						// Clean attributes
						var attributes = this.attributes;
						var keys = $.map(attributes , function(key, value) {
							return key.name;
						});
						for(var i = 0; i < keys.length; i++) {
							if (keys[i].indexOf('data-parsley') === 0) {
								$(this).removeAttr(keys[i]);
							}
						}
						$(this).removeData();
					});

        			$(this).parsley({
            				excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], .ignore-validation',
							errorsContainer: function (el) {
								return el.$element.closest(".field");
							}
        			});
			}
		});

		// Listen for error message when doing remote validation
		// See issue https://github.com/guillaumepotier/Parsley.js/issues/560
		$.listen('parsley:field:error', function(fieldInstance) {
			if(!fieldInstance._xhr) {
				return;
			}
			if(fieldInstance._xhr.status < 400 || fieldInstance._xhr.status > 499) {
				return;
			}
			fieldInstance.options['remoteMessage'] = fieldInstance._xhr.responseText;
		});

		// Add action to submitted form for parsley.remote
		// See issue https://github.com/guillaumepotier/Parsley.js/issues/826
		var submitActor = null;
		$('form.parsley [type=submit]').click(function() {
			submitActor = $(this);
		});
		$.listen('parsley:form:success', function(formInstance) {
			if(submitActor) {
				formInstance.$element.find('input.parsley-submit-actor').remove();
				formInstance.$element.append('<input class="parsley-submit-actor" type="hidden" name="'+submitActor.attr('name')+'" value="'+submitActor.attr('value')+'" />');
			}
			// If no action is specified, default action (the first) is used by Silverstripe (eg: if form is submitted with enter)
		});

		// Bypass validation on :hidden fields
		$.listen('parsley:field:validate', function(fieldInstance){
		    if (fieldInstance.$element.is(":hidden")) {
				fieldInstance._asyncIsValidField = function() {
					deferred = $.Deferred();
					return deferred.resolveWith(this);
				};
		    }
		});
		$.listen('parsley:field:validated', function(fieldInstance){
		    if (fieldInstance.$element.is(":hidden")) {
		        fieldInstance._ui.$errorsWrapper.css('display', 'none');
		        fieldInstance.validationResult = true;
		    }
		});

		$('.field').entwine({

			getFormField: function() {
				return this.find('[name='+this.getFieldName()+'], [name="'+this.getFieldName()+'[]"]');
			},

			getFieldName: function() {
				return this.attr('id');
			},

			getFieldValue: function() {
				return this.getFormField().val();
			},

			evaluateEqualTo: function(val) {
				return this.getFieldValue() === val;
			},

			evaluateNotEqualTo: function(val) {
				return this.getFieldValue() !== val;
			},

			evaluateLessThan: function(val) {
				num = parseFloat(val);
				return this.getFieldValue() < num;
			},

			evaluateGreaterThan: function(val) {
				num = parseFloat(val);
				return parseFloat(this.getFieldValue()) > num;
			},

			evaluateContains: function(val) {
				return this.getFieldValue().match(val) !== null;
			},

			evaluateEmpty: function() {
				return $.trim(this.getFieldValue()).length === 0;
			},

			evaluateNotEmpty: function() {
				return !this.evaluateEmpty();
			},

			evaluateChecked: function() {
				return this.getFormField().is(":checked");
			}

		});

		$('.field.validation-logic').entwine({
			onmatch: function () {
				masters = this.getMasters();
				for(m in masters) {
					this.closest('form').find('#'+masters[m]).addClass("validation-logic-master");
				}
			},

			getLogic: function() {
				return $.trim(this.getFormField().data('validation-logic-eval'));
			},

			parseLogic: function() {
				js = this.getLogic();
				result = eval(js);
				return result;
			},

			getMasters: function() {
				var field = this.getFormField();
				if(!field.length) {
					return new Array();
				}
				return field.data('validation-logic-masters').split(",");
			}

		});

		$('.field.optionset').entwine({

			getFormField: function() {
				f = this._super().filter(":checked");
				return f;
			}

		});

		$('.field.optionset.checkboxset').entwine({

			evaluateHasCheckedOption: function(val) {
				this.find(':checkbox').filter(':checked').each(function() {
					return $(this).val() === val || $(this).getLabel() === val;
				});
			},

			evaluateHasCheckedAtLeast: function(num) {
				return this.find(':checked').length >= num;
			},

			evaluateHasCheckedLessThan: function(num) {
				return this.find(':checked').length <= num;
			}
		});

		$('.field input[type=checkbox]').entwine({
			getLabel: function() {
				return this.closest('form').find('label[for='+this.attr('id')+']');
			}
		});

		$('.field.validation-logic.validation-logic-validate').entwine({
			testLogic: function() {
				this.getFormField().toggleClass('ignore-validation', this.parseLogic());
			}
		});

		$('.field.validation-logic.validation-logic-exclude').entwine({
			testLogic: function() {
				if(!this.parseLogic()){
					this.find('ul.parsley-errors-list').hide();
				}else{
					this.find('ul.parsley-errors-list').show();
				}
				this.getFormField().toggleClass('ignore-validation', !this.parseLogic());
			}
		});

		$('.field.validation-logic-master :text, .field.validation-logic-master select').entwine({
			onmatch: function() {
				this.closest(".field").notify();
			},

			onchange: function() {
				this.closest(".field").notify();
			}
		});

		$('.field.validation-logic-master :checkbox, .field.validation-logic-master :radio').entwine({
			onmatch: function() {
				this.closest(".field").notify();
			},

			onclick: function() {
				this.closest(".field").notify();
			}
		});

		$('.field.validation-logic-master').entwine({
			Listeners: null,

			notify: function() {
				$.each(this.getListeners(), function() {
					$(this).testLogic();
				});
			},

			getListeners: function() {
				if(l = this._super()) {
					return l;
				}
				var self = this;
				var listeners = [];
				this.closest("form").find('.validation-logic').each(function() {
					masters = $(this).getMasters();
					for(m in masters) {
						if(masters[m] == self.attr('id')) {
							listeners.push($(this));
							break;
						}
					}
				});
				this.setListeners(listeners);
				return this.getListeners();
			}
		});
	});

})(jQuery);
<|endoftext|>


<commit_before>(function() { //IIFE

    var DJANGO_SERVER_URL = "https://cryptic-citadel-5628.herokuapp.com/api";
    var FIREBASE_SERVER_URL = "https://tanks-for-waiting.firebaseio.com";

    angular.module('tanks-for-waiting').controller('GameController', GameController);
    GameController.$inject = ['$scope', '$http', '$interval', '$firebaseObject', '$firebaseArray'];

    function GameController($scope, $http, $interval, $firebaseObject, $firebaseArray) {

        var firebasePlayerRef = null;
        var playerID = null; //player_id stored here
        var gameID = null; //game_id stored here
        $scope.gameRunning = false;
        $scope.score = 0;
        /*
        *This begins the process of game selection.
        POST to /players/ for player_id
        Returns player_id
        Stores player_id
        POST to games/player_id
        Returns game_id
        Stores game_id
        Starts game
        */
        $scope.startGame = function() {
            $http.post(DJANGO_SERVER_URL + "/players/")
                .then(function(response) {
                    playerID = response.data.player_id;
                    //this is where I would display the tutorial
                    $http.post(DJANGO_SERVER_URL + "/games/", {
                            player_id: playerID
                        })
                        .then(function(response) {
                                gameID = response.data.game_id;
                                firebasePlayerRef = new Firebase(FIREBASE_SERVER_URL + "/games/" + gameID + "/tanks/" + playerID); //websocket to firebase api
                                var playerObj = $firebaseObject(firebasePlayerRef); //websocket to firebase api
                                playerObj.$bindTo($scope, "player").then(function() {
                                    console.log($scope.player);
                                    new Game("screen");
                                });
                                firebaseScoreRef = new Firebase(FIREBASE_SERVER_URL + "/games/" + gameID + "/scores/" + playerID);
                                var scoreObj = $firebaseObject(firebaseScoreRef);
                                scoreObj.$bindTo($scope, "score").then(function() {
                                    console.log($scope.score);
                                });
                            },
                            function(errobj) {
                                alert("Game request failed: " + JSON.stringify(errobj, null, 2));
                            });
                }, function(errobj) {
                    alert("Player request failed: " + JSON.stringify(errobj));
                });
            console.log("click");
        };

        var Game = function(canvasId) { //holds all the main game code
            var canvas = document.getElementById(canvasId); //get the canvas into my game
            var screen = canvas.getContext('2d'); //var screen will allow me to draw to the canvas. "2d" leads to the creation of a CanvasRenderingContext2D object representing a two-dimensional rendering context.
            var gameSize = {
                x: canvas.width,
                y: canvas.height
            }; // stores the width and height of the canvas for later use for placing entities on the canvas

            var self = this;
            //initalizing the targets
            firebaseTargetsRef = new Firebase(FIREBASE_SERVER_URL + "/games/" + gameID + "/targets/");
            var targetsObj = $firebaseObject(firebaseTargetsRef);
            $firebaseArray(firebaseTargetsRef).$loaded()
                .then(function(targets) {
                    self.targets = self.refreshTargets(this, targets);
                    $scope.gameRunning = true;
                    $interval(function() {
                        if (self.isReady) { //heartbeat of the game (interval runs about 60 times a second)
                            self.update(); //updates the screen
                            self.draw(screen, gameSize); //based upon what's happening in the game
                        }
                    }, 16.7);
                }, function() {
                    console.log("Failed to load targets");
                });

            var targetAdded = function() {
                if ($scope.gameRunning) {
                    console.log("it was hit");
                    $firebaseArray(firebaseTargetsRef).$loaded()
                        .then(function(targets) {
                            self.targets = self.refreshTargets(this, targets);
                        });
                }

            };
            var targetRemoved = function(dataSnapshot) {
                var destroyedTarget = dataSnapshot.val();
            };

            firebaseTargetsRef.on("child_added", targetAdded,
                function(err) {
                    console.log("failed");
                });
            firebaseTargetsRef.on("child_removed", targetRemoved,
                function(err) {
                    console.log("failed");
                });

            this.tanks = [new Player(this, $scope.player)]; //will hold all of the tanks in the game

            this.walls = [
                // left outter wall
                new Wall(this, 40, 40, 45, 460),
                new Wall(this, 40, 40, 225, 45),
                new Wall(this, 40, 460, 225, 455),
                //right outer wall
                new Wall(this, 275, 40, 460, 45),
                new Wall(this, 460, 40, 455, 460),
                new Wall(this, 275, 455, 455, 460),
                //top center wall
                new Wall(this, 80, 80, 420, 85),
                new Wall(this, 80, 80, 85, 225),
                new Wall(this, 415, 80, 420, 225),
                //bottom center wall
                new Wall(this, 80, 275, 85, 420),
                new Wall(this, 85, 415, 420, 420),
                new Wall(this, 415, 275, 420, 420),
                //left center wall
                new Wall(this, 225, 145, 230, 350),
                new Wall(this, 120, 250, 225, 255),
                //right center wall
                new Wall(this, 275, 145, 280, 350),
                new Wall(this, 275, 250, 380, 255)
            ];
        };

        Game.prototype = {

            isReady: true,

            update: function() { //updates the movement of all the on screen entities
                for (var i = 0; i < this.tanks.length; i++) {
                    this.tanks[i].update();
                }

                var thisPlayer = this.tanks[0];

                var deleteError = function(errobj) {
                    console.log('Error deleting target: ' + JSON.stringify(errobj));
                };

                var deleteSuccess = function(response) {
                    console.log(response);
                };
                $scope.player.x = thisPlayer.location().x;
                $scope.player.y = thisPlayer.location().y;
                $scope.player.direction = thisPlayer.direction;

                for (i = 0; i < this.targets.length; i++) {
                    if (collidingTarget(thisPlayer, this.targets[i])) {
                        this.targets[i].fillStyle = 'black';
                        console.log(this.targets[i].target_id);
                        if (this.targets[i].is_hit === 0) {
                            this.targets[i].is_hit = 1;
                            $http.delete(DJANGO_SERVER_URL + "/games/" + gameID + "/targets/" + this.targets[i].target_id + "/", {

                                data: playerID

                            }).then(deleteSuccess, deleteError);

                        }
                    }
                }
                this.tanks = this.tanks.slice(0, 1);
            },

            draw: function(screen, gameSize) {
                screen.clearRect(0, 0, gameSize.x, gameSize.y);

                for (i = 0; i < this.targets.length; i++) { //This loop draws the targets
                    drawTarget(screen, this.targets[i]);
                }

                for (i = 0; i < this.walls.length; i++) { //This loop draws the walls
                    this.walls[i].draw(screen);
                }

                for (var i = 0; i < this.tanks.length; i++) { //This loop draws the tanks
                    drawTank(screen, this.tanks[i]);
                    if (i === 0) {
                        if (this.tanks[i].direction === "W") {
                            drawDrillHeadLeft(screen, this.tanks[i]);
                        } else if (this.tanks[i].direction === "E") {
                            drawDrillHeadRight(screen, this.tanks[i]);
                        } else if (this.tanks[i].direction === "N") {
                            drawDrillHeadUp(screen, this.tanks[i]);
                        } else if (this.tanks[i].direction === "S") {
                            drawDrillHeadDown(screen, this.tanks[i]);
                        }
                    }
                }
            },

            refreshTanks: function(thisGame) {
                var tanks = [];
                for (var key in $scope.game.tanks) {
                    if (key !== playerID) {
                        tanks.push(new Player(this, $scope.game.tanks[key]));
                    }
                }
                return tanks;
            },

            refreshTargets: function(thisGame, firebaseTargets) {
                var targets = [];
                for (var i = 0; i < firebaseTargets.length; i++) {
                    targets.push(new Target(thisGame, firebaseTargets[i]));
                }
                return targets;
            }
        };
        var Player = function(game, location) {
            this.game = game;
            this.direction = "E";
            this.size = {
                x: 16,
                y: 16
            }; //player size
            this.center = {
                x: location.x,
                y: location.y
            }; //tells the game where the player is at the start
            this.keyboarder = new Keyboarder();
        };

        Player.prototype = {

            location: function() {
                return this.center;
            },

            update: function() {
                var wallHit = false;
                for (i = 0; i < this.game.walls.length; i++) {
                    if (collidingWall(this, this.game.walls[i])) {
                        console.log("Wall!");
                        wallHit = true;
                        break;
                    }
                }

                if (this.keyboarder.isDown(this.keyboarder.KEYS.LEFT)) {
                    this.direction = "W";
                    if (wallHit) {
                        this.center.x += 8;
                    } else if (this.center.x <= 10) {
                        this.center.x = 8;
                    } else {
                        this.center.x -= 2;
                    }
                } else if (this.keyboarder.isDown(this.keyboarder.KEYS.RIGHT)) {
                    this.direction = "E";
                    if (wallHit) {
                        this.center.x -= 8;
                    } else if (this.center.x >= 490) {
                        this.center.x = 492;
                    } else {
                        this.center.x += 2;
                    }
                } else if (this.keyboarder.isDown(this.keyboarder.KEYS.UP)) {
                    this.direction = "N";

                    if (wallHit) {
                        this.center.y += 8;
                    } else if (this.center.y <= 10) {
                        this.center.y = 8;
                    } else {
                        this.center.y -= 2;
                    }
                } else if (this.keyboarder.isDown(this.keyboarder.KEYS.DOWN)) {
                    this.direction = "S";

                    if (wallHit) {
                        this.center.y -= 8;
                    } else if (this.center.y >= 490) {
                        this.center.y = 492;
                    } else {
                        this.center.y += 2;
                    }
                }
            }
        };

        var Target = function(game, firebaseTarget) {
            this.game = game;
            this.size = {
                x: 10,
                y: 10
            }; //player size
            this.center = {
                x: firebaseTarget.x,
                y: firebaseTarget.y
            }; //tells the game where the targets are at the moment, starting at half way through the screen and just above the bottom
            this.target_id = firebaseTarget.$id;
            this.is_hit = 0;
            this.fillStyle = "red";
        };

        Target.prototype = {
            update: function() {
                console.log("helllo");
            }
        };

        var Wall = function(game, xmin, ymin, xmax, ymax) {
            this.game = game;
            this.xmin = xmin;
            this.ymin = ymin;
            this.xmax = xmax;
            this.ymax = ymax;
        };

        Wall.prototype = {
            draw: function(screen) {
                screen.fillStyle = 'white';
                screen.fillRect(this.xmin, //x coordinate
                    this.ymin, // y coordinate
                    this.xmax - this.xmin, //width
                    this.ymax - this.ymin); //height
            }
        };

        var drawTank = function(screen, body) {
            //tank body
            screen.fillStyle = 'green';
            screen.fillRect(body.center.x - body.size.x / 2, //x coordinate
                body.center.y - body.size.y / 2, // y coordinate
                body.size.x, body.size.y); //width and hieght
        };

        var drawDrillHeadLeft = function(screen, body) {
            screen.fillRect(body.center.x - body.size.x / 2 - 4, body.center.y - 2, 4, 4);
        };

        var drawDrillHeadRight = function(screen, body) {
            screen.fillRect(body.center.x + body.size.x / 2, body.center.y - 2, 4, 4);
        };

        var drawDrillHeadUp = function(screen, body) {
            screen.fillRect(body.center.x - 2, body.center.y - body.size.y / 2 - 4, 4, 4);
        };

        var drawDrillHeadDown = function(screen, body) {
            screen.fillRect(body.center.x - 2, body.center.y + body.size.y / 2, 4, 4);
        };

        var drawTarget = function(screen, target) {
            screen.fillStyle = target.fillStyle;
            screen.fillRect(target.center.x - target.size.x / 2, //x coordinate
                target.center.y - target.size.y / 2, // y coordinate
                target.size.x, target.size.y);
        };

        var Keyboarder = function() { //handles keyboard input
            var keyState = {}; //records if any key that's been pressed is pressed or released
            var keyPressed = false;
            var self = this;

            window.onkeydown = function(e) {
                e.preventDefault();
                if (e.keyCode >= self.KEYS.LEFT &&
                    e.keyCode <= self.KEYS.DOWN &&
                    !keyPressed) {
                    keyState[e.keyCode] = true;
                    keyPressed = true;
                    e.preventDefault();
                }
            };

            window.onkeyup = function(e) {
                e.preventDefault();
                if (e.keyCode >= self.KEYS.LEFT &&
                    e.keyCode <= self.KEYS.DOWN &&
                    keyPressed) {
                    keyState = {};
                    keyPressed = false;
                }
            };

            this.isDown = function(keyCode) {
                return keyState[keyCode] === true;
            };

            this.KEYS = {
                LEFT: 37,
                UP: 38,
                RIGHT: 39,
                DOWN: 40
            };
        };

        var collidingTarget = function(b1, b2) {
            return !(b1 === b2 ||
                b1.center.x + b1.size.x / 2 < b2.center.x - b2.size.x / 2 ||
                b1.center.y + b1.size.y / 2 < b2.center.y - b2.size.y / 2 ||
                b1.center.x - b1.size.x / 2 > b2.center.x + b2.size.x / 2 ||
                b1.center.y - b1.size.y / 2 > b2.center.y + b2.size.y / 2);
        };

        var collidingWall = function(b1, b2) {
            return (((b1.center.x - b1.size.x / 2) < b2.xmax) &&
                ((b1.center.x + b1.size.x / 2) > b2.xmin) &&
                ((b1.center.y - b1.size.y / 2) < b2.ymax) &&
                ((b1.center.y + b1.size.y / 2) > b2.ymin));
        };
    }

})(); // End of IIFE

//Credit to Mary Rose Cook's Video tutorial introducing game concepts in javascript
// https://vimeo.com/105955605
<commit_msg>fixed bug where epreventDefault messed up landing page google form<commit_after>(function() { //IIFE

    var DJANGO_SERVER_URL = "https://cryptic-citadel-5628.herokuapp.com/api";
    var FIREBASE_SERVER_URL = "https://tanks-for-waiting.firebaseio.com";

    angular.module('tanks-for-waiting').controller('GameController', GameController);
    GameController.$inject = ['$scope', '$http', '$interval', '$firebaseObject', '$firebaseArray'];

    function GameController($scope, $http, $interval, $firebaseObject, $firebaseArray) {

        var firebasePlayerRef = null;
        var playerID = null; //player_id stored here
        var gameID = null; //game_id stored here
        $scope.gameRunning = false;
        $scope.score = 0;
        /*
        *This begins the process of game selection.
        POST to /players/ for player_id
        Returns player_id
        Stores player_id
        POST to games/player_id
        Returns game_id
        Stores game_id
        Starts game
        */
        $scope.startGame = function() {
            $http.post(DJANGO_SERVER_URL + "/players/")
                .then(function(response) {
                    playerID = response.data.player_id;
                    //this is where I would display the tutorial
                    $http.post(DJANGO_SERVER_URL + "/games/", {
                            player_id: playerID
                        })
                        .then(function(response) {
                                gameID = response.data.game_id;
                                firebasePlayerRef = new Firebase(FIREBASE_SERVER_URL + "/games/" + gameID + "/tanks/" + playerID); //websocket to firebase api
                                var playerObj = $firebaseObject(firebasePlayerRef); //websocket to firebase api
                                playerObj.$bindTo($scope, "player").then(function() {
                                    console.log($scope.player);
                                    new Game("screen");
                                });
                                firebaseScoreRef = new Firebase(FIREBASE_SERVER_URL + "/games/" + gameID + "/scores/" + playerID);
                                var scoreObj = $firebaseObject(firebaseScoreRef);
                                scoreObj.$bindTo($scope, "score").then(function() {
                                    console.log($scope.score);
                                });
                            },
                            function(errobj) {
                                alert("Game request failed: " + JSON.stringify(errobj, null, 2));
                            });
                }, function(errobj) {
                    alert("Player request failed: " + JSON.stringify(errobj));
                });
            console.log("click");
        };

        var Game = function(canvasId) { //holds all the main game code
            var canvas = document.getElementById(canvasId); //get the canvas into my game
            var screen = canvas.getContext('2d'); //var screen will allow me to draw to the canvas. "2d" leads to the creation of a CanvasRenderingContext2D object representing a two-dimensional rendering context.
            var gameSize = {
                x: canvas.width,
                y: canvas.height
            }; // stores the width and height of the canvas for later use for placing entities on the canvas

            var self = this;
            //initalizing the targets
            firebaseTargetsRef = new Firebase(FIREBASE_SERVER_URL + "/games/" + gameID + "/targets/");
            var targetsObj = $firebaseObject(firebaseTargetsRef);
            $firebaseArray(firebaseTargetsRef).$loaded()
                .then(function(targets) {
                    self.targets = self.refreshTargets(this, targets);
                    $scope.gameRunning = true;
                    $interval(function() {
                        if (self.isReady) { //heartbeat of the game (interval runs about 60 times a second)
                            self.update(); //updates the screen
                            self.draw(screen, gameSize); //based upon what's happening in the game
                        }
                    }, 16.7);
                }, function() {
                    console.log("Failed to load targets");
                });

            var targetAdded = function() {
                if ($scope.gameRunning) {
                    console.log("it was hit");
                    $firebaseArray(firebaseTargetsRef).$loaded()
                        .then(function(targets) {
                            self.targets = self.refreshTargets(this, targets);
                        });
                }

            };
            var targetRemoved = function(dataSnapshot) {
                var destroyedTarget = dataSnapshot.val();
            };

            firebaseTargetsRef.on("child_added", targetAdded,
                function(err) {
                    console.log("failed");
                });
            firebaseTargetsRef.on("child_removed", targetRemoved,
                function(err) {
                    console.log("failed");
                });

            this.tanks = [new Player(this, $scope.player)]; //will hold all of the tanks in the game

            this.walls = [
                // left outter wall
                new Wall(this, 40, 40, 45, 460),
                new Wall(this, 40, 40, 225, 45),
                new Wall(this, 40, 460, 225, 455),
                //right outer wall
                new Wall(this, 275, 40, 460, 45),
                new Wall(this, 460, 40, 455, 460),
                new Wall(this, 275, 455, 455, 460),
                //top center wall
                new Wall(this, 80, 80, 420, 85),
                new Wall(this, 80, 80, 85, 225),
                new Wall(this, 415, 80, 420, 225),
                //bottom center wall
                new Wall(this, 80, 275, 85, 420),
                new Wall(this, 85, 415, 420, 420),
                new Wall(this, 415, 275, 420, 420),
                //left center wall
                new Wall(this, 225, 145, 230, 350),
                new Wall(this, 120, 250, 225, 255),
                //right center wall
                new Wall(this, 275, 145, 280, 350),
                new Wall(this, 275, 250, 380, 255)
            ];
        };

        Game.prototype = {

            isReady: true,

            update: function() { //updates the movement of all the on screen entities
                for (var i = 0; i < this.tanks.length; i++) {
                    this.tanks[i].update();
                }

                var thisPlayer = this.tanks[0];

                var deleteError = function(errobj) {
                    console.log('Error deleting target: ' + JSON.stringify(errobj));
                };

                var deleteSuccess = function(response) {
                    console.log(response);
                };
                $scope.player.x = thisPlayer.location().x;
                $scope.player.y = thisPlayer.location().y;
                $scope.player.direction = thisPlayer.direction;

                for (i = 0; i < this.targets.length; i++) {
                    if (collidingTarget(thisPlayer, this.targets[i])) {
                        this.targets[i].fillStyle = 'black';
                        console.log(this.targets[i].target_id);
                        if (this.targets[i].is_hit === 0) {
                            this.targets[i].is_hit = 1;
                            $http.delete(DJANGO_SERVER_URL + "/games/" + gameID + "/targets/" + this.targets[i].target_id + "/", {

                                data: playerID

                            }).then(deleteSuccess, deleteError);

                        }
                    }
                }
                this.tanks = this.tanks.slice(0, 1);
            },

            draw: function(screen, gameSize) {
                screen.clearRect(0, 0, gameSize.x, gameSize.y);

                for (i = 0; i < this.targets.length; i++) { //This loop draws the targets
                    drawTarget(screen, this.targets[i]);
                }

                for (i = 0; i < this.walls.length; i++) { //This loop draws the walls
                    this.walls[i].draw(screen);
                }

                for (var i = 0; i < this.tanks.length; i++) { //This loop draws the tanks
                    drawTank(screen, this.tanks[i]);
                    if (i === 0) {
                        if (this.tanks[i].direction === "W") {
                            drawDrillHeadLeft(screen, this.tanks[i]);
                        } else if (this.tanks[i].direction === "E") {
                            drawDrillHeadRight(screen, this.tanks[i]);
                        } else if (this.tanks[i].direction === "N") {
                            drawDrillHeadUp(screen, this.tanks[i]);
                        } else if (this.tanks[i].direction === "S") {
                            drawDrillHeadDown(screen, this.tanks[i]);
                        }
                    }
                }
            },

            refreshTanks: function(thisGame) {
                var tanks = [];
                for (var key in $scope.game.tanks) {
                    if (key !== playerID) {
                        tanks.push(new Player(this, $scope.game.tanks[key]));
                    }
                }
                return tanks;
            },

            refreshTargets: function(thisGame, firebaseTargets) {
                var targets = [];
                for (var i = 0; i < firebaseTargets.length; i++) {
                    targets.push(new Target(thisGame, firebaseTargets[i]));
                }
                return targets;
            }
        };
        var Player = function(game, location) {
            this.game = game;
            this.direction = "E";
            this.size = {
                x: 16,
                y: 16
            }; //player size
            this.center = {
                x: location.x,
                y: location.y
            }; //tells the game where the player is at the start
            this.keyboarder = new Keyboarder();
        };

        Player.prototype = {

            location: function() {
                return this.center;
            },

            update: function() {
                var wallHit = false;
                for (i = 0; i < this.game.walls.length; i++) {
                    if (collidingWall(this, this.game.walls[i])) {
                        console.log("Wall!");
                        wallHit = true;
                        break;
                    }
                }

                if (this.keyboarder.isDown(this.keyboarder.KEYS.LEFT)) {
                    this.direction = "W";
                    if (wallHit) {
                        this.center.x += 8;
                    } else if (this.center.x <= 10) {
                        this.center.x = 8;
                    } else {
                        this.center.x -= 2;
                    }
                } else if (this.keyboarder.isDown(this.keyboarder.KEYS.RIGHT)) {
                    this.direction = "E";
                    if (wallHit) {
                        this.center.x -= 8;
                    } else if (this.center.x >= 490) {
                        this.center.x = 492;
                    } else {
                        this.center.x += 2;
                    }
                } else if (this.keyboarder.isDown(this.keyboarder.KEYS.UP)) {
                    this.direction = "N";

                    if (wallHit) {
                        this.center.y += 8;
                    } else if (this.center.y <= 10) {
                        this.center.y = 8;
                    } else {
                        this.center.y -= 2;
                    }
                } else if (this.keyboarder.isDown(this.keyboarder.KEYS.DOWN)) {
                    this.direction = "S";

                    if (wallHit) {
                        this.center.y -= 8;
                    } else if (this.center.y >= 490) {
                        this.center.y = 492;
                    } else {
                        this.center.y += 2;
                    }
                }
            }
        };

        var Target = function(game, firebaseTarget) {
            this.game = game;
            this.size = {
                x: 10,
                y: 10
            }; //player size
            this.center = {
                x: firebaseTarget.x,
                y: firebaseTarget.y
            }; //tells the game where the targets are at the moment, starting at half way through the screen and just above the bottom
            this.target_id = firebaseTarget.$id;
            this.is_hit = 0;
            this.fillStyle = "red";
        };

        Target.prototype = {
            update: function() {
                console.log("helllo");
            }
        };

        var Wall = function(game, xmin, ymin, xmax, ymax) {
            this.game = game;
            this.xmin = xmin;
            this.ymin = ymin;
            this.xmax = xmax;
            this.ymax = ymax;
        };

        Wall.prototype = {
            draw: function(screen) {
                screen.fillStyle = 'white';
                screen.fillRect(this.xmin, //x coordinate
                    this.ymin, // y coordinate
                    this.xmax - this.xmin, //width
                    this.ymax - this.ymin); //height
            }
        };

        var drawTank = function(screen, body) {
            //tank body
            screen.fillStyle = 'green';
            screen.fillRect(body.center.x - body.size.x / 2, //x coordinate
                body.center.y - body.size.y / 2, // y coordinate
                body.size.x, body.size.y); //width and hieght
        };

        var drawDrillHeadLeft = function(screen, body) {
            screen.fillRect(body.center.x - body.size.x / 2 - 4, body.center.y - 2, 4, 4);
        };

        var drawDrillHeadRight = function(screen, body) {
            screen.fillRect(body.center.x + body.size.x / 2, body.center.y - 2, 4, 4);
        };

        var drawDrillHeadUp = function(screen, body) {
            screen.fillRect(body.center.x - 2, body.center.y - body.size.y / 2 - 4, 4, 4);
        };

        var drawDrillHeadDown = function(screen, body) {
            screen.fillRect(body.center.x - 2, body.center.y + body.size.y / 2, 4, 4);
        };

        var drawTarget = function(screen, target) {
            screen.fillStyle = target.fillStyle;
            screen.fillRect(target.center.x - target.size.x / 2, //x coordinate
                target.center.y - target.size.y / 2, // y coordinate
                target.size.x, target.size.y);
        };

        var Keyboarder = function() { //handles keyboard input
            var keyState = {}; //records if any key that's been pressed is pressed or released
            var keyPressed = false;
            var self = this;

            window.onkeydown = function(e) {
                if (e.keyCode >= self.KEYS.LEFT &&
                    e.keyCode <= self.KEYS.DOWN) {
                    e.preventDefault();
                }
                if (e.keyCode >= self.KEYS.LEFT &&
                    e.keyCode <= self.KEYS.DOWN &&
                    !keyPressed) {
                    keyState[e.keyCode] = true;
                    keyPressed = true;
                }
            };

            window.onkeyup = function(e) {
                if (e.keyCode >= self.KEYS.LEFT &&
                    e.keyCode <= self.KEYS.DOWN &&
                    keyPressed) {
                    keyState = {};
                    keyPressed = false;
                }
            };

            this.isDown = function(keyCode) {
                return keyState[keyCode] === true;
            };

            this.KEYS = {
                LEFT: 37,
                UP: 38,
                RIGHT: 39,
                DOWN: 40
            };
        };

        var collidingTarget = function(b1, b2) {
            return !(b1 === b2 ||
                b1.center.x + b1.size.x / 2 < b2.center.x - b2.size.x / 2 ||
                b1.center.y + b1.size.y / 2 < b2.center.y - b2.size.y / 2 ||
                b1.center.x - b1.size.x / 2 > b2.center.x + b2.size.x / 2 ||
                b1.center.y - b1.size.y / 2 > b2.center.y + b2.size.y / 2);
        };

        var collidingWall = function(b1, b2) {
            return (((b1.center.x - b1.size.x / 2) < b2.xmax) &&
                ((b1.center.x + b1.size.x / 2) > b2.xmin) &&
                ((b1.center.y - b1.size.y / 2) < b2.ymax) &&
                ((b1.center.y + b1.size.y / 2) > b2.ymin));
        };
    }

})(); // End of IIFE

//Credit to Mary Rose Cook's Video tutorial introducing game concepts in javascript
// https://vimeo.com/105955605
<|endoftext|>


<commit_before>define([
  'jquery',
  'require',

  './select2/core',
  './select2/defaults'
], function ($, require, Select2, Defaults) {
  // Force jQuery.mousewheel to be loaded if it hasn't already
  require('jquery.mousewheel');

  if ($.fn.select2 == null) {
    // All methods that should return the element
    var thisMethods = ['open', 'close', 'destroy'];

    $.fn.select2 = function (options) {
      options = options || {};

      if (typeof options === 'object') {
        this.each(function () {
          var instanceOptions = $.extend(true, {}, options);

          var instance = new Select2($(this), instanceOptions);
        });

        return this;
      } else if (typeof options === 'string') {
        var ret;

        this.each(function () {
          var instance = $(this).data('select2');

          if (instance == null && window.console && console.error) {
            console.error(
              'The select2(\'' + options + '\') method was called on an ' +
              'element that is not using Select2.'
            );
          }

          var args = Array.prototype.slice.call(arguments, 1);

          ret = instance[options].apply(instance, args);
        });

        // Check if we should be returning `this`
        if ($.inArray(options, thisMethods) > -1) {
          return this;
        }

        return ret;
      } else {
        throw new Error('Invalid arguments for Select2: ' + options);
      }
    };
  }

  if ($.fn.select2.defaults == null) {
    $.fn.select2.defaults = Defaults;
  }

  return Select2;
});
<commit_msg>Explicitly require jquery-mousewheel now<commit_after>define([
  'jquery',
  'jquery-mousewheel',

  './select2/core',
  './select2/defaults'
], function ($, _, Select2, Defaults) {
  if ($.fn.select2 == null) {
    // All methods that should return the element
    var thisMethods = ['open', 'close', 'destroy'];

    $.fn.select2 = function (options) {
      options = options || {};

      if (typeof options === 'object') {
        this.each(function () {
          var instanceOptions = $.extend(true, {}, options);

          var instance = new Select2($(this), instanceOptions);
        });

        return this;
      } else if (typeof options === 'string') {
        var ret;

        this.each(function () {
          var instance = $(this).data('select2');

          if (instance == null && window.console && console.error) {
            console.error(
              'The select2(\'' + options + '\') method was called on an ' +
              'element that is not using Select2.'
            );
          }

          var args = Array.prototype.slice.call(arguments, 1);

          ret = instance[options].apply(instance, args);
        });

        // Check if we should be returning `this`
        if ($.inArray(options, thisMethods) > -1) {
          return this;
        }

        return ret;
      } else {
        throw new Error('Invalid arguments for Select2: ' + options);
      }
    };
  }

  if ($.fn.select2.defaults == null) {
    $.fn.select2.defaults = Defaults;
  }

  return Select2;
});
<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Button for selecting a game level.
 * Also depicts the progress made on each level.
 *
 * @author John Blanco
 * @author Chris Malley
 */
define( function( require ) {
  'use strict';

  // modules
  var Dimension2 = require( 'DOT/Dimension2' );
  var GameTimer = require( 'VEGAS/GameTimer' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var ProgressIndicator = require( 'VEGAS/ProgressIndicator' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var RectangularPushButton = require( 'SUN/buttons/RectangularPushButton' );
  var Text = require( 'SCENERY/nodes/Text' );

  // constants
  var SCALING_TOLERANCE = 1E-4; // Empirically chosen as something the human eye is unlikely to notice.

  // TODO: Consider making this commonly accessible (or finding a better way to do it).
  // Create a node that is scaled and padded out to meet the size specification.
  function createSizedImageNode( icon, size ) {
    icon.scale( Math.min( size.width / icon.bounds.width, size.height / icon.bounds.height ) );
    if ( Math.abs( icon.bounds.width - size.width ) < SCALING_TOLERANCE &&
         Math.abs( icon.bounds.height - size.height ) < SCALING_TOLERANCE ) {
      // The aspect ratio of the icon matched that of the specified size, so no padding is necessary.
      return icon;
    }
    // else padding is needed in either the horizontal or vertical direction.
    var background = new Rectangle( 0, 0, size.width, size.height, 0, 0, { fill: null } );
    icon.center = background.center;
    background.addChild( icon );
    return background;
  }

  /**
   * @param {Node} icon Scenery node that appears on the button above the progress indicator, scaled to fit
   * @param {number} numStars Number of stars to show in the progress indicator at the bottom of the button
   * @param {function} fireFunction Called when the button fires
   * @param {Property.<number>} scoreProperty
   * @param {number} perfectScore
   * @param {Object} [options]
   * @constructor
   */
  function LevelSelectionButton( icon, numStars, fireFunction, scoreProperty, perfectScore, options ) {

    Node.call( this );

    options = _.extend( {
      // button size and appearance
      buttonWidth: 150,
      buttonHeight: 150,
      cornerRadius: 10,
      baseColor: 'rgb( 242, 255, 204 )',
      buttonXMargin: 10,
      buttonYMargin: 10,
      // progress indicator (stars)
      progressIndicatorProportion: 0.2, // percentage of the button height occupied by the progress indicator, (0,0.5]
      progressIndicatorMinXMargin: 10,
      progressIndicatorMinYMargin: 5,
      iconToProgressIndicatorYSpace: 10,
      // best time (optional)
      bestTimeProperty: null, // null if no best time || {Property.<number>} best time in seconds
      bestTimeVisibleProperty: null, // null || Property.<boolean>} controls visibility of best time
      bestTimeFill: 'black',
      bestTimeFont: new PhetFont( 24 ),
      bestTimeYSpacing: 10  // vertical space between drop shadow and best time
    }, options );

    assert && assert( options.progressIndicatorProportion > 0 && options.progressIndicatorProportion <= 0.5, 'progressIndicatorProportion value out of range' );

    var maxContentWidth = options.buttonWidth - 2 * options.buttonXMargin;

    // Progress indicator (stars), scaled to fit
    var progressIndicatorBackground = new Rectangle( 0, 0, maxContentWidth,
        options.buttonHeight * options.progressIndicatorProportion, options.cornerRadius, options.cornerRadius, {
        fill: 'white',
        stroke: 'black',
        lineWidth: 1,
        pickable: false
      } );
    var progressIndicator = new ProgressIndicator( numStars, scoreProperty, perfectScore, {
      pickable: false,
      starDiameter: options.buttonWidth / ( numStars + 1 )
    } );
    progressIndicator.scale( Math.min(
        ( progressIndicatorBackground.width - 2 * options.progressIndicatorMinXMargin ) / progressIndicator.width,
        ( progressIndicatorBackground.height - 2 * options.progressIndicatorMinYMargin ) / progressIndicator.height ) );

    // Icon, scaled and padded to fit and to make the button size correct.
    var iconSize = new Dimension2( maxContentWidth, options.buttonHeight - progressIndicatorBackground.height - 2 * options.buttonYMargin );
    var adjustedIcon = createSizedImageNode( icon, iconSize );
    adjustedIcon.pickable = false; // TODO: is this needed?

    // Assemble the content.
    var contentNode = new Node();
    if ( progressIndicatorBackground.width > adjustedIcon.width ) {
      adjustedIcon.centerX = progressIndicatorBackground.centerX;
    }
    else {
      progressIndicatorBackground.centerX = adjustedIcon.centerX;
    }
    progressIndicatorBackground.top = adjustedIcon.bottom + options.iconToProgressIndicatorYSpace;
    progressIndicator.center = progressIndicatorBackground.center;
    contentNode.addChild( adjustedIcon );
    contentNode.addChild( progressIndicatorBackground );
    contentNode.addChild( progressIndicator );

    // Create the button
    var buttonOptions = {
      content: contentNode,
      xMargin: options.buttonXMargin,
      yMargin: options.buttonYMargin,
      baseColor: options.baseColor,
      cornerRadius: options.cornerRadius,
      listener: fireFunction
    };
    var button = new RectangularPushButton( buttonOptions );
    this.addChild( button );

    // Best time (optional), centered below the button, does not move when button is pressed
    if ( options.bestTimeProperty ) {
      var bestTimeNode = new Text( '', { font: options.bestTimeFont, fill: options.bestTimeFill } );
      this.addChild( bestTimeNode );
      options.bestTimeProperty.link( function( bestTime ) {
        bestTimeNode.text = ( bestTime ? GameTimer.formatTime( bestTime ) : '' );
        bestTimeNode.centerX = button.centerX;
        bestTimeNode.top = button.bottom + options.bestTimeYSpacing;
      } );
      if ( options.bestTimeVisibleProperty ) {
        options.bestTimeVisibleProperty.linkAttribute( bestTimeNode, 'visible' );
      }
    }

    // Pass options to parent class
    this.mutate( options );
  }

  return inherit( Node, LevelSelectionButton );
} );<commit_msg>Fixed an issue where the spacing between the icon and the progress indicator was not being taken into account in the button height calculation.<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Button for selecting a game level.
 * Also depicts the progress made on each level.
 *
 * @author John Blanco
 * @author Chris Malley
 */
define( function( require ) {
  'use strict';

  // modules
  var Dimension2 = require( 'DOT/Dimension2' );
  var GameTimer = require( 'VEGAS/GameTimer' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var ProgressIndicator = require( 'VEGAS/ProgressIndicator' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var RectangularPushButton = require( 'SUN/buttons/RectangularPushButton' );
  var Text = require( 'SCENERY/nodes/Text' );

  // constants
  var SCALING_TOLERANCE = 1E-4; // Empirically chosen as something the human eye is unlikely to notice.

  // TODO: Consider making this commonly accessible (or finding a better way to do it).
  // Create a node that is scaled and padded out to meet the size specification.
  function createSizedImageNode( icon, size ) {
    icon.scale( Math.min( size.width / icon.bounds.width, size.height / icon.bounds.height ) );
    if ( Math.abs( icon.bounds.width - size.width ) < SCALING_TOLERANCE &&
         Math.abs( icon.bounds.height - size.height ) < SCALING_TOLERANCE ) {
      // The aspect ratio of the icon matched that of the specified size, so no padding is necessary.
      return icon;
    }
    // else padding is needed in either the horizontal or vertical direction.
    var background = new Rectangle( 0, 0, size.width, size.height, 0, 0, { fill: null } );
    icon.center = background.center;
    background.addChild( icon );
    return background;
  }

  /**
   * @param {Node} icon Scenery node that appears on the button above the progress indicator, scaled to fit
   * @param {number} numStars Number of stars to show in the progress indicator at the bottom of the button
   * @param {function} fireFunction Called when the button fires
   * @param {Property.<number>} scoreProperty
   * @param {number} perfectScore
   * @param {Object} [options]
   * @constructor
   */
  function LevelSelectionButton( icon, numStars, fireFunction, scoreProperty, perfectScore, options ) {

    Node.call( this );

    options = _.extend( {
      // button size and appearance
      buttonWidth: 150,
      buttonHeight: 150,
      cornerRadius: 10,
      baseColor: 'rgb( 242, 255, 204 )',
      buttonXMargin: 10,
      buttonYMargin: 10,
      // progress indicator (stars)
      progressIndicatorProportion: 0.2, // percentage of the button height occupied by the progress indicator, (0,0.5]
      progressIndicatorMinXMargin: 10,
      progressIndicatorMinYMargin: 5,
      iconToProgressIndicatorYSpace: 10,
      // best time (optional)
      bestTimeProperty: null, // null if no best time || {Property.<number>} best time in seconds
      bestTimeVisibleProperty: null, // null || Property.<boolean>} controls visibility of best time
      bestTimeFill: 'black',
      bestTimeFont: new PhetFont( 24 ),
      bestTimeYSpacing: 10  // vertical space between drop shadow and best time
    }, options );

    assert && assert( options.progressIndicatorProportion > 0 && options.progressIndicatorProportion <= 0.5, 'progressIndicatorProportion value out of range' );

    var maxContentWidth = options.buttonWidth - 2 * options.buttonXMargin;

    // Progress indicator (stars), scaled to fit
    var progressIndicatorBackground = new Rectangle( 0, 0, maxContentWidth,
        options.buttonHeight * options.progressIndicatorProportion, options.cornerRadius, options.cornerRadius, {
        fill: 'white',
        stroke: 'black',
        lineWidth: 1,
        pickable: false
      } );
    var progressIndicator = new ProgressIndicator( numStars, scoreProperty, perfectScore, {
      pickable: false,
      starDiameter: options.buttonWidth / ( numStars + 1 )
    } );
    progressIndicator.scale( Math.min(
        ( progressIndicatorBackground.width - 2 * options.progressIndicatorMinXMargin ) / progressIndicator.width,
        ( progressIndicatorBackground.height - 2 * options.progressIndicatorMinYMargin ) / progressIndicator.height ) );

    // Icon, scaled and padded to fit and to make the button size correct.
    var iconSize = new Dimension2( maxContentWidth, options.buttonHeight - progressIndicatorBackground.height -
                                                    2 * options.buttonYMargin - options.iconToProgressIndicatorYSpace );
    var adjustedIcon = createSizedImageNode( icon, iconSize );
    adjustedIcon.pickable = false; // TODO: is this needed?

    // Assemble the content.
    var contentNode = new Node();
    if ( progressIndicatorBackground.width > adjustedIcon.width ) {
      adjustedIcon.centerX = progressIndicatorBackground.centerX;
    }
    else {
      progressIndicatorBackground.centerX = adjustedIcon.centerX;
    }
    progressIndicatorBackground.top = adjustedIcon.bottom + options.iconToProgressIndicatorYSpace;
    progressIndicator.center = progressIndicatorBackground.center;
    contentNode.addChild( adjustedIcon );
    contentNode.addChild( progressIndicatorBackground );
    contentNode.addChild( progressIndicator );

    // Create the button
    var buttonOptions = {
      content: contentNode,
      xMargin: options.buttonXMargin,
      yMargin: options.buttonYMargin,
      baseColor: options.baseColor,
      cornerRadius: options.cornerRadius,
      listener: fireFunction
    };
    var button = new RectangularPushButton( buttonOptions );
    this.addChild( button );

    // Best time (optional), centered below the button, does not move when button is pressed
    if ( options.bestTimeProperty ) {
      var bestTimeNode = new Text( '', { font: options.bestTimeFont, fill: options.bestTimeFill } );
      this.addChild( bestTimeNode );
      options.bestTimeProperty.link( function( bestTime ) {
        bestTimeNode.text = ( bestTime ? GameTimer.formatTime( bestTime ) : '' );
        bestTimeNode.centerX = button.centerX;
        bestTimeNode.top = button.bottom + options.bestTimeYSpacing;
      } );
      if ( options.bestTimeVisibleProperty ) {
        options.bestTimeVisibleProperty.linkAttribute( bestTimeNode, 'visible' );
      }
    }

    // Pass options to parent class
    this.mutate( options );
  }

  return inherit( Node, LevelSelectionButton );
} );<|endoftext|>


<commit_before>this.mmooc=this.mmooc||{};

this.mmooc.groups = function() {
    function interceptLinkToGroupPageForHref(href, event) {
        if (/\/groups\/\d+$/.test(href)) {
            event.preventDefault();
            location.href = href + '/discussion_topics';
        }
    }

    return {
        interceptLinksToGroupPage: function() {
            $("#content").on('click', '.student-group-title a', function(event) {
                var href= $(this).attr("href");
                interceptLinkToGroupPageForHref(href, event);
            });

            $("#right-side").on('click', '.group_list a', function(event) {
                var href= $(this).attr("href");
                interceptLinkToGroupPageForHref(href, event);
            });
        },

        showGroupHeader: function() {
            var courseId = mmooc.api.getCurrentCourseId();
            var groupId = mmooc.api.getCurrentGroupId();
            if (groupId != null) {
                mmooc.api.getGroupMembers(groupId, function(members) {
                    var headerHTML = mmooc.util.renderTemplateWithData("groupheader", {groupId: groupId, courseId: courseId, members: members});
                    document.getElementById('content-wrapper').insertAdjacentHTML('afterbegin', headerHTML);
                });
            }
        },

        changeGroupListURLs: function(href) {
          if (/\/groups(\??([A-Za-z0-9\=\&]{0,}))$/.test(href)) {
            var list = $('.context_list li a');
            list.each(function(i) {
              this.setAttribute('href', this.getAttribute('href') + '/discussion_topics');
            });
            return true;
          }

          return false;
        }
    };
}();
<commit_msg>Rewrote regex checking<commit_after>this.mmooc=this.mmooc||{};

this.mmooc.groups = function() {
    function interceptLinkToGroupPageForHref(href, event) {
        if (/\/groups\/\d+$/.test(href)) {
            event.preventDefault();
            location.href = href + '/discussion_topics';
        }
    }

    return {
        interceptLinksToGroupPage: function() {
            $("#content").on('click', '.student-group-title a', function(event) {
                var href= $(this).attr("href");
                interceptLinkToGroupPageForHref(href, event);
            });

            $("#right-side").on('click', '.group_list a', function(event) {
                var href= $(this).attr("href");
                interceptLinkToGroupPageForHref(href, event);
            });
        },

        showGroupHeader: function() {
            var courseId = mmooc.api.getCurrentCourseId();
            var groupId = mmooc.api.getCurrentGroupId();
            if (groupId != null) {
                mmooc.api.getGroupMembers(groupId, function(members) {
                    var headerHTML = mmooc.util.renderTemplateWithData("groupheader", {groupId: groupId, courseId: courseId, members: members});
                    document.getElementById('content-wrapper').insertAdjacentHTML('afterbegin', headerHTML);
                });
            }
        },

        changeGroupListURLs: function(href) {
          if (/\/groups(\/)?$/.test(href) || /(\/groups(\??([A-Za-z0-9\=\&]{0,})))$/.test(href)) {
            var list = $('.context_list li a');
            list.each(function(i) {
              this.setAttribute('href', this.getAttribute('href') + '/discussion_topics');
            });
            return true;
          }

          return false;
        }
    };
}();
<|endoftext|>


<commit_before>;(function (Plugins, Utils, undefined) { 'use strict';

  // Slider plugin to change visible columns
  // ---------------------------------------

  var Slider = function (element, options) {
    // Store reference for a fast options passing
    this.element = element;
    this.options = options;

    this.currentIndex = 0;

    // Cache selectors
    // Note: it's a huge performance boost
    this.cacheSliders = element.querySelectorAll('.planner-slider');
    this.cacheColumn = element.querySelector('.planner-column');

    // Attach all listeners to planner.js element
    this._attachArrowsEvents();

    if (Planner.Plugins.isRegistered('mobile')) {
      // this._attachSlidingTouch(); // TODO: disabled for now
    }
  };

  Slider.DEFAULTS = {
    minMovement: 8,
    minSwipe: 100,
    headerOffset: 5
  };

  // Private plugin helpers
  // ----------------------

  Slider.prototype._attachArrowsEvents = function () {
    var arrowLeft = this.element.querySelector('.arrow-left');
    arrowLeft.addEventListener('click', this._slideLeft.bind(this));

    var arrowRight = this.element.querySelector('.arrow-right');
    arrowRight.addEventListener('click', this._slideRight.bind(this));
  };

  Slider.prototype._attachSlidingTouch = function () {
    var startClientX = 0;
    var lastClientX = 0;
    var currentOffset = 0;
    var started = false;
    var self = this;

    self.cacheSlider.on({
      'touchstart': function (event) {
        // If is a touch event, use just the first touch property (i.e. the first finger)
        event = event.originalEvent.touches[0];
        startClientX = event.clientX;
      },
      'touchmove': function (event) {
        // Calculate delta movement
        var eventTouch = event.originalEvent.touches[0];
        lastClientX = eventTouch.clientX - startClientX;

        // Start touch sliding with not too much swipe
        if (!started && (lastClientX < -self.options.minMovement || lastClientX > self.options.minMovement)) {
          event.preventDefault();
          started = true;
        }

        // Avoid column sliding when user has reached the border
        // Note: 'started' check is required to increase performance on slower mobile devices
        if (started &&
          (self.currentIndex === 0 && lastClientX < 0 ||
            (self.currentIndex !== 0 && self.currentIndex !== self.options.columnLabels.length - 1) ||
            (self.currentIndex === self.options.columnLabels.length - 1 && lastClientX > 0))) {

          self._appendTranslate3d(currentOffset + lastClientX);
        }
      },
      'touchend': function () {
        if (started) {
          started = false;

          if (lastClientX > self.options.minSwipe) {
            self._slideLeft();
          } else if (lastClientX < -self.options.minSwipe) {
            self._slideRight();
          } else {
            self.cacheSlider.addClass('animate');
            self._appendTranslate3d(currentOffset);
          }

          lastClientX = 0;
          currentOffset = self._columnOffset();
        }
      },
      'transitionend MSTransitionEnd webkitTransitionEnd oTransitionEnd': function () {
        self.cacheSlider.removeClass('animate');
      }
    });
  };

  Slider.prototype._columnOffset = function () {
    var columnWidth = this.cacheColumn.offsetWidth + this.options.headerOffset;

    return -columnWidth * this.currentIndex;
  };

  Slider.prototype._slideLeft = function () {
    if (this.currentIndex > 0) {
      Utils.addClass(this.cacheSliders, 'animate');

      this.currentIndex -= 1;
      this._appendTranslate3d(this._columnOffset());
    }
  };

  Slider.prototype._slideRight = function () {
    // TODO: this behaviour should be optimized with better options passing
    var visibleColumns = document.documentElement.clientWidth <= 768 ?
      this.options.mobileVisibleColumns :
      this.options.visibleColumns;

    if (this.currentIndex < (this.options.columnLabels.length - visibleColumns)) {
      for (var i = 0; i < this.cacheSliders.length; i++) {
        Utils.addClass(this.cacheSliders[i], 'animate');
      }

      this.currentIndex += 1;
      this._appendTranslate3d(this._columnOffset());
    }
  };

  Slider.prototype._appendTranslate3d = function (value) {
    if (typeof value === 'number') {
      var translate = 'translate3d(' + value + 'px, 0, 0)';

      for (var i = 0; i < this.cacheSliders.length; i++) {
        this.cacheSliders[i].style.webkitTransform = translate;
        this.cacheSliders[i].style.mozTransform = translate;
        this.cacheSliders[i].style.msTransform = translate;
        this.cacheSliders[i].style.oTransform = translate;
        this.cacheSliders[i].style.transform = translate;
      }
    } else {
      throw new Error('Unable to append a 3D translation if the value isn\'t a number');
    }
  };

  // Register this plugin to plugins list
  // ------------------------------------

  Plugins.register('slider', Slider);

})(Planner.Plugins, Planner.Utils);
<commit_msg>migrate mobile swipe for slider plugin<commit_after>;(function (Plugins, Utils, undefined) { 'use strict';

  // Slider plugin to change visible columns
  // ---------------------------------------

  var Slider = function (element, options) {
    // Store reference for a fast options passing
    this.element = element;
    this.options = options;

    this.currentIndex = 0;

    // Cache selectors
    // Note: it's a huge performance boost
    this.cacheSliders = element.querySelectorAll('.planner-slider');
    this.cacheColumn = element.querySelector('.planner-column');

    // Attach all listeners to planner.js element
    this._attachArrowsEvents();

    if (Planner.Plugins.isRegistered('mobile')) {
      this._attachSlidingTouch();
    }
  };

  Slider.DEFAULTS = {
    minMovement: 15,
    minSwipe: 100,
    headerOffset: 5
  };

  // Private plugin helpers
  // ----------------------

  Slider.prototype._attachArrowsEvents = function () {
    var arrowLeft = this.element.querySelector('.arrow-left');
    // TODO: avoid bind() use
    arrowLeft.addEventListener('click', this._slideLeft.bind(this));

    var arrowRight = this.element.querySelector('.arrow-right');
    // TODO: avoid bind() use
    arrowRight.addEventListener('click', this._slideRight.bind(this));
  };

  Slider.prototype._attachSlidingTouch = function () {
    var startClientX = 0;
    var lastClientX = 0;
    var currentOffset = 0;
    var started = false;

    // TODO: avoid use of that=this pattern
    var self = this;

    var _touchStart = function (event) {
      // If is a touch event, use just the first touch property (i.e. the first finger)
      event = event.touches[0];
      startClientX = event.clientX;
      for (var i = 0; i < self.cacheSliders.length; i++) {
        Utils.removeClass(self.cacheSliders[i], 'animate');
      }
    };

    var _touchMove = function (event) {
      // Calculate delta movement
      var eventTouch = event.touches[0];
      lastClientX = eventTouch.clientX - startClientX;

      // Start sliding without too much swipe
      if (!started && (lastClientX < -self.options.minMovement || lastClientX > self.options.minMovement)) {
        event.preventDefault();
        started = true;
      }

      // Avoid column sliding when user has reached the border
      // Note: 'started' check is required to increase performance on slower mobile devices
      if (started &&
        (self.currentIndex === 0 && lastClientX < 0 ||
          (self.currentIndex !== 0 && self.currentIndex !== self.options.columnLabels.length - 1) ||
          (self.currentIndex === self.options.columnLabels.length - 1 && lastClientX > 0))) {

        self._appendTranslate3d(currentOffset + lastClientX);
      }
    };

    var _touchEnd = function () {
      if (started) {
        started = false;

        for (var i = 0; i < self.cacheSliders.length; i++) {
          Utils.addClass(self.cacheSliders[i], 'animate');
        }

        if (lastClientX > self.options.minSwipe) {
          self._slideLeft();
        } else if (lastClientX < -self.options.minSwipe) {
          self._slideRight();
        } else {
          self._appendTranslate3d(currentOffset);
        }

        lastClientX = 0;
        currentOffset = self._columnOffset();
      }
    };

    // Add listeners
    // -------------

    for (var i = 0; i < this.cacheSliders.length; i++) {
      this.cacheSliders[i].addEventListener('touchstart', _touchStart);
      this.cacheSliders[i].addEventListener('touchmove', _touchMove);
      this.cacheSliders[i].addEventListener('touchend', _touchEnd);
    }
  };

  Slider.prototype._columnOffset = function () {
    var columnWidth = this.cacheColumn.offsetWidth + this.options.headerOffset;

    return -columnWidth * this.currentIndex;
  };

  Slider.prototype._slideLeft = function () {
    if (this.currentIndex > 0) {
      Utils.addClass(this.cacheSliders, 'animate');

      this.currentIndex -= 1;
      this._appendTranslate3d(this._columnOffset());
    }
  };

  Slider.prototype._slideRight = function () {
    // TODO: this behaviour should be optimized with better options passing
    var visibleColumns = document.documentElement.clientWidth <= 768 ?
      this.options.mobileVisibleColumns :
      this.options.visibleColumns;

    if (this.currentIndex < (this.options.columnLabels.length - visibleColumns)) {
      for (var i = 0; i < this.cacheSliders.length; i++) {
        Utils.addClass(this.cacheSliders[i], 'animate');
      }

      this.currentIndex += 1;
      this._appendTranslate3d(this._columnOffset());
    }
  };

  Slider.prototype._appendTranslate3d = function (value) {
    if (typeof value === 'number') {
      var translate = 'translate3d(' + value + 'px, 0, 0)';

      for (var i = 0; i < this.cacheSliders.length; i++) {
        this.cacheSliders[i].style.webkitTransform = translate;
        this.cacheSliders[i].style.mozTransform = translate;
        this.cacheSliders[i].style.msTransform = translate;
        this.cacheSliders[i].style.oTransform = translate;
        this.cacheSliders[i].style.transform = translate;
      }
    } else {
      throw new Error('Unable to append a 3D translation if the value isn\'t a number');
    }
  };

  // Register this plugin to plugins list
  // ------------------------------------

  Plugins.register('slider', Slider);

})(Planner.Plugins, Planner.Utils);
<|endoftext|>