<commit_before>angular.module( 'gj.Game.Package.Card' ).directive( 'gjGamePackageCard', function(
	$window, $timeout, $state, $injector, Screen, Growls, Game, Game_Build, Game_PlayModal, Device, Environment, HistoryTick, Analytics, Popover )
{
	/**
	 * Sort must start at 1 so that we can put their prefered OS as sort 0 later on.
	 */
	var supportInfo = {
		windows: {
			icon: 'windows',
			tooltip: 'Windows Support',
			sort: 10,
		},
		windows_64: {
			icon: 'windows',
			tooltip: 'Windows 64-bit Support',
			arch: '64',
			sort: 11,
		},
		mac: {
			icon: 'mac',
			tooltip: 'Mac Support',
			sort: 20,
		},
		mac_64: {
			icon: 'mac',
			tooltip: 'Mac 64-bit Support',
			arch: '64',
			sort: 21,
		},
		linux: {
			icon: 'linux',
			tooltip: 'Linux Support',
			sort: 30,
		},
		linux_64: {
			icon: 'linux',
			tooltip: 'Linux 64-bit Support',
			arch: '64',
			sort: 30,
		},
		other: {
			icon: 'other-os',
			tooltip: 'Downloadable File',
			sort: 40,
		},
		html: {
			icon: 'html5',
			tooltip: 'Web Playable',
			sort: 50,
		},
		flash: {
			icon: 'flash',
			tooltip: 'Flash Web Playable',
			sort: 51,
		},
		unity: {
			icon: 'unity',
			tooltip: 'Unity Web Playable',
			sort: 52,
		},
		applet: {
			icon: 'java',
			tooltip: 'Java Applet Web Playable',
			sort: 53,
		},
		silverlight: {
			icon: 'silverlight',
			tooltip: 'Silverlight Web Playable',
			sort: 54,
		},
	};

	function pluckOsSupport( build )
	{
		var support = [];

		// We only include the 64-bit versions if the build doesn't have 32bit and 64bit
		// on the same build. That basically just means it's a universal build.

		if ( build.os_windows ) {
			support.push( 'windows' );
		}

		if ( build.os_windows_64 && !build.os_windows ) {
			support.push( 'windows_64' );
		}

		if ( build.os_mac ) {
			support.push( 'mac' );
		}

		if ( build.os_mac_64 && !build.os_mac ) {
			support.push( 'mac_64' );
		}

		if ( build.os_linux ) {
			support.push( 'linux' );
		}

		if ( build.os_linux_64 && !build.os_linux ) {
			support.push( 'linux_64' );
		}

		if ( build.os_other ) {
			support.push( 'other' );
		}

		return support;
	}

	function checkSupport( support, type )
	{
		return support.indexOf( type ) !== -1;
	}

	return {
		restrict: 'E',
		templateUrl: '/lib/gj-lib-client/components/game/package/card/card.html',
		scope: {},
		bindToController: {
			game: '=game',
			'package': '=gamePackage',
			releases: '=gameReleases',
			builds: '=gameBuilds',
			key: '@?',
			launchOptions: '=?gameBuildLaunchOptions',
		},
		controllerAs: 'ctrl',
		controller: function( $scope, $attrs, $parse )
		{
			var _this = this;

			$scope.Environment = Environment;
			$scope.Screen = Screen;
			$scope.Game_Build = Game_Build;

			this.showFullDescription = false;
			this.canToggleDescription = undefined;

			this.supportInfo = angular.copy( supportInfo );
			this.support = [];

			this.downloadableBuild = null;
			this.browserBuild = null;
			this.extraBuilds = [];

			this.showcasedRelease = null;
			this.showcasedOs = null;
			this.showcasedOsIcon = null;
			this.showcasedBrowserIcon = null;

			this.otherOnly = false;

			// If this game is in their installed games, this will populate.
			this.installedBuild = null;

			if ( this.builds ) {

				var os = Device.os();
				var arch = Device.arch();  // Will only be set in client.

				// Indexes by the os/type of the build: [ { type: build } ]
				// While looping we also gather all OS/browser support for this complete package.
				var indexedBuilds = {};
				var otherBuilds = [];
				this.builds.forEach( function( build )
				{
					if ( build.isBrowserBased() ) {
						indexedBuilds[ build.type ] = build;
						this.support.push( build.type );
					}
					else if ( build.os_other ) {
						otherBuilds.push( build );
					}
					else {
						var support = pluckOsSupport( build );
						support.forEach( function( _os )
						{
							indexedBuilds[ _os ] = build;

							// Skip 64-bit builds for the global support icons.
							if ( this.supportInfo[ _os ].arch == '64' ) {
								return;
							}

							this.support.push( _os );
						}, this );
					}
				}, this );

				this.support = _.uniq( this.support );

				// At this point we should have all the OS/browser support, so let's sort it.
				// The sort values are defined above, but we want to push their detected OS at
				// the front. This is because you'd probably want to see [linux] first if you're
				// on a linux machine, before windows, etc.
				// We change the sort for their detected OS to be the first before sorting.
				this.supportInfo[ os ].sort = 0;
				this.support.sort( function( a, b )
				{
					return _this.supportInfo[ a ].sort - _this.supportInfo[ b ].sort;
				} );

				// Now that we have all the builds indexed by the platform they support
				// we need to try to pick one to showcase as the default download. We put
				// their detected OS first so that it tries to pick that one first.
				// Arch is only detected in Client.
				var checkDownloadables = [ 'windows', 'windows_64', 'mac', 'linux' ];

				// This will put the 64 bit version as higher priority.
				if ( arch == '64' ) {
					checkDownloadables.unshift( os );
					checkDownloadables.unshift( os + '_64' );
				}
				// If we don't have a detected arch that is 64, we prioritize the universal version.
				else {
					checkDownloadables.unshift( os + '_64' );
					checkDownloadables.unshift( os );
				}

				checkDownloadables.every( function( _os )
				{
					if ( !indexedBuilds[ _os ] ) {
						return true;
					}
					this.downloadableBuild = indexedBuilds[ _os ];
					this.showcasedOs = _os;
					this.showcasedOsIcon = _this.supportInfo[ _os ].icon;
				}, this );

				// Do the same with browser type. Pick the default browser one to show.
				[ 'html', 'flash', 'unity', 'applet', 'silverlight' ].every( function( type )
				{
					if ( !indexedBuilds[ type ] ) {
						return true;
					}
					this.browserBuild = indexedBuilds[ type ];
					this.showcasedBrowserIcon = _this.supportInfo[ type ].icon;
				}, this );

				// Pull the showcased release version.
				// It should be the greater one for either the downloadable or browser build chosen.
				if ( this.downloadableBuild ) {
					this.showcasedRelease = this.downloadableBuild._release;
				}

				// Lower sort value is a "newer" version.
				if ( this.browserBuild && (!this.showcasedRelease || this.browserBuild._release.sort < this.showcasedRelease) ) {
					this.showcasedRelease = this.browserBuild._release;
				}

				// Now pull the extra builds (ones that aren't default).
				angular.forEach( indexedBuilds, function( build, type )
				{
					if ( build == _this.downloadableBuild && type == _this.showcasedOs ) {
						return;
					}

					if ( build.type != Game_Build.TYPE_DOWNLOADABLE ) {
						if ( _this.browserBuild && _this.browserBuild.id == build.id ) {
							return;
						}
					}

					_this.extraBuilds.push( {
						type: build.type,
						icon: _this.supportInfo[ type ].icon,
						build: build,
						arch: _this.supportInfo[ type ].arch || null,
						platform: type,
					} );
				} );

				// Add all the "Other" builds onto the end of extra.
				if ( otherBuilds.length ) {
					otherBuilds.forEach( function( build )
					{
						_this.extraBuilds.push( {
							type: build.type,
							icon: _this.supportInfo['other'].icon,
							build: build,
							platform: 'other',
						} );
					} );
				}

				// Sort extra builds if there are any.
				if ( this.extraBuilds.length ) {
					this.extraBuilds.sort( function( a, b )
					{
						return _this.supportInfo[ a.platform ].sort - _this.supportInfo[ b.platform ].sort;
					} );
				}

				if ( !this.downloadableBuild && !this.browserBuild && otherBuilds.length ) {
					this.otherOnly = true;
					this.showcasedRelease = this.releases[0];
				}
			}

			this.buildClick = function( build )
			{
				if ( build.type == Game_Build.TYPE_DOWNLOADABLE ) {
					this.download( build );
				}
				else if ( build.isBrowserBased() ) {
					this.showBrowserModal( build );
				}
			};

			this.download = function( build )
			{
				Analytics.trackEvent( 'game-package-card', 'download', 'download' );

				// Bundle-only games can only live in a person's library, or as a key.
				// So if it's bundle-only, or if a key was passed in, go direct.
				if ( this.game.bundle_only || this.key ) {

					// If already waiting on a download, don't do anything.
					if ( downloadPromise ) {
						return;
					}

					// If they click away from the page before the download starts, then cancel the download redirect.
					var shouldTransition = true;
					var downloadUrl = null;
					var downloadPromise = build.getDownloadUrl( { key: this.key } )
						.then( function( response )
						{
							downloadUrl = response.downloadUrl;

							// Be sure to log the build download.
							return HistoryTick.sendBeacon( 'game-build', build.id );
						} )
						.then( function()
						{
							if ( shouldTransition ) {
								$window.location = downloadUrl;
							}
							downloadPromise = null;
						} );

					$scope.$on( '$stateChangeStart', function()
					{
						shouldTransition = false;
					} );
				}
				// Client needs to download externally.
				else if ( Environment.isClient ) {
					var gui = require( 'nw.gui' );
					gui.Shell.openExternal( Environment.baseUrl + $state.href( 'discover.games.view.download.build', { slug: this.game.slug, id: this.game.id, buildId: build.id } ) );
					Popover.hideAll();
				}
				else {
					$state.go( 'discover.games.view.download.build', { slug: this.game.slug, id: this.game.id, buildId: build.id } );
				}
			};

			this.showBrowserModal = function( build )
			{
				Analytics.trackEvent( 'game-package-card', 'download', 'play' );

				// TODO: This only goes to game page. We need to direct to a URL that would open the correct build in a modal.
				if ( Environment.isClient && build.type != Game_Build.TYPE_HTML ) {
					var gui = require( 'nw.gui' );
					gui.Shell.openExternal( Environment.baseUrl + $state.href( 'discover.games.view.overview', { slug: this.game.slug, id: this.game.id } ) );
					Popover.hideAll();
				}
				else {
					Game_PlayModal.show( this.game, build );
				}
			};
		}
	};
} );
<commit_msg>Package cards weren't showing an OS support icon if it only had a build for 64-bit and not 32-bit.<commit_after>angular.module( 'gj.Game.Package.Card' ).directive( 'gjGamePackageCard', function(
	$window, $timeout, $state, $injector, Screen, Growls, Game, Game_Build, Game_PlayModal, Device, Environment, HistoryTick, Analytics, Popover )
{
	/**
	 * Sort must start at 1 so that we can put their prefered OS as sort 0 later on.
	 */
	var supportInfo = {
		windows: {
			icon: 'windows',
			tooltip: 'Windows Support',
			sort: 10,
		},
		windows_64: {
			icon: 'windows',
			tooltip: 'Windows 64-bit Support',
			arch: '64',
			sort: 11,
		},
		mac: {
			icon: 'mac',
			tooltip: 'Mac Support',
			sort: 20,
		},
		mac_64: {
			icon: 'mac',
			tooltip: 'Mac 64-bit Support',
			arch: '64',
			sort: 21,
		},
		linux: {
			icon: 'linux',
			tooltip: 'Linux Support',
			sort: 30,
		},
		linux_64: {
			icon: 'linux',
			tooltip: 'Linux 64-bit Support',
			arch: '64',
			sort: 30,
		},
		other: {
			icon: 'other-os',
			tooltip: 'Downloadable File',
			sort: 40,
		},
		html: {
			icon: 'html5',
			tooltip: 'Web Playable',
			sort: 50,
		},
		flash: {
			icon: 'flash',
			tooltip: 'Flash Web Playable',
			sort: 51,
		},
		unity: {
			icon: 'unity',
			tooltip: 'Unity Web Playable',
			sort: 52,
		},
		applet: {
			icon: 'java',
			tooltip: 'Java Applet Web Playable',
			sort: 53,
		},
		silverlight: {
			icon: 'silverlight',
			tooltip: 'Silverlight Web Playable',
			sort: 54,
		},
	};

	function pluckOsSupport( build )
	{
		var support = [];

		// We only include the 64-bit versions if the build doesn't have 32bit and 64bit
		// on the same build. That basically just means it's a universal build.

		if ( build.os_windows ) {
			support.push( 'windows' );
		}

		if ( build.os_windows_64 && !build.os_windows ) {
			support.push( 'windows_64' );
		}

		if ( build.os_mac ) {
			support.push( 'mac' );
		}

		if ( build.os_mac_64 && !build.os_mac ) {
			support.push( 'mac_64' );
		}

		if ( build.os_linux ) {
			support.push( 'linux' );
		}

		if ( build.os_linux_64 && !build.os_linux ) {
			support.push( 'linux_64' );
		}

		if ( build.os_other ) {
			support.push( 'other' );
		}

		return support;
	}

	function checkSupport( support, type )
	{
		return support.indexOf( type ) !== -1;
	}

	return {
		restrict: 'E',
		templateUrl: '/lib/gj-lib-client/components/game/package/card/card.html',
		scope: {},
		bindToController: {
			game: '=game',
			'package': '=gamePackage',
			releases: '=gameReleases',
			builds: '=gameBuilds',
			key: '@?',
			launchOptions: '=?gameBuildLaunchOptions',
		},
		controllerAs: 'ctrl',
		controller: function( $scope, $attrs, $parse )
		{
			var _this = this;

			$scope.Environment = Environment;
			$scope.Screen = Screen;
			$scope.Game_Build = Game_Build;

			this.showFullDescription = false;
			this.canToggleDescription = undefined;

			this.supportInfo = angular.copy( supportInfo );
			this.support = [];

			this.downloadableBuild = null;
			this.browserBuild = null;
			this.extraBuilds = [];

			this.showcasedRelease = null;
			this.showcasedOs = null;
			this.showcasedOsIcon = null;
			this.showcasedBrowserIcon = null;

			this.otherOnly = false;

			// If this game is in their installed games, this will populate.
			this.installedBuild = null;

			if ( this.builds ) {

				var os = Device.os();
				var arch = Device.arch();  // Will only be set in client.

				// Indexes by the os/type of the build: [ { type: build } ]
				// While looping we also gather all OS/browser support for this complete package.
				var indexedBuilds = {};
				var otherBuilds = [];
				this.builds.forEach( function( build )
				{
					if ( build.isBrowserBased() ) {
						indexedBuilds[ build.type ] = build;
						this.support.push( build.type );
					}
					else if ( build.os_other ) {
						otherBuilds.push( build );
					}
					else {
						var support = pluckOsSupport( build );
						support.forEach( function( _os )
						{
							indexedBuilds[ _os ] = build;
							this.support.push( this.supportInfo[ _os ].icon );
						}, this );
					}
				}, this );

				this.support = _.uniq( this.support );

				// At this point we should have all the OS/browser support, so let's sort it.
				// The sort values are defined above, but we want to push their detected OS at
				// the front. This is because you'd probably want to see [linux] first if you're
				// on a linux machine, before windows, etc.
				// We change the sort for their detected OS to be the first before sorting.
				this.supportInfo[ os ].sort = 0;
				this.support.sort( function( a, b )
				{
					return _this.supportInfo[ a ].sort - _this.supportInfo[ b ].sort;
				} );

				// Now that we have all the builds indexed by the platform they support
				// we need to try to pick one to showcase as the default download. We put
				// their detected OS first so that it tries to pick that one first.
				// Arch is only detected in Client.
				var checkDownloadables = [ 'windows', 'windows_64', 'mac', 'linux' ];

				// This will put the 64 bit version as higher priority.
				if ( arch == '64' ) {
					checkDownloadables.unshift( os );
					checkDownloadables.unshift( os + '_64' );
				}
				// If we don't have a detected arch that is 64, we prioritize the universal version.
				else {
					checkDownloadables.unshift( os + '_64' );
					checkDownloadables.unshift( os );
				}

				checkDownloadables.every( function( _os )
				{
					if ( !indexedBuilds[ _os ] ) {
						return true;
					}
					this.downloadableBuild = indexedBuilds[ _os ];
					this.showcasedOs = _os;
					this.showcasedOsIcon = _this.supportInfo[ _os ].icon;
				}, this );

				// Do the same with browser type. Pick the default browser one to show.
				[ 'html', 'flash', 'unity', 'applet', 'silverlight' ].every( function( type )
				{
					if ( !indexedBuilds[ type ] ) {
						return true;
					}
					this.browserBuild = indexedBuilds[ type ];
					this.showcasedBrowserIcon = _this.supportInfo[ type ].icon;
				}, this );

				// Pull the showcased release version.
				// It should be the greater one for either the downloadable or browser build chosen.
				if ( this.downloadableBuild ) {
					this.showcasedRelease = this.downloadableBuild._release;
				}

				// Lower sort value is a "newer" version.
				if ( this.browserBuild && (!this.showcasedRelease || this.browserBuild._release.sort < this.showcasedRelease) ) {
					this.showcasedRelease = this.browserBuild._release;
				}

				// Now pull the extra builds (ones that aren't default).
				angular.forEach( indexedBuilds, function( build, type )
				{
					if ( build == _this.downloadableBuild && type == _this.showcasedOs ) {
						return;
					}

					if ( build.type != Game_Build.TYPE_DOWNLOADABLE ) {
						if ( _this.browserBuild && _this.browserBuild.id == build.id ) {
							return;
						}
					}

					_this.extraBuilds.push( {
						type: build.type,
						icon: _this.supportInfo[ type ].icon,
						build: build,
						arch: _this.supportInfo[ type ].arch || null,
						platform: type,
					} );
				} );

				// Add all the "Other" builds onto the end of extra.
				if ( otherBuilds.length ) {
					otherBuilds.forEach( function( build )
					{
						_this.extraBuilds.push( {
							type: build.type,
							icon: _this.supportInfo['other'].icon,
							build: build,
							platform: 'other',
						} );
					} );
				}

				// Sort extra builds if there are any.
				if ( this.extraBuilds.length ) {
					this.extraBuilds.sort( function( a, b )
					{
						return _this.supportInfo[ a.platform ].sort - _this.supportInfo[ b.platform ].sort;
					} );
				}

				if ( !this.downloadableBuild && !this.browserBuild && otherBuilds.length ) {
					this.otherOnly = true;
					this.showcasedRelease = this.releases[0];
				}
			}

			this.buildClick = function( build )
			{
				if ( build.type == Game_Build.TYPE_DOWNLOADABLE ) {
					this.download( build );
				}
				else if ( build.isBrowserBased() ) {
					this.showBrowserModal( build );
				}
			};

			this.download = function( build )
			{
				Analytics.trackEvent( 'game-package-card', 'download', 'download' );

				// Bundle-only games can only live in a person's library, or as a key.
				// So if it's bundle-only, or if a key was passed in, go direct.
				if ( this.game.bundle_only || this.key ) {

					// If already waiting on a download, don't do anything.
					if ( downloadPromise ) {
						return;
					}

					// If they click away from the page before the download starts, then cancel the download redirect.
					var shouldTransition = true;
					var downloadUrl = null;
					var downloadPromise = build.getDownloadUrl( { key: this.key } )
						.then( function( response )
						{
							downloadUrl = response.downloadUrl;

							// Be sure to log the build download.
							return HistoryTick.sendBeacon( 'game-build', build.id );
						} )
						.then( function()
						{
							if ( shouldTransition ) {
								$window.location = downloadUrl;
							}
							downloadPromise = null;
						} );

					$scope.$on( '$stateChangeStart', function()
					{
						shouldTransition = false;
					} );
				}
				// Client needs to download externally.
				else if ( Environment.isClient ) {
					var gui = require( 'nw.gui' );
					gui.Shell.openExternal( Environment.baseUrl + $state.href( 'discover.games.view.download.build', { slug: this.game.slug, id: this.game.id, buildId: build.id } ) );
					Popover.hideAll();
				}
				else {
					$state.go( 'discover.games.view.download.build', { slug: this.game.slug, id: this.game.id, buildId: build.id } );
				}
			};

			this.showBrowserModal = function( build )
			{
				Analytics.trackEvent( 'game-package-card', 'download', 'play' );

				// TODO: This only goes to game page. We need to direct to a URL that would open the correct build in a modal.
				if ( Environment.isClient && build.type != Game_Build.TYPE_HTML ) {
					var gui = require( 'nw.gui' );
					gui.Shell.openExternal( Environment.baseUrl + $state.href( 'discover.games.view.overview', { slug: this.game.slug, id: this.game.id } ) );
					Popover.hideAll();
				}
				else {
					Game_PlayModal.show( this.game, build );
				}
			};
		}
	};
} );
<|endoftext|>


<commit_before>const net = require('net')
const find = require('array-find')
const assign = require('object-assign')
const each = require('each-async')
const Map = require('es6-map')
const User = require('./User')
const Channel = require('./Channel')
const Message = require('./Message')
const defaultCommands = require('./defaultCommands')
const isValidChannelName = require('./util/isValidChannelName')

const debug = require('debug')('ircs:Server')

/**
 * Represents a single IRC server.
 */
module.exports = class Server extends net.Server {
  /**
   * Creates a server instance.
   *
   * @see Server
   * @return {Server}
   */
  static createServer (options, connectionListener) {
    return new Server(options, connectionListener)
  }

  static defaultOptions () {
    return {
      useDefaultCommands: true
    }
  }

  /**
   * Create an IRC server.
   *
   * @param {Object} options `net.Server` options.
   * @param {function()} connectionListener `net.Server` connection listener.
   */
  constructor (options, connectionListener) {
    options = Object.assign(Server.defaultOptions(), options)

    super(options, connectionListener)

    this.created = new Date()
    this._middleware = []
    this.users = []
    this.channels = new Map()
    this.hostname = options.hostname || 'localhost'

    this.on('connection', sock => {
      debug('incoming connection', sock.remoteAddress)
      const user = new User(sock)
      this.users.push(user)
      user.on('readable', () => {
        let message = user.read()
        if (message) {
          // woo.
          debug('message', message + '')
          this.execute(message)
        }
      })
    })

    if (options.useDefaultCommands) {
      defaultCommands(this)
    }

    debug('server started')
  }

  /**
   * Finds a user by their nickname.
   *
   * @param {string} nickname Nickname to look for.
   *
   * @return {User|undefined} Relevant User object if found, `undefined` if not found.
   */
  findUser (nickname) {
    nickname = normalize(nickname)
    return find(this.users, user => normalize(user.nickname) === nickname)
  }

  /**
   * Finds a channel on the server.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel|undefined} Relevant Channel object if found, `undefined` if not found.
   */
  findChannel (channelName) {
    return this.channels.get(normalize(channelName))
  }

  /**
   * Creates a new channel with the given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The new Channel.
   */
  createChannel (channelName) {
    channelName = normalize(channelName)
    if (!isValidChannelName(channelName)) {
      throw new Error('Invalid channel name')
    }

    if (!this.channels.has(channelName)) {
      this.channels.set(channelName, new Channel(channelName))
    }

    return this.channels.get(channelName)
  }

  /**
   * Gets a channel by name, creating a new one if it does not yet exist.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The Channel.
   */
  getChannel (channelName) {
    if (!isValidChannelName(channelName)) {
      return
    }
    return this.findChannel(channelName) || this.createChannel(channelName)
  }

  /**
   * Checks if there is a channel of a given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {boolean} True if the channel exists, false if not.
   */
  hasChannel (channelName) {
    return this.channels.has(normalize(channelName))
  }

  use (command, fn) {
    if (!fn) {
      [ command, fn ] = [ '', command ]
    }
    debug('register middleware', command)
    this._middleware.push({ command, fn })
  }

  execute (message, cb) {
    debug('exec', message + '')
    message.server = this
    each(this._middleware, (mw, idx, next) => {
      if (mw.command === '' || mw.command === message.command) {
        debug('executing', mw.command, message.parameters)
        if (mw.fn.length < 2) {
          mw.fn(message)
          next(null)
        } else {
          mw.fn(message, next)
        }
      }
    }, cb)
  }

  /**
   * Send a message to every user on the server, including the sender.
   *
   * That sounds dangerous.
   *
   * @param {Message} message Message to send.
   */
  send (message) {
    if (!(message instanceof Message)) {
      message = new Message(...arguments)
    }
    this.users.forEach(u => { u.send(message) })
  }

  /**
   * Gives the server mask.
   *
   * @return {string} Mask.
   */
  mask () {
    return this.hostname
  }
}

function normalize (str) {
  return str.toLowerCase().trim()
    // {, } and | are uppercase variants of [, ] and \ respectively
    .replace(/{/g, '[')
    .replace(/}/g, ']')
    .replace(/\|/g, '\\')
}
<commit_msg>remove unused import<commit_after>const net = require('net')
const find = require('array-find')
const each = require('each-async')
const Map = require('es6-map')
const User = require('./User')
const Channel = require('./Channel')
const Message = require('./Message')
const defaultCommands = require('./defaultCommands')
const isValidChannelName = require('./util/isValidChannelName')

const debug = require('debug')('ircs:Server')

/**
 * Represents a single IRC server.
 */
module.exports = class Server extends net.Server {
  /**
   * Creates a server instance.
   *
   * @see Server
   * @return {Server}
   */
  static createServer (options, connectionListener) {
    return new Server(options, connectionListener)
  }

  static defaultOptions () {
    return {
      useDefaultCommands: true
    }
  }

  /**
   * Create an IRC server.
   *
   * @param {Object} options `net.Server` options.
   * @param {function()} connectionListener `net.Server` connection listener.
   */
  constructor (options, connectionListener) {
    options = Object.assign(Server.defaultOptions(), options)

    super(options, connectionListener)

    this.created = new Date()
    this._middleware = []
    this.users = []
    this.channels = new Map()
    this.hostname = options.hostname || 'localhost'

    this.on('connection', sock => {
      debug('incoming connection', sock.remoteAddress)
      const user = new User(sock)
      this.users.push(user)
      user.on('readable', () => {
        let message = user.read()
        if (message) {
          // woo.
          debug('message', message + '')
          this.execute(message)
        }
      })
    })

    if (options.useDefaultCommands) {
      defaultCommands(this)
    }

    debug('server started')
  }

  /**
   * Finds a user by their nickname.
   *
   * @param {string} nickname Nickname to look for.
   *
   * @return {User|undefined} Relevant User object if found, `undefined` if not found.
   */
  findUser (nickname) {
    nickname = normalize(nickname)
    return find(this.users, user => normalize(user.nickname) === nickname)
  }

  /**
   * Finds a channel on the server.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel|undefined} Relevant Channel object if found, `undefined` if not found.
   */
  findChannel (channelName) {
    return this.channels.get(normalize(channelName))
  }

  /**
   * Creates a new channel with the given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The new Channel.
   */
  createChannel (channelName) {
    channelName = normalize(channelName)
    if (!isValidChannelName(channelName)) {
      throw new Error('Invalid channel name')
    }

    if (!this.channels.has(channelName)) {
      this.channels.set(channelName, new Channel(channelName))
    }

    return this.channels.get(channelName)
  }

  /**
   * Gets a channel by name, creating a new one if it does not yet exist.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The Channel.
   */
  getChannel (channelName) {
    if (!isValidChannelName(channelName)) {
      return
    }
    return this.findChannel(channelName) || this.createChannel(channelName)
  }

  /**
   * Checks if there is a channel of a given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {boolean} True if the channel exists, false if not.
   */
  hasChannel (channelName) {
    return this.channels.has(normalize(channelName))
  }

  use (command, fn) {
    if (!fn) {
      [ command, fn ] = [ '', command ]
    }
    debug('register middleware', command)
    this._middleware.push({ command, fn })
  }

  execute (message, cb) {
    debug('exec', message + '')
    message.server = this
    each(this._middleware, (mw, idx, next) => {
      if (mw.command === '' || mw.command === message.command) {
        debug('executing', mw.command, message.parameters)
        if (mw.fn.length < 2) {
          mw.fn(message)
          next(null)
        } else {
          mw.fn(message, next)
        }
      }
    }, cb)
  }

  /**
   * Send a message to every user on the server, including the sender.
   *
   * That sounds dangerous.
   *
   * @param {Message} message Message to send.
   */
  send (message) {
    if (!(message instanceof Message)) {
      message = new Message(...arguments)
    }
    this.users.forEach(u => { u.send(message) })
  }

  /**
   * Gives the server mask.
   *
   * @return {string} Mask.
   */
  mask () {
    return this.hostname
  }
}

function normalize (str) {
  return str.toLowerCase().trim()
    // {, } and | are uppercase variants of [, ] and \ respectively
    .replace(/{/g, '[')
    .replace(/}/g, ']')
    .replace(/\|/g, '\\')
}
<|endoftext|>


<commit_before>/* globals gtag */

const CONSUMPTIONS = /consumptions:(type|compare|granularity|normalized)/;

module.exports = function () {
  return function (state, emitter) {
    emitter.on('track', data => {
      const name = data.event_name;
      const props = Object.assign({ is_editor: false }, data);

      delete props.event_name;

      const user = state.user;
      if (user.isAuthenticated) {
        if (props.id && state.cooperatives.find(item => item._id === props.id)) {
          props.is_editor = user.cooperative === props.id;
        } else if (state.params.cooperative) {
          props.is_editor === user.cooperative === state.params.cooperative;
        } else if (state.params.action) {
          var action = state.actions.find(item => item._id === state.params.action);
          if (action) {
            props.is_editor === action.cooperative === user.cooperative;
          }
        }
      }

      // Cast boolean custom dimension to string
      props.is_editor = props.is_editor ? 'Yes' : 'No';

      gtag('event', name, props);
    });

    emitter.on(state.events.DOMCONTENTLOADED, onpageview);

    emitter.on(state.events.NAVIGATE, () => {
      requestAnimationFrame(onpageview);
    });

    emitter.on('track:exception', err => {
      gtag('event', 'exception', {
        description: err.message,
        fatal: err.status > 499
      });
    });

    emitter.on('error', err => {
      gtag('event', 'exception', {
        description: err.message,
        fatal: err.status > 499
      });
    });

    emitter.on('chart:paginate', () => {
      emitter.emit('track', {
        event_name: 'paginate',
        event_category: 'chart',
        event_label: 'paginate',
        value: state.chart.page,
        energy_type: state.consumptions.type,
        cooperative_compare: state.cooperatives.find(item => {
          const id = (/cooperative:(.+)/).match(state.consumptions.compare)[1];
          return item._id === id;
        }).name,
        energy_granularity: state.consumptions.granularity,
        energy_normalized: state.consumptions.normalized
      });
    });

    emitter.on('*', type => {
      if (typeof window !== 'undefined' && CONSUMPTIONS.test(type)) {
        emitter.emit('track', {
          event_name: 'filter',
          event_category: 'consumption',
          event_label: type.match(CONSUMPTIONS)[1],
          energy_type: state.consumptions.type,
          cooperative_compare: state.cooperatives.find(item => {
            const id = (/cooperative:(.+)/).match(state.consumptions.compare)[1];
            return item._id === id;
          }).name,
          energy_granularity: state.consumptions.granularity,
          energy_normalized: state.consumptions.normalized
        });
      }
    });

    function onpageview() {
      const props = {
        page_title: state.title.split(' | ')[0],
        page_location: window.location.href,
        page_path: state.href,
        user_id: state.user.isAuthenticated ? state.user._id : null,
        is_editor: false,
        custom_map: {
          dimension1: 'is_editor',
          dimension2: 'energy_type',
          dimension3: 'cooperative_compare',
          dimension4: 'energy_granularity',
          dimension5: 'energy_normalized'
        }
      };

      const user = state.user;
      if (user.isAuthenticated) {
        if (state.params.cooperative) {
          props.is_editor = user.cooperative === state.params.cooperative;
        } else if (state.params.action) {
          var action = state.actions.find(item => item._id === state.params.action);
          if (action) {
            props.is_editor = action.cooperative === user.cooperative;
          }
        }
      }

      // Cast boolean custom dimension to string
      props.is_editor = props.is_editor ? 'Yes' : 'No';

      gtag('config', process.env.GOOGLE_ANALYTICS_ID, props);
    }
  };
};
<commit_msg>Fix borked regex<commit_after>/* globals gtag */

const CONSUMPTIONS = /consumptions:(type|compare|granularity|normalized)/;
const COOPERATIVE_COMPARE = /cooperative:(.+)/;

module.exports = function () {
  return function (state, emitter) {
    emitter.on('track', data => {
      const name = data.event_name;
      const props = Object.assign({ is_editor: false }, data);

      delete props.event_name;

      const user = state.user;
      if (user.isAuthenticated) {
        if (props.id && state.cooperatives.find(item => item._id === props.id)) {
          props.is_editor = user.cooperative === props.id;
        } else if (state.params.cooperative) {
          props.is_editor === user.cooperative === state.params.cooperative;
        } else if (state.params.action) {
          var action = state.actions.find(item => item._id === state.params.action);
          if (action) {
            props.is_editor === action.cooperative === user.cooperative;
          }
        }
      }

      if (COOPERATIVE_COMPARE.test(props.cooperative_compare)) {
        props.cooperative_compare = state.cooperatives.find(item => {
          const id = state.consumptions.compare.match(COOPERATIVE_COMPARE)[1];
          return item._id === id;
        }).name;
      }

      // Cast boolean custom dimension to string
      props.is_editor = props.is_editor ? 'Yes' : 'No';

      gtag('event', name, props);
    });

    emitter.on(state.events.DOMCONTENTLOADED, onpageview);

    emitter.on(state.events.NAVIGATE, () => {
      requestAnimationFrame(onpageview);
    });

    emitter.on('track:exception', err => {
      gtag('event', 'exception', {
        description: err.message,
        fatal: err.status > 499
      });
    });

    emitter.on('error', err => {
      gtag('event', 'exception', {
        description: err.message,
        fatal: err.status > 499
      });
    });

    emitter.on('chart:paginate', () => {
      emitter.emit('track', {
        event_name: 'paginate',
        event_category: 'chart',
        event_label: 'paginate',
        value: state.chart.page,
        energy_type: state.consumptions.type,
        cooperative_compare: state.consumptions.compare,
        energy_granularity: state.consumptions.granularity,
        energy_normalized: state.consumptions.normalized
      });
    });

    emitter.on('*', type => {
      if (typeof window !== 'undefined' && CONSUMPTIONS.test(type)) {
        emitter.emit('track', {
          event_name: 'filter',
          event_category: 'consumption',
          event_label: type.match(CONSUMPTIONS)[1],
          energy_type: state.consumptions.type,
          cooperative_compare: state.consumptions.compare,
          energy_granularity: state.consumptions.granularity,
          energy_normalized: state.consumptions.normalized
        });
      }
    });

    function onpageview() {
      const props = {
        page_title: state.title.split(' | ')[0],
        page_location: window.location.href,
        page_path: state.href,
        user_id: state.user.isAuthenticated ? state.user._id : null,
        is_editor: false,
        custom_map: {
          dimension1: 'is_editor',
          dimension2: 'energy_type',
          dimension3: 'cooperative_compare',
          dimension4: 'energy_granularity',
          dimension5: 'energy_normalized'
        }
      };

      const user = state.user;
      if (user.isAuthenticated) {
        if (state.params.cooperative) {
          props.is_editor = user.cooperative === state.params.cooperative;
        } else if (state.params.action) {
          var action = state.actions.find(item => item._id === state.params.action);
          if (action) {
            props.is_editor = action.cooperative === user.cooperative;
          }
        }
      }

      // Cast boolean custom dimension to string
      props.is_editor = props.is_editor ? 'Yes' : 'No';

      gtag('config', process.env.GOOGLE_ANALYTICS_ID, props);
    }
  };
};
<|endoftext|>


<commit_before>#!/usr/bin/env node --harmony

var program = require('commander');
var fs = require('fs');
var chalk = require('chalk');
var JSONStream = require('JSONStream');

const DAY_IN_MILLI = 86400000;
const BG_CONVERSION = 18.01559;

program
	.version('0.0.1');

program
	.command('cbg')
	.arguments('<output> <dates> <groupId>')
	.option('--numPerDay <numPerDay>',
		'Number of events per day. Use comma separated values'
		+ ' for each date range, or one value for all dates.'
		+ ' Default is 288 cbg values.', numberList, [288])
	.option('--values <values>',
		'Range for possible cbg values in mg/dL.'
		+ 'Use comma separated values'
		+ ' for each date range, or one value for all dates.'
		+ ' Default is 100 mg/dL cbg values.', numberList, [100])
	.description('Generate cbg data.')
	.action(function(output, dates, groupId, options) {
		var dates = datesList(dates);
		if (dates.length/2 !== options.numPerDay.length
			&& options.numPerDay.length !== 1) {
			console.log(chalk.red.bold('Must have --numPerDay specified for each date pair '
				+ 'OR only specify one --numPerDay.'));
			process.exit(1);
		}
		if (dates.length !== options.values.length
			&& options.values.length !== 1) {
			console.log(chalk.red.bold('Must have --values specified for each date pair '
				+ 'OR only specify one --values.'));
			process.exit(1);
		}
		generateCbgData(output, dates, groupId, options, function() {});
	});

program
	.command('smbg')
	.arguments('<output> <dates> <groupId>')
	.option('--numPerDay <numPerDay>',
		'Number of events per day. Use comma separated values'
		+ ' for each date range, or one value for all dates.'
		+ ' Default is 1 smbg value.', numberList, [1])
	.option('--values <values>',
		'Range for possible smbg values in mg/dL.'
		+ ' Use comma separated values'
		+ ' for each date range, or one value for all dates.'
		+ ' Default is 100 mg/dL smbg values.', numberList, [100])
	.description('Generate smbg data.')
	.action(function(output, dates, groupId, options) {
		var dates = datesList(dates);
		if (dates.length/2 !== options.numPerDay.length
			&& options.numPerDay.length !== 1) {
			console.log(chalk.red.bold('Must have --numPerDay specified for each date pair '
				+ 'OR only specify one --numPerDay.'));
			process.exit(1);
		}
		if (dates.length !== options.values.length
			&& options.values.length !== 1) {
			console.log(chalk.red.bold('Must have --values specified for each date pair '
				+ 'OR only specify one --values.'));
			process.exit(1);
		}
		generateSmbgData(output, dates, groupId, options, function() {});
	});

program.parse(process.argv);

function generateCbgData(output, dates, groupId, options, callback) {
	generateSimpleData(output,
						'cbg',
						'mmol/L',
						function(val) {
							return val/BG_CONVERSION;
						},
						dates,
						groupId,
						options,
						callback);
}

function generateSmbgData(output, dates, groupId, options, callback) {
	generateSimpleData(output,
						'smbg',
						'mmol/L',
						function(val) {
							return val/BG_CONVERSION;
						},
						dates,
						groupId,
						options,
						callback);
}

function generateSimpleData(output, type, units, conversion, dates, groupId, options, callback) {

	var newData = [];

	for (var i = 0; i < dates.length; i++) {
		var start = dates[i];
		var end = dates[++i];
		var numDays = (end.getTime() - start.getTime())
						/ DAY_IN_MILLI;

		for (var j = 0; j < numDays; j++) {
			var numEvents = options.numPerDay.length === 1 ?
								options.numPerDay[0]
									: options.numPerDay[(i - 1)/2];

			for (var k = 0; k < numEvents; k++) {
				var value;
				if (options.values.length === 1) {
					value = options.values[0];
				} else {
					value = Math.random()
						* (options.values[i] - options.values[i - 1])
						+ options.values[i - 1];
				}

				var time = new Date(start);
				time.setDate(time.getDate() + j);

				newData.push({
					"_groupId": groupId,
					"clockDriftOffset": 0,
					"conversionOffset": 0,
					"createdTime": new Date().toISOString(),
					"deviceId": type + " device-Serial Number",
					"guid": "not_actually_a_guid",
					"id": "not_actually_an_id",
					"time": time.toISOString(),
					"timezoneOffset": 0,
					"type": type,
					"units": units,
					"uploadId": "upid_NA",
					"value": conversion(value)
				});
			}
		}
	}

	readExistingData(output, function(data) {
		var writeData = newData.concat(data);
		fs.writeFile(output, JSON.stringify(writeData), function(err) {
			if (err) {
				console.error(chalk.red.bold('An error occurred with writing the file.'));
				process.exit(1);
			}
			callback();
		});
	});

}

function datesList(string) {
	var dates = string.split(',');
 	if (dates.length%2 !== 0) {
		console.error(chalk.red.bold(
			'Dates arguments must come in pairs.'));
		process.exit(1);
	}
	return dates.map(function(str) {
		return new Date(str);
	});
}

function numberList(string) {
	return string.split(',').map(Number);
}

function readExistingData(filename, callback) {

	fs.exists(filename, function(exists) {
		if (!exists) {
			callback([]);
			return;
		}

		var ifs = fs.createReadStream(filename, {encoding: 'utf8'});
		var jsonStream = JSONStream.parse();
		ifs
			.pipe(jsonStream)
			.on('data', function(data) {
				callback(data);
			});
	});

}<commit_msg>refactor generatedata to abstract common fields<commit_after>#!/usr/bin/env node --harmony

var program = require('commander');
var fs = require('fs');
var chalk = require('chalk');
var JSONStream = require('JSONStream');

const DAY_IN_MILLI = 86400000;
const BG_CONVERSION = 18.01559;

program
	.version('0.0.1');

program
	.command('cbg')
	.arguments('<output> <dates> <groupId>')
	.option('--numPerDay <numPerDay>',
		'Number of events per day.'
		+ 'Use comma separated values'
		+ ' for a value range, or one exact value.'
		+ ' Default is 288 cbg values per day.', numberList, [288])
	.option('--values <values>',
		'Range for possible cbg values in mg/dL.'
		+ 'Use comma separated values'
		+ ' for a value range, or one exact value.'
		+ ' Default is 100 mg/dL cbg values.', numberList, [100])
	.description('Generate cbg data.')
	.action(function(output, dates, groupId, options) {
		var dates = datesList(dates);

		checkDatesAndOptionsWithExit(dates, options);

		generateCbgData(output, dates, groupId, options, function() {});
	});

program
	.command('smbg')
	.arguments('<output> <dates> <groupId>')
	.option('--numPerDay <numPerDay>',
		'Number of events per day.'
		+ 'Use comma separated values'
		+ ' for a value range, or one exact value.'
		+ ' Default is 288 cbg values per day.', numberList, [288])
	.option('--values <values>',
		'Range for possible cbg values in mg/dL.'
		+ 'Use comma separated values'
		+ ' for a value range, or one exact value.'
		+ ' Default is 100 mg/dL cbg values.', numberList, [100])
	.description('Generate smbg data.')
	.action(function(output, dates, groupId, options) {
		var dates = datesList(dates);

		checkDatesAndOptionsWithExit(dates, options);

		generateSmbgData(output, dates, groupId, options, function() {});
	});

program.parse(process.argv);

function generateCbgData(output, dates, groupId, options, callback) {
	var extras = {
		"type": "cbg",
		"units": "mmol/L",
		"value": randomValueInRange(options.values) / BG_CONVERSION
	}

	generateDataWithExtras(output,
						extras,
						dates,
						groupId,
						options,
						callback);
}

function generateSmbgData(output, dates, groupId, options, callback) {
	var extras = {
		"type": "smbg",
		"units": "mmol/L",
		"value": randomValueInRange(options.values) / BG_CONVERSION
	}

	generateDataWithExtras(output,
						extras,
						dates,
						groupId,
						options,
						callback);
}

function generateDataWithExtras(output, extras, dates, groupId, options, callback) {

	var newData = [];

	var start = dates[0];
	var end = dates[1];

	var numDays = (end.getTime() - start.getTime())
					/ DAY_IN_MILLI;

	for (var i = 0; i < numDays; i++) {
		var numEvents = randomValueInRange(options.numPerDay);

		for (var j = 0; j < numEvents; j++) {

			var time = new Date(start);
			time.setDate(time.getDate() + i);

			var common = {
				"_groupId": groupId,
				"clockDriftOffset": 0,
				"conversionOffset": 0,
				"createdTime": new Date().toISOString(),
				"deviceId": extras.type + " device-Serial Number",
				"deviceTime": time.toISOString(),
				"guid": "not_actually_a_guid",
				"id": "not_actually_an_id",
				"time": time.toISOString(),
				"timezoneOffset": 0,
				"uploadId": "upid_NA"
			};

			for (var key in extras) {
				common[key] = extras[key];
			}

			newData.push(common);
		}
	}

	readExistingData(output, function(data) {
		var writeData = newData.concat(data);
		fs.writeFile(output, JSON.stringify(writeData), function(err) {
			if (err) {
				console.error(chalk.red.bold('An error occurred with writing the file.'));
				process.exit(1);
			}
			callback();
		});
	});

}

function randomValueInRange(range) {
	if (range.length === 1) {
		return range[0];
	}
	return Math.random()
		* (range[1] - range[0])
		+ range[0];
}

function checkDatesAndOptionsWithExit(dates, options) {

	if (dates.length !== 2) {
		console.log(chalk.red.bold('Must have a date range with exactly'
			+ ' two dates.'));
		process.exit(1);
	}
	if (options.numPerDay.length !== 2
		&& options.numPerDay.length !== 1) {
		console.log(chalk.red.bold('For --numPerDay, must specify a '
			+ 'range or an exact value.'));
		process.exit(1);
	}
	if (options.values.length !== 2
		&& options.values.length !== 1) {
		console.log(chalk.red.bold('For --values, must specify a '
			+ 'range or an exact value.'));
		process.exit(1);
	}

}

function datesList(string) {
	var dates = string.split(',');
	return dates.map(function(str) {
		return new Date(str);
	});
}

function numberList(string) {
	return string.split(',').map(Number);
}

function readExistingData(filename, callback) {

	fs.exists(filename, function(exists) {
		if (!exists) {
			callback([]);
			return;
		}

		var ifs = fs.createReadStream(filename, {encoding: 'utf8'});
		var jsonStream = JSONStream.parse();
		ifs
			.pipe(jsonStream)
			.on('data', function(data) {
				callback(data);
			});
	});

}<|endoftext|>


<commit_before>    /**
     * Created by JetBrains WebStorm.
     * User: creynder
     * Date: 21/09/11
     * Time: 14:53
     * To change this template use File | Settings | File Templates.
     */
    var system;

    function TestClassA(){
        this.name = 'TestClassA';
    }

    function TestClassB(){
        this.name = 'TestClassB';

        this.bar = undefined;
    }

    //TODO: test Injectro#setValue

    module( 'dijon.system', {
        setup : function(){
            system = new dijon.System();
        },
        teardown : function(){
            system = undefined;
        }
    });

    test( 'mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapClass: hasMapping', function(){
        system.mapClass( 'a', function(){} );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapClass: unique instances', function(){
        var SomeClass = function(){
        }
        system.mapClass( 'o', SomeClass );

        var s1 = system.getObject( 'o' );
        var s2 = system.getObject( 'o' );

        ok( s1 instanceof SomeClass );
        ok( s2 instanceof SomeClass );
        notEqual( s1, s2 );
    })

    test( 'injectInto', function(){
        var UserModel = function(){
        }
        system.mapSingleton( 'userModel', UserModel );
        var SomeClass = function(){
             user = undefined; //inject
        }
        system.mapSingleton( 'o', SomeClass );
        system.mapOutlet( 'userModel', 'o', 'user' );

        var foo = {
              user : undefined //inject
        }

        system.injectInto( foo, 'o' );

        strictEqual( foo.user, system.getObject( 'userModel' ) );
    })

    test( 'getObject for mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        var inj = system;
        var a = system.getObject( 'a' );
        ok( a instanceof TestClassA, 'must be instance of TestClassA' );
        strictEqual( system.getObject( 'a' ), a, 'must be single instance' );
    })

    test( 'getObject for mapClass', function(){
        system.mapClass( 'a', TestClassA );
        var a = system.getObject( 'a' );
        ok( a instanceof TestClassA );
        notStrictEqual( system.getObject( 'a' ), a );
    })

    test( 'getObject for mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        strictEqual( system.getObject( 'a' ), a );
    })

    test( 'instantiate for mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        var a = system.getObject( 'a' );
        notStrictEqual( system.instantiate( 'a' ), a, 'instantiate must always provide a new instance regardless of rules' );
    })

    test( 'instantiate for mapClass', function(){
        system.mapClass( 'a', TestClassA );
        var a = system.getObject( 'a' );
        notStrictEqual( system.instantiate( 'a' ), a );
    })

    test( 'instantiate for mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        var result = system.instantiate( 'a' );
        strictEqual( result, a );
    })

    test( 'unmap', function(){
        system.mapSingleton( 'a', TestClassA )
        system.unmap( 'a' );
        ok( ! system.hasMapping( 'a' ) );
    })

    test( 'mapOutlet: all params given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        var o = {
            user : undefined //inject
        }
        system.mapOutlet( 'userModel', 'o', 'user' );
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.user instanceof TestClassA );
    })

    test( 'mapOutlet: source and target given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        var o = {
            userModel : undefined //inject
        }
        system.mapOutlet( 'userModel', 'o' );
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.userModel instanceof TestClassA );
    })

    test( 'mapOutlet: source given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        system.mapOutlet( 'userModel' );
        var o = {
            userModel : undefined //inject
        }
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.userModel instanceof TestClassA );
    })

    test( 'removeOutlet', function() {
        system.mapSingleton( 'a', TestClassA );
        system.mapSingleton( 'b', TestClassB );
        system.mapOutlet( 'a', 'b', 'bar' );
        system.unmapOutlet( 'b', 'bar' );
        var b = system.getObject( 'b' );
        strictEqual( b.bar, undefined );
    })
    test( 'mapHandler: event, key and handlerName given', function(){
        var hasExecuted = false;
        var userView = {
             showUserProfile : function(){
                 hasExecuted = true;
             }
        }
        system.mapValue( 'userView', userView );
        system.mapHandler( 'user/profile', 'userView', 'showUserProfile' );
        system.notify( 'user/profile' );

        ok( hasExecuted );
    })
    test( 'mapHandler: event and key given', function(){
        var hasExecuted = false;
        var userView = {
             showUserProfile : function(){
                 hasExecuted = true;
             }
        }
        system.mapValue( 'userView', userView );
        system.mapHandler( 'showUserProfile', 'userView' );
        system.notify( 'showUserProfile' );

        ok( hasExecuted );
    })
    test( 'mapHandler: event and handler given', function(){
        var hasExecuted = false;
        var showUserProfile = function(){
             hasExecuted = true;
        }
        system.mapHandler( 'showUserProfile', undefined, showUserProfile );
        system.notify( 'showUserProfile' );

        ok( hasExecuted );
    })

    test( 'mapHandler: oneShot', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a', undefined, true );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        ok( hasExecuted==1);
    })

    test( 'unmapHandler: simple use', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.unmapHandler( 'loginStart', 'a' );
        system.notify( 'loginStart' );
        ok( hasExecuted == 2 );
    })
<commit_msg>added primitive value mapping test<commit_after>    /**
     * Created by JetBrains WebStorm.
     * User: creynder
     * Date: 21/09/11
     * Time: 14:53
     * To change this template use File | Settings | File Templates.
     */
    var system;

    function TestClassA(){
        this.name = 'TestClassA';
    }

    function TestClassB(){
        this.name = 'TestClassB';

        this.bar = undefined;
    }

    //TODO: test Injectro#setValue

    module( 'dijon.system', {
        setup : function(){
            system = new dijon.System();
        },
        teardown : function(){
            system = undefined;
        }
    });

    test( 'mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        ok( system.hasMapping( 'a' ) );
    });

    test( 'mapValue, constructor function', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        ok( system.hasMapping( 'a' ) );
    });

	test( 'mapValue, generic object: dependencies should be satisified', function(){
		var foo = {};
		system.mapValue( 'foo', foo );
		var a = {
			foo : undefined
		};
		system.mapOutlet( 'foo', 'a', 'foo' );
		system.mapValue( 'a', a );
		strictEqual( a.foo, foo );
	} );

	test( 'mapValue, string', function(){
		var a = 'mofo';
		system.mapValue( 'a', a );
		strictEqual( system.getObject( 'a'), a );
	} );

    test( 'mapClass: hasMapping', function(){
        system.mapClass( 'a', function(){} );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapClass: unique instances', function(){
        var SomeClass = function(){
        }
        system.mapClass( 'o', SomeClass );

        var s1 = system.getObject( 'o' );
        var s2 = system.getObject( 'o' );

        ok( s1 instanceof SomeClass );
        ok( s2 instanceof SomeClass );
        notEqual( s1, s2 );
    })

    test( 'injectInto', function(){
        var UserModel = function(){
        }
        system.mapSingleton( 'userModel', UserModel );
        var SomeClass = function(){
             user = undefined; //inject
        }
        system.mapSingleton( 'o', SomeClass );
        system.mapOutlet( 'userModel', 'o', 'user' );

        var foo = {
              user : undefined //inject
        }

        system.injectInto( foo, 'o' );

        strictEqual( foo.user, system.getObject( 'userModel' ) );
    })

    test( 'getObject for mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        var inj = system;
        var a = system.getObject( 'a' );
        ok( a instanceof TestClassA, 'must be instance of TestClassA' );
        strictEqual( system.getObject( 'a' ), a, 'must be single instance' );
    })

    test( 'getObject for mapClass', function(){
        system.mapClass( 'a', TestClassA );
        var a = system.getObject( 'a' );
        ok( a instanceof TestClassA );
        notStrictEqual( system.getObject( 'a' ), a );
    })

    test( 'getObject for mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        strictEqual( system.getObject( 'a' ), a );
    })

    test( 'instantiate for mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        var a = system.getObject( 'a' );
        notStrictEqual( system.instantiate( 'a' ), a, 'instantiate must always provide a new instance regardless of rules' );
    })

    test( 'instantiate for mapClass', function(){
        system.mapClass( 'a', TestClassA );
        var a = system.getObject( 'a' );
        notStrictEqual( system.instantiate( 'a' ), a );
    })

    test( 'instantiate for mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        var result = system.instantiate( 'a' );
        strictEqual( result, a );
    })

    test( 'unmap', function(){
        system.mapSingleton( 'a', TestClassA )
        system.unmap( 'a' );
        ok( ! system.hasMapping( 'a' ) );
    })

    test( 'mapOutlet: all params given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        var o = {
            user : undefined //inject
        }
        system.mapOutlet( 'userModel', 'o', 'user' );
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.user instanceof TestClassA );
    })

    test( 'mapOutlet: source and target given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        var o = {
            userModel : undefined //inject
        }
        system.mapOutlet( 'userModel', 'o' );
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.userModel instanceof TestClassA );
    })

    test( 'mapOutlet: source given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        system.mapOutlet( 'userModel' );
        var o = {
            userModel : undefined //inject
        }
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.userModel instanceof TestClassA );
    })

    test( 'removeOutlet', function() {
        system.mapSingleton( 'a', TestClassA );
        system.mapSingleton( 'b', TestClassB );
        system.mapOutlet( 'a', 'b', 'bar' );
        system.unmapOutlet( 'b', 'bar' );
        var b = system.getObject( 'b' );
        strictEqual( b.bar, undefined );
    })
    test( 'mapHandler: event, key and handlerName given', function(){
        var hasExecuted = false;
        var userView = {
             showUserProfile : function(){
                 hasExecuted = true;
             }
        }
        system.mapValue( 'userView', userView );
        system.mapHandler( 'user/profile', 'userView', 'showUserProfile' );
        system.notify( 'user/profile' );

        ok( hasExecuted );
    })
    test( 'mapHandler: event and key given', function(){
        var hasExecuted = false;
        var userView = {
             showUserProfile : function(){
                 hasExecuted = true;
             }
        }
        system.mapValue( 'userView', userView );
        system.mapHandler( 'showUserProfile', 'userView' );
        system.notify( 'showUserProfile' );

        ok( hasExecuted );
    })
    test( 'mapHandler: event and handler given', function(){
        var hasExecuted = false;
        var showUserProfile = function(){
             hasExecuted = true;
        }
        system.mapHandler( 'showUserProfile', undefined, showUserProfile );
        system.notify( 'showUserProfile' );

        ok( hasExecuted );
    })

    test( 'mapHandler: oneShot', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a', undefined, true );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        ok( hasExecuted==1);
    })

    test( 'unmapHandler: simple use', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.unmapHandler( 'loginStart', 'a' );
        system.notify( 'loginStart' );
        ok( hasExecuted == 2 );
    })
<|endoftext|>


<commit_before>var React = require('react-native');
var AdSupportIOS = require('AdSupportIOS');
var Dimensions = require('Dimensions');

module.exports = {
  getClientId(cb) {
    AdSupportIOS.getAdvertisingId(function(advertisingId) {
      cb(null, advertisingId);
    }, cb);
  },
  device: {
    height: Dimensions.get('window').height,
    width: Dimensions.get('window').width
  }
};
<commit_msg>Upgrading google analytics<commit_after>var React = require('react-native');
var AdSupportIOS = React.AdSupportIOS;
var Dimensions = require('Dimensions');

module.exports = {
  getClientId(cb) {
    AdSupportIOS.getAdvertisingId(function(advertisingId) {
      cb(null, advertisingId);
    }, cb);
  },
  device: {
    height: Dimensions.get('window').height,
    width: Dimensions.get('window').width
  }
};
<|endoftext|>


<commit_before>$(document).ready(function(){

	var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera",
			versionSearch: "Version"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			   string: navigator.userAgent,
			   subString: "iPhone",
			   identity: "iPhone/iPod"
	    },
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

	};

		BrowserDetect.init();

		if((BrowserDetect.browser=='Firefox'&&BrowserDetect.version<12)||(BrowserDetect.browser=='Explorer'&&BrowserDetect.version<9)) {
			$('#browserModal').modal('show');
			console.log(BrowserDetect.version);
		}

	/***************************************************/
	/*************** HEADER ****************************/
	/***************************************************/

	/*************** USER LOGIN ************************/

	$('#sign-in').click(function(){
		$('#user-modal-body').empty().append('');
		$('#user-modal').modal('show');
		return false;
	});

	$('#user-modal').bind('authenticated',function(){
		$('#sign-in').hide();
		$('#user-dropdown').show();
		$('#jda-header-me').show();
		if(!_.isUndefined(window.jda))jda.app.userAuthenticated();
		return false;
	});

	$('#user-modal').bind('close',function(){$("#user-modal-close").trigger('click');});

	/*************** ACCOUNT SETTINGS ************************/

	$('#account-settings').click(function(){
		$('#user-modal-body').empty().append('');
		$('#user-modal').modal('show');
		return false;

	});

	/************  BUG REPORT **********************/

	$('.bug-report').click(function(e){e.stopPropagation();});

	$('.bug-report').parent().click(function(){
		$('.bug-unsubmitted').show();
		$('.bug-submitted').hide();
	});

	$('.close-bug').click(function(){
		$('.bug-report').parent().trigger('click');
	});

	$('.submit-bug').click(function(){

		var bug = new Backbone.Model({

			url:window.location.href,
			hash: window.location.hash.substr(1),
			description: $('.bug-description').val(),
			email: $('.bug-email').val(),
			browser: BrowserDetect.browser,
			version: BrowserDetect.version,
			os:BrowserDetect.OS,
			login:sessionStorage.getItem('user')

		});

		bug.url="../bugs/report.php";
		bug.save();
		$('.bug-description').attr('value','');
		$('.bug-unsubmitted').fadeOut('fast',function(){
				$('.bug-submitted').fadeIn();
		});

	});

	/*************** LANGUAGE TOGGLE ************************/
	$('#jda-language-toggle').find('.btn').click(function(){
		if(!$(this).hasClass('active')){
			console.log('switching languages');
			$('#jda-language-toggle').find('.btn').removeClass('active');
			$(this).addClass('active');
			console.log($(this).data('language'));
			if($(this).data('language')=='en') window.location =  window.location.href.replace('/ja/','/en/');
			else window.location =  window.location.href.replace('/en/','/ja/');
		}

	});

	/*********** SEARCH SPECIFIC GO TO PROFILE PAGE ****************/

  $("#jda-search-button-group,#search-bar").fadeTo('fast',1);

  //View buttons toggle
  $("#zeega-view-buttons button").tooltip({'placement':'bottom', delay: { show: 600, hide: 100 }});

  $('#zeega-view-buttons a').click(function(){ jda.app.switchViewTo( $(this).data('goto-view') , true); return false; });

  $('#zeega-search-help').popover({'title':l.jda_searching,'placement':'bottom'});

  $('#zeega-content-type').change(function(){
    $('#select-wrap-text').text( $('#zeega-content-type option[value=\''+$('#zeega-content-type').val()+'\']').text() );
    jda.app.parseSearchUI();
    return false;
  });

  $(window).resize(function() {
    if (jda.app.currentView == "event"){
      jda.app.eventMap.resetMapSize();
    }
  });

  $('#jda-go-button').click(function(){
        var e = jQuery.Event("keydown");
		e.which = 13;

		//For whatever reason there are two ways of telling VS to search
		//based on whether the facet has been created yet or not
		if ( $(".search_facet_input_container input").length ){
			$(".search_facet_input_container input").trigger(e);
		} else{
			VisualSearch.searchBox.searchEvent(e);
		}

        return false;
    });

  //Infinite Scroll
  jda.app.killScroll = false;
  $(window).scroll(function(){
    //don't execute if the app is loading, if it's too far down, or if the viewing the map event view
    if  ( jda.app.isLoading === false && $(window).scrollTop()+200 >= ($(document).height() - ($(window).height())) && jda.app.currentView != 'event' ) {
        // Keeps the loader from fetching more than once.
        if (jda.app.killScroll === false) {
            ('#spinner-text').fadeTo('fast',1);
            $('#jda-left').fadeTo('slow',0.8);
            jda.app.killScroll = true;
            jda.app.searchObject.page=jda.app.resultsView.collection.search.page+1;
            jda.app.search(jda.app.searchObject);
      }
    }
  });

  //Sets variable for Fancybox "more" view to false each time the page is reloaded
  sessionStorage.setItem('moreFancy', false);

  //set up fancybox lightbox plugin
  $(".thumb-fancymedia,.map-fancymedia,.list-fancymedia").fancybox({

    openEffect : 'fade',
      closeEffect : 'fade',
      openSpeed : 'fast',
      closeSpeed : 'fast',
    closeClick:false,
    nextClick:false,
    mouseWheel:false,
    fitToView:false,
    arrows:false,
    closeBtn:false,
    aspectRatio:true,
    scroll:'none',
      // Changing next gallery item
    nextEffect: 'none', // 'elastic', 'fade' or 'none'
    nextSpeed: 700,
    nextEasing: 'none',
    nextMethod: 'changeIn',

    // Changing previous gallery item
    prevEffect: 'none', // 'elastic', 'fade' or 'none'
    prevSpeed: 700,
    prevEasing: 'none',
    prevMethod: 'changeOut',

    keys: {
        next: [ 34, 39, 40], //  page down, right arrow, down arrow
        prev: [ 33, 37, 38], //  page up, left arrow, up arrow
        close: [27] // escape key
    },

      helpers : {
        title : false,
        buttons: {}

      },
      beforeClose : function() {

          if (this.fancyView !=null){
            this.fancyView.beforeClose();
          }
          $('a.btnNext, a.btnPrev, a.btnClose').fadeOut('slow');
          //set video src to null to prevent browser bug
          $('video').attr("src", null);

          //reactivate keyboard controls for OL map so arrow scrolling works again

       /*
       if (!_.isUndefined(jda.app.map)){
          var keyboardControls = jda.app.map.getControlsByClass('OpenLayers.Control.KeyboardDefaults');
          keyboardControls[0].activate();
        }

    */

      },
      afterShow : function(){
        this.fancyView.afterShow();
        $('#fancybox-buttons a.btnNext').show();
      },

    /* This is where we decide which kind of content to put in the fancybox */
      beforeLoad : function() {

      //deactivate keyboard controls for OL map so arrow scrolling doesn't scroll map too
      /*
      if (!_.isUndefined(jda.app.map)){
      var keyboardControls = jda.app.map.getControlsByClass('OpenLayers.Control.KeyboardDefaults');
      keyboardControls[0].deactivate();
      }
      */

    var Browser = jda.module("browser");
    $('#fancybox-document-cloud').remove();

    var elementID = $(this.element).attr('id');
      console.log(jda.app,elementID);
      var thisModel = jda.app.currentView == 'list' || jda.app.currentView == 'thumb' ? jda.app.resultsView.collection.get(elementID) : jda.app.eventMap.mapViewCollection.collection.get(elementID);

      this.fancyView = null;

    switch(thisModel.get("media_type")){
      case 'Image':
        this.fancyView = new Browser.Views.FancyBox.Image({model:thisModel});
        break;
      case 'Video':
        this.fancyView = new Browser.Views.FancyBox.Video({model:thisModel});
        break;
      case 'Audio':
        this.fancyView = new Browser.Views.FancyBox.Audio({model:thisModel});
        break;
      case 'Tweet':
        this.fancyView = new Browser.Views.FancyBox.Tweet({model:thisModel});
        break;
      case 'Text':
        this.fancyView = new Browser.Views.FancyBox.Testimonial({model:thisModel});
        break;
      case 'Document':
        this.fancyView = new Browser.Views.FancyBox.DocumentCloud({model:thisModel});
        break;
      case 'Website':
        this.fancyView = new Browser.Views.FancyBox.Website({model:thisModel});
        break;

      }

          this.fancyView.render(this);
        }

  });

});<commit_msg>Added missing jQuery selector - closes #428<commit_after>$(document).ready(function(){

	var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera",
			versionSearch: "Version"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			   string: navigator.userAgent,
			   subString: "iPhone",
			   identity: "iPhone/iPod"
	    },
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

	};

		BrowserDetect.init();

		if((BrowserDetect.browser=='Firefox'&&BrowserDetect.version<12)||(BrowserDetect.browser=='Explorer'&&BrowserDetect.version<9)) {
			$('#browserModal').modal('show');
			console.log(BrowserDetect.version);
		}

	/***************************************************/
	/*************** HEADER ****************************/
	/***************************************************/

	/*************** USER LOGIN ************************/

	$('#sign-in').click(function(){
		$('#user-modal-body').empty().append('');
		$('#user-modal').modal('show');
		return false;
	});

	$('#user-modal').bind('authenticated',function(){
		$('#sign-in').hide();
		$('#user-dropdown').show();
		$('#jda-header-me').show();
		if(!_.isUndefined(window.jda))jda.app.userAuthenticated();
		return false;
	});

	$('#user-modal').bind('close',function(){$("#user-modal-close").trigger('click');});

	/*************** ACCOUNT SETTINGS ************************/

	$('#account-settings').click(function(){
		$('#user-modal-body').empty().append('');
		$('#user-modal').modal('show');
		return false;

	});

	/************  BUG REPORT **********************/

	$('.bug-report').click(function(e){e.stopPropagation();});

	$('.bug-report').parent().click(function(){
		$('.bug-unsubmitted').show();
		$('.bug-submitted').hide();
	});

	$('.close-bug').click(function(){
		$('.bug-report').parent().trigger('click');
	});

	$('.submit-bug').click(function(){

		var bug = new Backbone.Model({

			url:window.location.href,
			hash: window.location.hash.substr(1),
			description: $('.bug-description').val(),
			email: $('.bug-email').val(),
			browser: BrowserDetect.browser,
			version: BrowserDetect.version,
			os:BrowserDetect.OS,
			login:sessionStorage.getItem('user')

		});

		bug.url="../bugs/report.php";
		bug.save();
		$('.bug-description').attr('value','');
		$('.bug-unsubmitted').fadeOut('fast',function(){
				$('.bug-submitted').fadeIn();
		});

	});

	/*************** LANGUAGE TOGGLE ************************/
	$('#jda-language-toggle').find('.btn').click(function(){
		if(!$(this).hasClass('active')){
			console.log('switching languages');
			$('#jda-language-toggle').find('.btn').removeClass('active');
			$(this).addClass('active');
			console.log($(this).data('language'));
			if($(this).data('language')=='en') window.location =  window.location.href.replace('/ja/','/en/');
			else window.location =  window.location.href.replace('/en/','/ja/');
		}

	});

	/*********** SEARCH SPECIFIC GO TO PROFILE PAGE ****************/

  $("#jda-search-button-group,#search-bar").fadeTo('fast',1);

  //View buttons toggle
  $("#zeega-view-buttons button").tooltip({'placement':'bottom', delay: { show: 600, hide: 100 }});

  $('#zeega-view-buttons a').click(function(){ jda.app.switchViewTo( $(this).data('goto-view') , true); return false; });

  $('#zeega-search-help').popover({'title':l.jda_searching,'placement':'bottom'});

  $('#zeega-content-type').change(function(){
    $('#select-wrap-text').text( $('#zeega-content-type option[value=\''+$('#zeega-content-type').val()+'\']').text() );
    jda.app.parseSearchUI();
    return false;
  });

  $(window).resize(function() {
    if (jda.app.currentView == "event"){
      jda.app.eventMap.resetMapSize();
    }
  });

  $('#jda-go-button').click(function(){
        var e = jQuery.Event("keydown");
		e.which = 13;

		//For whatever reason there are two ways of telling VS to search
		//based on whether the facet has been created yet or not
		if ( $(".search_facet_input_container input").length ){
			$(".search_facet_input_container input").trigger(e);
		} else{
			VisualSearch.searchBox.searchEvent(e);
		}

        return false;
    });

  //Infinite Scroll
  jda.app.killScroll = false;
  $(window).scroll(function(){
    //don't execute if the app is loading, if it's too far down, or if the viewing the map event view
    if  ( jda.app.isLoading === false && $(window).scrollTop()+200 >= ($(document).height() - ($(window).height())) && jda.app.currentView != 'event' ) {
        // Keeps the loader from fetching more than once.
        if (jda.app.killScroll === false) {
            $('#spinner-text').fadeTo('fast',1);
            $('#jda-left').fadeTo('slow',0.8);
            jda.app.killScroll = true;
            jda.app.searchObject.page=jda.app.resultsView.collection.search.page+1;
            jda.app.search(jda.app.searchObject);
      }
    }
  });

  //Sets variable for Fancybox "more" view to false each time the page is reloaded
  sessionStorage.setItem('moreFancy', false);

  //set up fancybox lightbox plugin
  $(".thumb-fancymedia,.map-fancymedia,.list-fancymedia").fancybox({

    openEffect : 'fade',
      closeEffect : 'fade',
      openSpeed : 'fast',
      closeSpeed : 'fast',
    closeClick:false,
    nextClick:false,
    mouseWheel:false,
    fitToView:false,
    arrows:false,
    closeBtn:false,
    aspectRatio:true,
    scroll:'none',
      // Changing next gallery item
    nextEffect: 'none', // 'elastic', 'fade' or 'none'
    nextSpeed: 700,
    nextEasing: 'none',
    nextMethod: 'changeIn',

    // Changing previous gallery item
    prevEffect: 'none', // 'elastic', 'fade' or 'none'
    prevSpeed: 700,
    prevEasing: 'none',
    prevMethod: 'changeOut',

    keys: {
        next: [ 34, 39, 40], //  page down, right arrow, down arrow
        prev: [ 33, 37, 38], //  page up, left arrow, up arrow
        close: [27] // escape key
    },

      helpers : {
        title : false,
        buttons: {}

      },
      beforeClose : function() {

          if (this.fancyView !=null){
            this.fancyView.beforeClose();
          }
          $('a.btnNext, a.btnPrev, a.btnClose').fadeOut('slow');
          //set video src to null to prevent browser bug
          $('video').attr("src", null);

          //reactivate keyboard controls for OL map so arrow scrolling works again

       /*
       if (!_.isUndefined(jda.app.map)){
          var keyboardControls = jda.app.map.getControlsByClass('OpenLayers.Control.KeyboardDefaults');
          keyboardControls[0].activate();
        }

    */

      },
      afterShow : function(){
        this.fancyView.afterShow();
        $('#fancybox-buttons a.btnNext').show();
      },

    /* This is where we decide which kind of content to put in the fancybox */
      beforeLoad : function() {

      //deactivate keyboard controls for OL map so arrow scrolling doesn't scroll map too
      /*
      if (!_.isUndefined(jda.app.map)){
      var keyboardControls = jda.app.map.getControlsByClass('OpenLayers.Control.KeyboardDefaults');
      keyboardControls[0].deactivate();
      }
      */

    var Browser = jda.module("browser");
    $('#fancybox-document-cloud').remove();

    var elementID = $(this.element).attr('id');
      console.log(jda.app,elementID);
      var thisModel = jda.app.currentView == 'list' || jda.app.currentView == 'thumb' ? jda.app.resultsView.collection.get(elementID) : jda.app.eventMap.mapViewCollection.collection.get(elementID);

      this.fancyView = null;

    switch(thisModel.get("media_type")){
      case 'Image':
        this.fancyView = new Browser.Views.FancyBox.Image({model:thisModel});
        break;
      case 'Video':
        this.fancyView = new Browser.Views.FancyBox.Video({model:thisModel});
        break;
      case 'Audio':
        this.fancyView = new Browser.Views.FancyBox.Audio({model:thisModel});
        break;
      case 'Tweet':
        this.fancyView = new Browser.Views.FancyBox.Tweet({model:thisModel});
        break;
      case 'Text':
        this.fancyView = new Browser.Views.FancyBox.Testimonial({model:thisModel});
        break;
      case 'Document':
        this.fancyView = new Browser.Views.FancyBox.DocumentCloud({model:thisModel});
        break;
      case 'Website':
        this.fancyView = new Browser.Views.FancyBox.Website({model:thisModel});
        break;

      }

          this.fancyView.render(this);
        }

  });

});
<|endoftext|>


<commit_before>'use strict';

const Alexa = require('ask-sdk-core');
const rp = require('request-promise-native');

// Generates a URL used to search for an item and return a list of possible matches.
const searchUrl = function (itemName) {
    itemName = itemName.replace(' ', '+');
    return 'https://recollect.net/api/areas/recology-1051/services/waste/pages?suggest=' + escape(itemName) + '&type=material&set=default&include_links=true&locale=en-US&accept_list=true';
};

// Generates a URL used to return a specific item.
const itemUrl = function (itemId) {
    return 'https://recollect.net/api/areas/recology-1051/services/waste/pages/en-US/' + itemId + '.json';
}

// Generates options for request-promise.
const searchOptions = function (itemName) {
    return {
        method: 'GET',
        uri: searchUrl(itemName),
        json: true
    }
}

// Generates options for request-promise.
const itemOptions = function (itemId) {
    return {
        method: 'GET',
        uri: itemUrl(itemId),
        json: true
    }
}
const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speechText = 'Bin Buddy can tell you where to put any item.';
        const repromptText = 'Ask me where to put an item.';
        return handlerInput.responseBuilder
            .speak(speechText)
            .reprompt(repromptText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const GetItemIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'GetItemIntent';
    },
    async handle(handlerInput) {
        const itemSlot = handlerInput.requestEnvelope.request.intent.slots.Item;
        let itemName;
        let binName = 'unknown';
        if (!itemSlot || !itemSlot.value) {
            return handlerInput.responseBuilder
                .speak("Sorry, I didn't hear an item name. Ask where to put an item.")
                .getResponse();
        }
        itemName = itemSlot.value.toLowerCase();
        console.log('Item name is ' + itemName);
        await rp(searchOptions(itemName))
            .then(function (items) {
                if (!items || !items[0] || !items[0].id) {
                    console.log('No item found');
                    return;
                }
                const itemId = items[0].id;
                console.log('Item ID is ' + itemId);
                return rp(itemOptions(itemId))
                    .then(function (item) {
                        binName = item.sections[1].title;
                        console.log('Bin name is ' + binName);
                    });
            });
        let speechText = "Sorry, I don't know where to put " + itemName;
        if (binName != 'unknown') {
            const speechText = 'Please put ' + itemName + ' in the ' + binName + ' bin';
        }
        return handlerInput.responseBuilder
            .speak(speechText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const HelpIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
    },
    handle(handlerInput) {
        const speechText = 'Bin Buddy can tell you where to put any item.';
        const repromptText = 'Ask me where to put an item.';

        return handlerInput.responseBuilder
            .speak(speechText)
            .reprompt(repromptText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const CancelAndStopIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
                || handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
    },
    handle(handlerInput) {
        const speechText = 'Goodbye!';

        return handlerInput.responseBuilder
            .speak(speechText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const SessionEndedRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
    },
    handle(handlerInput) {
        //any cleanup logic goes here
        return handlerInput.responseBuilder.getResponse();
    }
};

exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(LaunchRequestHandler,
        GetItemIntentHandler,
        HelpIntentHandler,
        CancelAndStopIntentHandler,
        SessionEndedRequestHandler)
    .lambda();<commit_msg>Fixed typo.<commit_after>'use strict';

const Alexa = require('ask-sdk-core');
const rp = require('request-promise-native');

// Generates a URL used to search for an item and return a list of possible matches.
const searchUrl = function (itemName) {
    itemName = itemName.replace(' ', '+');
    return 'https://recollect.net/api/areas/recology-1051/services/waste/pages?suggest=' + escape(itemName) + '&type=material&set=default&include_links=true&locale=en-US&accept_list=true';
};

// Generates a URL used to return a specific item.
const itemUrl = function (itemId) {
    return 'https://recollect.net/api/areas/recology-1051/services/waste/pages/en-US/' + itemId + '.json';
}

// Generates options for request-promise.
const searchOptions = function (itemName) {
    return {
        method: 'GET',
        uri: searchUrl(itemName),
        json: true
    }
}

// Generates options for request-promise.
const itemOptions = function (itemId) {
    return {
        method: 'GET',
        uri: itemUrl(itemId),
        json: true
    }
}
const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speechText = 'Bin Buddy can tell you where to put any item.';
        const repromptText = 'Ask me where to put an item.';
        return handlerInput.responseBuilder
            .speak(speechText)
            .reprompt(repromptText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const GetItemIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'GetItemIntent';
    },
    async handle(handlerInput) {
        const itemSlot = handlerInput.requestEnvelope.request.intent.slots.Item;
        let itemName;
        let binName = 'unknown';
        if (!itemSlot || !itemSlot.value) {
            return handlerInput.responseBuilder
                .speak("Sorry, I didn't hear an item name. Ask where to put an item.")
                .getResponse();
        }
        itemName = itemSlot.value.toLowerCase();
        console.log('Item name is ' + itemName);
        await rp(searchOptions(itemName))
            .then(function (items) {
                if (!items || !items[0] || !items[0].id) {
                    console.log('No item found');
                    return;
                }
                const itemId = items[0].id;
                console.log('Item ID is ' + itemId);
                return rp(itemOptions(itemId))
                    .then(function (item) {
                        binName = item.sections[1].title;
                        console.log('Bin name is ' + binName);
                    });
            });
        let speechText = "Sorry, I don't know where to put " + itemName;
        if (binName != 'unknown') {
            speechText = 'Please put ' + itemName + ' in the ' + binName + ' bin';
        }
        return handlerInput.responseBuilder
            .speak(speechText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const HelpIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
    },
    handle(handlerInput) {
        const speechText = 'Bin Buddy can tell you where to put any item.';
        const repromptText = 'Ask me where to put an item.';

        return handlerInput.responseBuilder
            .speak(speechText)
            .reprompt(repromptText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const CancelAndStopIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
                || handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
    },
    handle(handlerInput) {
        const speechText = 'Goodbye!';

        return handlerInput.responseBuilder
            .speak(speechText)
            .withSimpleCard('Bin Buddy', speechText)
            .getResponse();
    }
};

const SessionEndedRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
    },
    handle(handlerInput) {
        //any cleanup logic goes here
        return handlerInput.responseBuilder.getResponse();
    }
};

exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(LaunchRequestHandler,
        GetItemIntentHandler,
        HelpIntentHandler,
        CancelAndStopIntentHandler,
        SessionEndedRequestHandler)
    .lambda();<|endoftext|>