<commit_before>/**
 * @license Angulartics
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * License: MIT
 */
(function(angular, analytics) {
'use strict';

var angulartics = window.angulartics || (window.angulartics = {});
angulartics.waitForVendorCount = 0;
angulartics.waitForVendorApi = function (objectName, delay, containsField, registerFn, onTimeout) {
  if (!onTimeout) { angulartics.waitForVendorCount++; }
  if (!registerFn) { registerFn = containsField; containsField = undefined; }
  if (!Object.prototype.hasOwnProperty.call(window, objectName) || (containsField !== undefined && window[objectName][containsField] === undefined)) {
    setTimeout(function () { angulartics.waitForVendorApi(objectName, delay, containsField, registerFn, true); }, delay);
  }
  else {
    angulartics.waitForVendorCount--;
    registerFn(window[objectName]);
  }
};

/**
 * @ngdoc overview
 * @name angulartics
 */
angular.module('angulartics', [])
.provider('$analytics', $analytics)
.run(['$rootScope', '$window', '$analytics', '$injector', $analyticsRun])
.directive('analyticsOn', ['$analytics', analyticsOn])
.config(['$provide', exceptionTrack]);

function $analytics() {
  var settings = {
    pageTracking: {
      autoTrackFirstPage: true,
      autoTrackVirtualPages: true,
      trackRelativePath: false,
      autoBasePath: false,
      basePath: '',
      excludedRoutes: []
    },
    eventTracking: {},
    bufferFlushDelay: 1000, // Support only one configuration for buffer flush delay to simplify buffering
    trackExceptions: false,
    developerMode: false // Prevent sending data in local/development environment
  };

  // List of known handlers that plugins can register themselves for
  var knownHandlers = [
    'pageTrack',
    'eventTrack',
    'exceptionTrack',
    'transactionTrack',
    'setAlias',
    'setUsername',
    'setUserProperties',
    'setUserPropertiesOnce',
    'setSuperProperties',
    'setSuperPropertiesOnce',
    'incrementProperty',
    'userTimings'
  ];
  // Cache and handler properties will match values in 'knownHandlers' as the buffering functons are installed.
  var cache = {};
  var handlers = {};
  var handlerOptions = {};

  // General buffering handler
  function bufferedHandler(handlerName){
    return function(){
      if(angulartics.waitForVendorCount){
        if(!cache[handlerName]){ cache[handlerName] = []; }
        cache[handlerName].push(arguments);
      }
    };
  }

  // As handlers are installed by plugins, they get pushed into a list and invoked in order.
  function updateHandlers(handlerName, fn, options){
    if(!handlers[handlerName]){
      handlers[handlerName] = [];
    }
    handlers[handlerName].push(fn);
    handlerOptions[fn] = options;
    return function(){
      var handlerArgs = Array.prototype.slice.apply(arguments);
      return this.$inject(['$q', angular.bind(this, function($q) {
        return $q.all(handlers[handlerName].map(function(handlerFn) {
          var options = handlerOptions[handlerFn] || {};
          if (options.async) {
            var deferred = $q.defer();
            var currentArgs = angular.copy(handlerArgs);
            currentArgs.unshift(deferred.resolve);
            handlerFn.apply(this, currentArgs);
            return deferred.promise;
          } else{
            return $q.when(handlerFn.apply(this, handlerArgs));
          }
        }, this));
      })]);
    };
  }

  // The api (returned by this provider) gets populated with handlers below.
  var api = {
    settings: settings
  };

  // Will run setTimeout if delay is > 0
  // Runs immediately if no delay to make sure cache/buffer is flushed before anything else.
  // Plugins should take care to register handlers by order of precedence.
  function onTimeout(fn, delay){
    if(delay){
      setTimeout(fn, delay);
    } else {
      fn();
    }
  }

  var provider = {
    $get: ['$injector', function($injector) {
      return apiWithInjector($injector);
    }],
    api: api,
    settings: settings,
    virtualPageviews: function (value) { this.settings.pageTracking.autoTrackVirtualPages = value; },
    excludeRoutes: function(routes) { this.settings.pageTracking.excludedRoutes = routes; },
    firstPageview: function (value) { this.settings.pageTracking.autoTrackFirstPage = value; },
    withBase: function (value) {
      this.settings.pageTracking.basePath = (value) ? angular.element(document).find('base').attr('href') : '';
    },
    withAutoBase: function (value) { this.settings.pageTracking.autoBasePath = value; },
    trackExceptions: function (value) { this.settings.trackExceptions = value; },
    developerMode: function(value) { this.settings.developerMode = value; }
  };

  // General function to register plugin handlers. Flushes buffers immediately upon registration according to the specified delay.
  function register(handlerName, fn, options){
    // Do not add a handler if developerMode is true
    if (settings.developerMode) {
        return;
    }
    api[handlerName] = updateHandlers(handlerName, fn, options);
    var handlerSettings = settings[handlerName];
    var handlerDelay = (handlerSettings) ? handlerSettings.bufferFlushDelay : null;
    var delay = (handlerDelay !== null) ? handlerDelay : settings.bufferFlushDelay;
    angular.forEach(cache[handlerName], function (args, index) {
      onTimeout(function () { fn.apply(this, args); }, index * delay);
    });
  }

  function capitalize(input) {
      return input.replace(/^./, function (match) {
          return match.toUpperCase();
      });
  }

  //provide a method to inject services into handlers
  var apiWithInjector = function(injector) {
    return angular.extend(api, {
      '$inject': injector.invoke
    });
  };

  // Adds to the provider a 'register#{handlerName}' function that manages multiple plugins and buffer flushing.
  function installHandlerRegisterFunction(handlerName){
    var registerName = 'register'+capitalize(handlerName);
    provider[registerName] = function(fn, options){
      register(handlerName, fn, options);
    };
    api[handlerName] = updateHandlers(handlerName, bufferedHandler(handlerName));
  }

  // Set up register functions for each known handler
  angular.forEach(knownHandlers, installHandlerRegisterFunction);
  for (var key in provider) {
    this[key] = provider[key];
  }
}

function $analyticsRun($rootScope, $window, $analytics, $injector) {
  function matchesExcludedRoute(url) {
    for (var i = 0; i < $analytics.settings.pageTracking.excludedRoutes.length; i++) {
      var excludedRoute = $analytics.settings.pageTracking.excludedRoutes[i];
      if ((excludedRoute instanceof RegExp && excludedRoute.test(url)) || url.indexOf(excludedRoute) > -1) {
        return true;
      }
    }
    return false;
  }

  function pageTrack(url, $location) {
    if (!matchesExcludedRoute(url)) {
      $analytics.pageTrack(url, $location);
    }
  }

  if ($analytics.settings.pageTracking.autoTrackFirstPage) {
    $injector.invoke(['$location', function ($location) {
      /* Only track the 'first page' if there are no routes or states on the page */
      var noRoutesOrStates = true;
      if ($injector.has('$route')) {
         var $route = $injector.get('$route');
         if ($route) {
          for (var route in $route.routes) {
            noRoutesOrStates = false;
            break;
          }
         } else if ($route === null){
          noRoutesOrStates = false;
         }
      } else if ($injector.has('$state')) {
        var $state = $injector.get('$state');
        for (var state in $state.get()) {
          noRoutesOrStates = false;
          break;
        }
      }
      if (noRoutesOrStates) {
        if ($analytics.settings.pageTracking.autoBasePath) {
          $analytics.settings.pageTracking.basePath = $window.location.pathname;
        }
        if ($analytics.settings.pageTracking.trackRelativePath) {
          var url = $analytics.settings.pageTracking.basePath + $location.url();
          pageTrack(url, $location);
        } else {
          pageTrack($location.absUrl(), $location);
        }
      }
    }]);
  }

  if ($analytics.settings.pageTracking.autoTrackVirtualPages) {
    $injector.invoke(['$location', function ($location) {
      if ($analytics.settings.pageTracking.autoBasePath) {
        /* Add the full route to the base. */
        $analytics.settings.pageTracking.basePath = $window.location.pathname + "#";
      }
      var noRoutesOrStates = true;
      if ($injector.has('$route')) {
        var $route = $injector.get('$route');
        if ($route) {
          for (var route in $route.routes) {
            noRoutesOrStates = false;
            break;
          }
        } else if ($route === null){
          noRoutesOrStates = false;
        }
        $rootScope.$on('$routeChangeSuccess', function (event, current) {
          if (current && (current.$$route||current).redirectTo) return;
          var url = $analytics.settings.pageTracking.basePath + $location.url();
          pageTrack(url, $location);
        });
      }
      if ($injector.has('$state') && !$injector.has('$transitions')) {
        noRoutesOrStates = false;
        $rootScope.$on('$stateChangeSuccess', function (event, current) {
          var url = $analytics.settings.pageTracking.basePath + $location.url();
          pageTrack(url, $location);
        });
      }
      if ($injector.has('$state') && $injector.has('$transitions')) {
        noRoutesOrStates = false;
        $injector.invoke(['$transitions', function($transitions) {
          $transitions.onSuccess({}, ['$transition$', function($transition$) {
            var transitionOptions = $transition$.options();

            // only track for transitions that would have triggered $stateChangeSuccess
            if (transitionOptions.notify) {
              var url = $analytics.settings.pageTracking.basePath + $location.url();
              pageTrack(url, $location);
            }
          }]);
        }]);
      }
      if (noRoutesOrStates) {
        $rootScope.$on('$locationChangeSuccess', function (event, current) {
          if (current && (current.$$route || current).redirectTo) return;
          if ($analytics.settings.pageTracking.trackRelativePath) {
            var url = $analytics.settings.pageTracking.basePath + $location.url();
            pageTrack(url, $location);
          } else {
            pageTrack($location.absUrl(), $location);
          }
        });
      }
    }]);
  }
  if ($analytics.settings.developerMode) {
    angular.forEach($analytics, function(attr, name) {
      if (typeof attr === 'function') {
        $analytics[name] = function(){};
      }
    });
  }
}

function analyticsOn($analytics) {
  return {
    restrict: 'A',
    link: function ($scope, $element, $attrs) {
      var eventType = $attrs.analyticsOn || 'click';
      var trackingData = {};

      angular.forEach($attrs.$attr, function(attr, name) {
        if (isProperty(name)) {
          trackingData[propertyName(name)] = $attrs[name];
          $attrs.$observe(name, function(value){
            trackingData[propertyName(name)] = value;
          });
        }
      });

      angular.element($element[0]).bind(eventType, function ($event) {
        var eventName = $attrs.analyticsEvent || inferEventName($element[0]);
        trackingData.eventType = $event.type;

        if($attrs.analyticsIf){
          if(! $scope.$eval($attrs.analyticsIf)){
            return; // Cancel this event if we don't pass the analytics-if condition
          }
        }
        // Allow components to pass through an expression that gets merged on to the event properties
        // eg. analytics-properites='myComponentScope.someConfigExpression.$analyticsProperties'
        if($attrs.analyticsProperties){
          angular.extend(trackingData, $scope.$eval($attrs.analyticsProperties));
        }
        $analytics.eventTrack(eventName, trackingData);
      });
    }
  };
}

function exceptionTrack($provide) {
  $provide.decorator('$exceptionHandler', ['$delegate', '$injector', function ($delegate, $injector) {
    return function (error, cause) {
      var result = $delegate(error, cause);
      var $analytics = $injector.get('$analytics');
      if ($analytics.settings.trackExceptions) {
        $analytics.exceptionTrack(error, cause);
      }
      return result;
    };
  }]);
}

function isCommand(element) {
  return ['a:','button:','button:button','button:submit','input:button','input:submit'].indexOf(
    element.tagName.toLowerCase()+':'+(element.type||'')) >= 0;
}

function inferEventType(element) {
  if (isCommand(element)) return 'click';
  return 'click';
}

function inferEventName(element) {
  if (isCommand(element)) return element.innerText || element.value;
  return element.id || element.name || element.tagName;
}

function isProperty(name) {
  return name.substr(0, 9) === 'analytics' && ['On', 'Event', 'If', 'Properties', 'EventType'].indexOf(name.substr(9)) === -1;
}

function propertyName(name) {
  var s = name.slice(9); // slice off the 'analytics' prefix
  if (typeof s !== 'undefined' && s!==null && s.length > 0) {
    return s.substring(0, 1).toLowerCase() + s.substring(1);
  }
  else {
    return s;
  }
}
})(angular);
<commit_msg>Remove inline injector annotations from onSuccess hook, since hooks no longer receive injected parameters.<commit_after>/**
 * @license Angulartics
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * License: MIT
 */
(function(angular, analytics) {
'use strict';

var angulartics = window.angulartics || (window.angulartics = {});
angulartics.waitForVendorCount = 0;
angulartics.waitForVendorApi = function (objectName, delay, containsField, registerFn, onTimeout) {
  if (!onTimeout) { angulartics.waitForVendorCount++; }
  if (!registerFn) { registerFn = containsField; containsField = undefined; }
  if (!Object.prototype.hasOwnProperty.call(window, objectName) || (containsField !== undefined && window[objectName][containsField] === undefined)) {
    setTimeout(function () { angulartics.waitForVendorApi(objectName, delay, containsField, registerFn, true); }, delay);
  }
  else {
    angulartics.waitForVendorCount--;
    registerFn(window[objectName]);
  }
};

/**
 * @ngdoc overview
 * @name angulartics
 */
angular.module('angulartics', [])
.provider('$analytics', $analytics)
.run(['$rootScope', '$window', '$analytics', '$injector', $analyticsRun])
.directive('analyticsOn', ['$analytics', analyticsOn])
.config(['$provide', exceptionTrack]);

function $analytics() {
  var settings = {
    pageTracking: {
      autoTrackFirstPage: true,
      autoTrackVirtualPages: true,
      trackRelativePath: false,
      autoBasePath: false,
      basePath: '',
      excludedRoutes: []
    },
    eventTracking: {},
    bufferFlushDelay: 1000, // Support only one configuration for buffer flush delay to simplify buffering
    trackExceptions: false,
    developerMode: false // Prevent sending data in local/development environment
  };

  // List of known handlers that plugins can register themselves for
  var knownHandlers = [
    'pageTrack',
    'eventTrack',
    'exceptionTrack',
    'transactionTrack',
    'setAlias',
    'setUsername',
    'setUserProperties',
    'setUserPropertiesOnce',
    'setSuperProperties',
    'setSuperPropertiesOnce',
    'incrementProperty',
    'userTimings'
  ];
  // Cache and handler properties will match values in 'knownHandlers' as the buffering functons are installed.
  var cache = {};
  var handlers = {};
  var handlerOptions = {};

  // General buffering handler
  function bufferedHandler(handlerName){
    return function(){
      if(angulartics.waitForVendorCount){
        if(!cache[handlerName]){ cache[handlerName] = []; }
        cache[handlerName].push(arguments);
      }
    };
  }

  // As handlers are installed by plugins, they get pushed into a list and invoked in order.
  function updateHandlers(handlerName, fn, options){
    if(!handlers[handlerName]){
      handlers[handlerName] = [];
    }
    handlers[handlerName].push(fn);
    handlerOptions[fn] = options;
    return function(){
      var handlerArgs = Array.prototype.slice.apply(arguments);
      return this.$inject(['$q', angular.bind(this, function($q) {
        return $q.all(handlers[handlerName].map(function(handlerFn) {
          var options = handlerOptions[handlerFn] || {};
          if (options.async) {
            var deferred = $q.defer();
            var currentArgs = angular.copy(handlerArgs);
            currentArgs.unshift(deferred.resolve);
            handlerFn.apply(this, currentArgs);
            return deferred.promise;
          } else{
            return $q.when(handlerFn.apply(this, handlerArgs));
          }
        }, this));
      })]);
    };
  }

  // The api (returned by this provider) gets populated with handlers below.
  var api = {
    settings: settings
  };

  // Will run setTimeout if delay is > 0
  // Runs immediately if no delay to make sure cache/buffer is flushed before anything else.
  // Plugins should take care to register handlers by order of precedence.
  function onTimeout(fn, delay){
    if(delay){
      setTimeout(fn, delay);
    } else {
      fn();
    }
  }

  var provider = {
    $get: ['$injector', function($injector) {
      return apiWithInjector($injector);
    }],
    api: api,
    settings: settings,
    virtualPageviews: function (value) { this.settings.pageTracking.autoTrackVirtualPages = value; },
    excludeRoutes: function(routes) { this.settings.pageTracking.excludedRoutes = routes; },
    firstPageview: function (value) { this.settings.pageTracking.autoTrackFirstPage = value; },
    withBase: function (value) {
      this.settings.pageTracking.basePath = (value) ? angular.element(document).find('base').attr('href') : '';
    },
    withAutoBase: function (value) { this.settings.pageTracking.autoBasePath = value; },
    trackExceptions: function (value) { this.settings.trackExceptions = value; },
    developerMode: function(value) { this.settings.developerMode = value; }
  };

  // General function to register plugin handlers. Flushes buffers immediately upon registration according to the specified delay.
  function register(handlerName, fn, options){
    // Do not add a handler if developerMode is true
    if (settings.developerMode) {
        return;
    }
    api[handlerName] = updateHandlers(handlerName, fn, options);
    var handlerSettings = settings[handlerName];
    var handlerDelay = (handlerSettings) ? handlerSettings.bufferFlushDelay : null;
    var delay = (handlerDelay !== null) ? handlerDelay : settings.bufferFlushDelay;
    angular.forEach(cache[handlerName], function (args, index) {
      onTimeout(function () { fn.apply(this, args); }, index * delay);
    });
  }

  function capitalize(input) {
      return input.replace(/^./, function (match) {
          return match.toUpperCase();
      });
  }

  //provide a method to inject services into handlers
  var apiWithInjector = function(injector) {
    return angular.extend(api, {
      '$inject': injector.invoke
    });
  };

  // Adds to the provider a 'register#{handlerName}' function that manages multiple plugins and buffer flushing.
  function installHandlerRegisterFunction(handlerName){
    var registerName = 'register'+capitalize(handlerName);
    provider[registerName] = function(fn, options){
      register(handlerName, fn, options);
    };
    api[handlerName] = updateHandlers(handlerName, bufferedHandler(handlerName));
  }

  // Set up register functions for each known handler
  angular.forEach(knownHandlers, installHandlerRegisterFunction);
  for (var key in provider) {
    this[key] = provider[key];
  }
}

function $analyticsRun($rootScope, $window, $analytics, $injector) {
  function matchesExcludedRoute(url) {
    for (var i = 0; i < $analytics.settings.pageTracking.excludedRoutes.length; i++) {
      var excludedRoute = $analytics.settings.pageTracking.excludedRoutes[i];
      if ((excludedRoute instanceof RegExp && excludedRoute.test(url)) || url.indexOf(excludedRoute) > -1) {
        return true;
      }
    }
    return false;
  }

  function pageTrack(url, $location) {
    if (!matchesExcludedRoute(url)) {
      $analytics.pageTrack(url, $location);
    }
  }

  if ($analytics.settings.pageTracking.autoTrackFirstPage) {
    $injector.invoke(['$location', function ($location) {
      /* Only track the 'first page' if there are no routes or states on the page */
      var noRoutesOrStates = true;
      if ($injector.has('$route')) {
         var $route = $injector.get('$route');
         if ($route) {
          for (var route in $route.routes) {
            noRoutesOrStates = false;
            break;
          }
         } else if ($route === null){
          noRoutesOrStates = false;
         }
      } else if ($injector.has('$state')) {
        var $state = $injector.get('$state');
        for (var state in $state.get()) {
          noRoutesOrStates = false;
          break;
        }
      }
      if (noRoutesOrStates) {
        if ($analytics.settings.pageTracking.autoBasePath) {
          $analytics.settings.pageTracking.basePath = $window.location.pathname;
        }
        if ($analytics.settings.pageTracking.trackRelativePath) {
          var url = $analytics.settings.pageTracking.basePath + $location.url();
          pageTrack(url, $location);
        } else {
          pageTrack($location.absUrl(), $location);
        }
      }
    }]);
  }

  if ($analytics.settings.pageTracking.autoTrackVirtualPages) {
    $injector.invoke(['$location', function ($location) {
      if ($analytics.settings.pageTracking.autoBasePath) {
        /* Add the full route to the base. */
        $analytics.settings.pageTracking.basePath = $window.location.pathname + "#";
      }
      var noRoutesOrStates = true;
      if ($injector.has('$route')) {
        var $route = $injector.get('$route');
        if ($route) {
          for (var route in $route.routes) {
            noRoutesOrStates = false;
            break;
          }
        } else if ($route === null){
          noRoutesOrStates = false;
        }
        $rootScope.$on('$routeChangeSuccess', function (event, current) {
          if (current && (current.$$route||current).redirectTo) return;
          var url = $analytics.settings.pageTracking.basePath + $location.url();
          pageTrack(url, $location);
        });
      }
      if ($injector.has('$state') && !$injector.has('$transitions')) {
        noRoutesOrStates = false;
        $rootScope.$on('$stateChangeSuccess', function (event, current) {
          var url = $analytics.settings.pageTracking.basePath + $location.url();
          pageTrack(url, $location);
        });
      }
      if ($injector.has('$state') && $injector.has('$transitions')) {
        noRoutesOrStates = false;
        $injector.invoke(['$transitions', function($transitions) {
          $transitions.onSuccess({}, function($transition$) {
            var transitionOptions = $transition$.options();

            // only track for transitions that would have triggered $stateChangeSuccess
            if (transitionOptions.notify) {
              var url = $analytics.settings.pageTracking.basePath + $location.url();
              pageTrack(url, $location);
            }
          });
        }]);
      }
      if (noRoutesOrStates) {
        $rootScope.$on('$locationChangeSuccess', function (event, current) {
          if (current && (current.$$route || current).redirectTo) return;
          if ($analytics.settings.pageTracking.trackRelativePath) {
            var url = $analytics.settings.pageTracking.basePath + $location.url();
            pageTrack(url, $location);
          } else {
            pageTrack($location.absUrl(), $location);
          }
        });
      }
    }]);
  }
  if ($analytics.settings.developerMode) {
    angular.forEach($analytics, function(attr, name) {
      if (typeof attr === 'function') {
        $analytics[name] = function(){};
      }
    });
  }
}

function analyticsOn($analytics) {
  return {
    restrict: 'A',
    link: function ($scope, $element, $attrs) {
      var eventType = $attrs.analyticsOn || 'click';
      var trackingData = {};

      angular.forEach($attrs.$attr, function(attr, name) {
        if (isProperty(name)) {
          trackingData[propertyName(name)] = $attrs[name];
          $attrs.$observe(name, function(value){
            trackingData[propertyName(name)] = value;
          });
        }
      });

      angular.element($element[0]).bind(eventType, function ($event) {
        var eventName = $attrs.analyticsEvent || inferEventName($element[0]);
        trackingData.eventType = $event.type;

        if($attrs.analyticsIf){
          if(! $scope.$eval($attrs.analyticsIf)){
            return; // Cancel this event if we don't pass the analytics-if condition
          }
        }
        // Allow components to pass through an expression that gets merged on to the event properties
        // eg. analytics-properites='myComponentScope.someConfigExpression.$analyticsProperties'
        if($attrs.analyticsProperties){
          angular.extend(trackingData, $scope.$eval($attrs.analyticsProperties));
        }
        $analytics.eventTrack(eventName, trackingData);
      });
    }
  };
}

function exceptionTrack($provide) {
  $provide.decorator('$exceptionHandler', ['$delegate', '$injector', function ($delegate, $injector) {
    return function (error, cause) {
      var result = $delegate(error, cause);
      var $analytics = $injector.get('$analytics');
      if ($analytics.settings.trackExceptions) {
        $analytics.exceptionTrack(error, cause);
      }
      return result;
    };
  }]);
}

function isCommand(element) {
  return ['a:','button:','button:button','button:submit','input:button','input:submit'].indexOf(
    element.tagName.toLowerCase()+':'+(element.type||'')) >= 0;
}

function inferEventType(element) {
  if (isCommand(element)) return 'click';
  return 'click';
}

function inferEventName(element) {
  if (isCommand(element)) return element.innerText || element.value;
  return element.id || element.name || element.tagName;
}

function isProperty(name) {
  return name.substr(0, 9) === 'analytics' && ['On', 'Event', 'If', 'Properties', 'EventType'].indexOf(name.substr(9)) === -1;
}

function propertyName(name) {
  var s = name.slice(9); // slice off the 'analytics' prefix
  if (typeof s !== 'undefined' && s!==null && s.length > 0) {
    return s.substring(0, 1).toLowerCase() + s.substring(1);
  }
  else {
    return s;
  }
}
})(angular);
<|endoftext|>


<commit_before>/**
 * @license Angulartics v0.17.0
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * License: MIT
 */
(function(angular, analytics) {
'use strict';

var angulartics = window.angulartics || (window.angulartics = {});
angulartics.waitForVendorCount = 0;
angulartics.waitForVendorApi = function (objectName, delay, containsField, registerFn, onTimeout) {
  if (!onTimeout) { angulartics.waitForVendorCount++; }
  if (!registerFn) { registerFn = containsField; containsField = undefined; }
  if (!Object.prototype.hasOwnProperty.call(window, objectName) || (containsField !== undefined && window[objectName][containsField] === undefined)) {
    setTimeout(function () { angulartics.waitForVendorApi(objectName, delay, containsField, registerFn, true); }, delay);
  }
  else {
    angulartics.waitForVendorCount--;
    registerFn(window[objectName]);
  }
};

/**
 * @ngdoc overview
 * @name angulartics
 */
angular.module('angulartics', [])
.provider('$analytics', function () {
  var settings = {
    pageTracking: {
      autoTrackFirstPage: true,
      autoTrackVirtualPages: true,
      trackRelativePath: false,
      autoBasePath: false,
      basePath: ''
    },
    eventTracking: {},
    bufferFlushDelay: 1000 // Support only one configuration for buffer flush delay to simplify buffering
  };

  // List of known handlers that plugins can register themselves for
  var knownHandlers = [
    'pageTrack',
    'eventTrack',
    'setUsername',
    'setAlias',
    'setUserProperties',
    'setUserPropertiesOnce',
    'setSuperProperties',
    'setSuperPropertiesOnce'
  ];
  // Cache and handler properties will match values in 'knownHandlers' as the buffering functons are installed.
  var cache = {};
  var handlers = {};

  // General buffering handler
  var bufferedHandler = function(handlerName){
    return function(){
      if(angulartics.waitForVendorCount){
        if(!cache[handlerName]){ cache[handlerName] = []; }
        cache[handlerName].push(arguments);
      }
    };
  };

  // As handlers are installed by plugins, they get pushed into a list and invoked in order.
  var updateHandlers = function(handlerName, fn){
    if(!handlers[handlerName]){
      handlers[handlerName] = [];
    }
    handlers[handlerName].push(fn);
    return function(){
      var handlerArgs = arguments;
      angular.forEach(handlers[handlerName], function(handler){
        handler.apply(this, handlerArgs);
      }, this);
    };
  };

  // The api (returned by this provider) gets populated with handlers below.
  var api = {
    settings: settings
  };

  // Will run setTimeout if delay is > 0
  // Runs immediately if no delay to make sure cache/buffer is flushed before anything else.
  // Plugins should take care to register handlers by order of precedence.
  var onTimeout = function(fn, delay){
    if(delay){
      setTimeout(fn, delay);
    } else {
      fn();
    }
  };

  var provider = {
    $get: function() { return api; },
    api: api,
    settings: settings,
    virtualPageviews: function (value) { this.settings.pageTracking.autoTrackVirtualPages = value; },
    firstPageview: function (value) { this.settings.pageTracking.autoTrackFirstPage = value; },
    withBase: function (value) { this.settings.pageTracking.basePath = (value) ? angular.element('base').attr('href').slice(0, -1) : ''; },
    withAutoBase: function (value) { this.settings.pageTracking.autoBasePath = value; },
  };

  // General function to register plugin handlers. Flushes buffers immediately upon registration according to the specified delay.
  var register = function(handlerName, fn){
    api[handlerName] = updateHandlers(handlerName, fn);
    var handlerSettings = settings[handlerName];
    var handlerDelay = (handlerSettings) ? handlerSettings.bufferFlushDelay : null;
    var delay = (handlerDelay !== null) ? handlerDelay : settings.bufferFlushDelay;
    angular.forEach(cache[handlerName], function (args, index) {
      onTimeout(function () { fn.apply(this, args); }, index * delay);
    });
  };

  var capitalize = function (input) {
      return input.replace(/^./, function (match) {
          return match.toUpperCase();
      });
  };

  // Adds to the provider a 'register#{handlerName}' function that manages multiple plugins and buffer flushing.
  var installHandlerRegisterFunction = function(handlerName){
    var registerName = 'register'+capitalize(handlerName);
    provider[registerName] = function(fn){
      register(handlerName, fn);
    };
    api[handlerName] = updateHandlers(handlerName, bufferedHandler(handlerName));
  };

  // Set up register functions for each known handler
  angular.forEach(knownHandlers, installHandlerRegisterFunction);
  return provider;
})

.run(['$rootScope', '$location', '$window', '$analytics', '$injector', function ($rootScope, $location, $window, $analytics, $injector) {

  if ($analytics.settings.pageTracking.autoTrackFirstPage) {
    /* Only track the 'first page' if there are no routes or states on the page */
    var noRoutesOrStates = true;
    if ($injector.has('$route')) {
       var $route = $injector.get('$route');
       for (var route in $route.routes) {
         noRoutesOrStates = false;
         break;
       }
    } else if ($injector.has('$state')) {
      var $state = $injector.get('$state');
      for (var state in $state.get()) {
        noRoutesOrStates = false;
        break;
      }
    }
    if (noRoutesOrStates) {
      if ($analytics.settings.pageTracking.autoBasePath) {
        $analytics.settings.pageTracking.basePath = $window.location.pathname;
      }
      if ($analytics.settings.trackRelativePath) {
        var url = $analytics.settings.pageTracking.basePath + $location.url();
        $analytics.pageTrack(url);
      } else {
        $analytics.pageTrack($location.absUrl());
      }
    }
  }
  if ($analytics.settings.pageTracking.autoTrackVirtualPages) {
    if ($analytics.settings.pageTracking.autoBasePath) {
      /* Add the full route to the base. */
      $analytics.settings.pageTracking.basePath = $window.location.pathname + "#";
    }
    if ($injector.has('$route')) {
      $rootScope.$on('$routeChangeSuccess', function (event, current) {
        if (current && (current.$$route||current).redirectTo) return;
        var url = $analytics.settings.pageTracking.basePath + $location.url();
        $analytics.pageTrack(url);
      });
    }
    if ($injector.has('$state')) {
      $rootScope.$on('$stateChangeSuccess', function (event, current) {
        var url = $analytics.settings.pageTracking.basePath + $location.url();
        $analytics.pageTrack(url);
      });
    }
  }
}])

.directive('analyticsOn', ['$analytics', function ($analytics) {
  function isCommand(element) {
    return ['a:','button:','button:button','button:submit','input:button','input:submit'].indexOf(
      element.tagName.toLowerCase()+':'+(element.type||'')) >= 0;
  }

  function inferEventType(element) {
    if (isCommand(element)) return 'click';
    return 'click';
  }

  function inferEventName(element) {
    if (isCommand(element)) return element.innerText || element.value;
    return element.id || element.name || element.tagName;
  }

  function isProperty(name) {
    return name.substr(0, 9) === 'analytics' && ['On', 'Event', 'If', 'Properties', 'EventType'].indexOf(name.substr(9)) === -1;
  }

  function propertyName(name) {
    var s = name.slice(9); // slice off the 'analytics' prefix
    if (typeof s !== 'undefined' && s!==null && s.length > 0) {
      return s.substring(0, 1).toLowerCase() + s.substring(1);
    }
    else {
      return s;
    }
  }

  return {
    restrict: 'A',
    scope: true,
    link: function ($scope, $element, $attrs) {
      var eventType = $attrs.analyticsOn || inferEventType($element[0]);

      $scope.$analytics = {};

      angular.forEach($attrs.$attr, function(attr, name) {
        if (isProperty(name)) {
          $scope.$analytics[propertyName(name)] = $attrs[name];
          $attrs.$observe(name, function(value){
            $scope.$analytics[propertyName(name)] = value;
          });
        }
      });

      angular.element($element[0]).bind(eventType, function ($event) {
        var eventName = $attrs.analyticsEvent || inferEventName($element[0]);
        var properties = {};
        $scope.$analytics.eventType = $event.type;

        if($attrs.analyticsIf){
          if(! $scope.$eval($attrs.analyticsIf)){
            return; // Cancel this event if we don't pass the analytics-if condition
          }
        }
        // Allow components to pass through an expression that gets merged on to the event properties
        // eg. analytics-properites='myComponentScope.someConfigExpression.$analyticsProperties'
        if($attrs.analyticsProperties){
          angular.extend($scope.$analytics, $scope.$eval($attrs.analyticsProperties));
        }
        $analytics.eventTrack(eventName, $scope.$analytics);
      });
    }
  };
}]);
})(angular);
<commit_msg>New developer mode to prevent sending data<commit_after>/**
 * @license Angulartics v0.17.0
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * License: MIT
 */
(function(angular, analytics) {
'use strict';

var angulartics = window.angulartics || (window.angulartics = {});
angulartics.waitForVendorCount = 0;
angulartics.waitForVendorApi = function (objectName, delay, containsField, registerFn, onTimeout) {
  if (!onTimeout) { angulartics.waitForVendorCount++; }
  if (!registerFn) { registerFn = containsField; containsField = undefined; }
  if (!Object.prototype.hasOwnProperty.call(window, objectName) || (containsField !== undefined && window[objectName][containsField] === undefined)) {
    setTimeout(function () { angulartics.waitForVendorApi(objectName, delay, containsField, registerFn, true); }, delay);
  }
  else {
    angulartics.waitForVendorCount--;
    registerFn(window[objectName]);
  }
};

/**
 * @ngdoc overview
 * @name angulartics
 */
angular.module('angulartics', [])
.provider('$analytics', function () {
  var settings = {
    pageTracking: {
      autoTrackFirstPage: true,
      autoTrackVirtualPages: true,
      trackRelativePath: false,
      autoBasePath: false,
      basePath: ''
    },
    eventTracking: {},
    bufferFlushDelay: 1000, // Support only one configuration for buffer flush delay to simplify buffering
    developerMode: false // Prevent sending data in local/development environment
  };

  // List of known handlers that plugins can register themselves for
  var knownHandlers = [
    'pageTrack',
    'eventTrack',
    'setUsername',
    'setAlias',
    'setUserProperties',
    'setUserPropertiesOnce',
    'setSuperProperties',
    'setSuperPropertiesOnce'
  ];
  // Cache and handler properties will match values in 'knownHandlers' as the buffering functons are installed.
  var cache = {};
  var handlers = {};

  // General buffering handler
  var bufferedHandler = function(handlerName){
    return function(){
      if(angulartics.waitForVendorCount){
        if(!cache[handlerName]){ cache[handlerName] = []; }
        cache[handlerName].push(arguments);
      }
    };
  };

  // As handlers are installed by plugins, they get pushed into a list and invoked in order.
  var updateHandlers = function(handlerName, fn){
    if(!handlers[handlerName]){
      handlers[handlerName] = [];
    }
    handlers[handlerName].push(fn);
    return function(){
      var handlerArgs = arguments;
      angular.forEach(handlers[handlerName], function(handler){
        handler.apply(this, handlerArgs);
      }, this);
    };
  };

  // The api (returned by this provider) gets populated with handlers below.
  var api = {
    settings: settings
  };

  // Will run setTimeout if delay is > 0
  // Runs immediately if no delay to make sure cache/buffer is flushed before anything else.
  // Plugins should take care to register handlers by order of precedence.
  var onTimeout = function(fn, delay){
    if(delay){
      setTimeout(fn, delay);
    } else {
      fn();
    }
  };

  var provider = {
    $get: function() { return api; },
    api: api,
    settings: settings,
    virtualPageviews: function (value) { this.settings.pageTracking.autoTrackVirtualPages = value; },
    firstPageview: function (value) { this.settings.pageTracking.autoTrackFirstPage = value; },
    withBase: function (value) { this.settings.pageTracking.basePath = (value) ? angular.element('base').attr('href').slice(0, -1) : ''; },
    withAutoBase: function (value) { this.settings.pageTracking.autoBasePath = value; },
    developerMode: function(value) { this.settings.developerMode = value; }
  };

  // General function to register plugin handlers. Flushes buffers immediately upon registration according to the specified delay.
  var register = function(handlerName, fn){
    api[handlerName] = updateHandlers(handlerName, fn);
    var handlerSettings = settings[handlerName];
    var handlerDelay = (handlerSettings) ? handlerSettings.bufferFlushDelay : null;
    var delay = (handlerDelay !== null) ? handlerDelay : settings.bufferFlushDelay;
    angular.forEach(cache[handlerName], function (args, index) {
      onTimeout(function () { fn.apply(this, args); }, index * delay);
    });
  };

  var capitalize = function (input) {
      return input.replace(/^./, function (match) {
          return match.toUpperCase();
      });
  };

  // Adds to the provider a 'register#{handlerName}' function that manages multiple plugins and buffer flushing.
  var installHandlerRegisterFunction = function(handlerName){
    var registerName = 'register'+capitalize(handlerName);
    provider[registerName] = function(fn){
      register(handlerName, fn);
    };
    api[handlerName] = updateHandlers(handlerName, bufferedHandler(handlerName));
  };

  // Set up register functions for each known handler
  angular.forEach(knownHandlers, installHandlerRegisterFunction);
  return provider;
})

.run(['$rootScope', '$location', '$window', '$analytics', '$injector', function ($rootScope, $location, $window, $analytics, $injector) {

  if ($analytics.settings.pageTracking.autoTrackFirstPage) {
    /* Only track the 'first page' if there are no routes or states on the page */
    var noRoutesOrStates = true;
    if ($injector.has('$route')) {
       var $route = $injector.get('$route');
       for (var route in $route.routes) {
         noRoutesOrStates = false;
         break;
       }
    } else if ($injector.has('$state')) {
      var $state = $injector.get('$state');
      for (var state in $state.get()) {
        noRoutesOrStates = false;
        break;
      }
    }
    if (noRoutesOrStates) {
      if ($analytics.settings.pageTracking.autoBasePath) {
        $analytics.settings.pageTracking.basePath = $window.location.pathname;
      }
      if ($analytics.settings.trackRelativePath) {
        var url = $analytics.settings.pageTracking.basePath + $location.url();
        $analytics.pageTrack(url);
      } else {
        $analytics.pageTrack($location.absUrl());
      }
    }
  }
  if ($analytics.settings.pageTracking.autoTrackVirtualPages) {
    if ($analytics.settings.pageTracking.autoBasePath) {
      /* Add the full route to the base. */
      $analytics.settings.pageTracking.basePath = $window.location.pathname + "#";
    }
    if ($injector.has('$route')) {
      $rootScope.$on('$routeChangeSuccess', function (event, current) {
        if (current && (current.$$route||current).redirectTo) return;
        var url = $analytics.settings.pageTracking.basePath + $location.url();
        $analytics.pageTrack(url);
      });
    }
    if ($injector.has('$state')) {
      $rootScope.$on('$stateChangeSuccess', function (event, current) {
        var url = $analytics.settings.pageTracking.basePath + $location.url();
        $analytics.pageTrack(url);
      });
    }
  }
  if ($analytics.settings.developerMode) {
    angular.forEach($analytics, function(attr, name) {
      if (typeof attr === 'function') {
        $analytics[name] = function(){};
      }
    });
  }
}])

.directive('analyticsOn', ['$analytics', function ($analytics) {
  function isCommand(element) {
    return ['a:','button:','button:button','button:submit','input:button','input:submit'].indexOf(
      element.tagName.toLowerCase()+':'+(element.type||'')) >= 0;
  }

  function inferEventType(element) {
    if (isCommand(element)) return 'click';
    return 'click';
  }

  function inferEventName(element) {
    if (isCommand(element)) return element.innerText || element.value;
    return element.id || element.name || element.tagName;
  }

  function isProperty(name) {
    return name.substr(0, 9) === 'analytics' && ['On', 'Event', 'If', 'Properties', 'EventType'].indexOf(name.substr(9)) === -1;
  }

  function propertyName(name) {
    var s = name.slice(9); // slice off the 'analytics' prefix
    if (typeof s !== 'undefined' && s!==null && s.length > 0) {
      return s.substring(0, 1).toLowerCase() + s.substring(1);
    }
    else {
      return s;
    }
  }

  return {
    restrict: 'A',
    scope: true,
    link: function ($scope, $element, $attrs) {
      var eventType = $attrs.analyticsOn || inferEventType($element[0]);

      $scope.$analytics = {};

      angular.forEach($attrs.$attr, function(attr, name) {
        if (isProperty(name)) {
          $scope.$analytics[propertyName(name)] = $attrs[name];
          $attrs.$observe(name, function(value){
            $scope.$analytics[propertyName(name)] = value;
          });
        }
      });

      angular.element($element[0]).bind(eventType, function ($event) {
        var eventName = $attrs.analyticsEvent || inferEventName($element[0]);
        var properties = {};
        $scope.$analytics.eventType = $event.type;

        if($attrs.analyticsIf){
          if(! $scope.$eval($attrs.analyticsIf)){
            return; // Cancel this event if we don't pass the analytics-if condition
          }
        }
        // Allow components to pass through an expression that gets merged on to the event properties
        // eg. analytics-properites='myComponentScope.someConfigExpression.$analyticsProperties'
        if($attrs.analyticsProperties){
          angular.extend($scope.$analytics, $scope.$eval($attrs.analyticsProperties));
        }
        $analytics.eventTrack(eventName, $scope.$analytics);
      });
    }
  };
}]);
})(angular);
<|endoftext|>


<commit_before>var authorCache = {};
var currentPublication = null;
var numberOfAuthors = 0; // number of unique authors in the cache, used to
// generate author id

function clearPublication() {
	// clear submission form first
	PublicationManager.clearPublication( function(publication) {
		dwr.util.setValues(publication);
		currentPublication = publication;
		// not sure if we need to clear status, description, samples, file, and
			// visibility
			populateAuthors(false);
		});
}

function showAuthors(publicationId) {

}
function updateSubmitFormBasedOnCategory() {
	var category = dwr.util.getValue("category");
	if (category != "report" && category != "book chapter" && category != "") {
		show("pubMedRow", true);
		show("doiRow", true);
		show("journalRow", true);
		show("volumePageRow", true);
	} else {
		hide("pubMedRow");
		hide("doiRow");
		hide("journalRow");
		hide("volumePageRow");
	}
	// if report, set publish status to published
	if (category == "report") {
		dwr.util.setValue("status", "published");
	}
}

function enableAutoFields() {
	document.getElementById("domainFile.digitalObjectId").readOnly = false;
	document.getElementById("domainFile.title").readOnly = false;
	document.getElementById("domainFile.journalName").readOnly = false;
	document.getElementById("domainFile.year").readOnly = false;
	document.getElementById("domainFile.volume").readOnly = false;
	document.getElementById("domainFile.startPage").readOnly = false;
	document.getElementById("domainFile.endPage").readOnly = false;
	show("addAuthor");
	show("fileSection");
}

function updateSearchFormBasedOnCategory() {
	var category = dwr.util.getValue("publicationCategory");
	if (category != "report" && category != "book chapter" && category != "") {
		show("pubMedRow", true);
	} else {
		hide("pubMedRow");
	}
}

function showSampleNameDropdown() {
	// display progress.gif while waiting for the response.
	show("loaderImg");
	hide("browseSampleNames");
	var selected = dwr.util.getValue("allSampleNameSelect");
	PublicationManager.getAllSampleNames( function(data) {
		dwr.util.removeAllOptions("allSampleNameSelect");
		dwr.util.addOptions("allSampleNameSelect", data);
		dwr.util.setValue("allSampleNameSelect", selected);
		hide("loaderImg");
		show("allSampleNameSelect");
	});
}

function setPublicationDropdowns() {
	var searchLocations = getSelectedOptions(document
			.getElementById("searchLocations"));
	PublicationManager.getPublicationCategories(searchLocations,
			function(data) {
				dwr.util.removeAllOptions("publicationCategories");
				dwr.util.addOptions("publicationCategories", data);
			});
	SampleManager.getNanomaterialEntityTypes(searchLocations, function(data) {
		dwr.util.removeAllOptions("nanomaterialEntityTypes");
		dwr.util.addOptions("nanomaterialEntityTypes", data);
	});
	SampleManager.getFunctionalizingEntityTypes(searchLocations,
			function(data) {
				dwr.util.removeAllOptions("functionalizingEntityTypes");
				dwr.util.addOptions("functionalizingEntityTypes", data);
			});

	SampleManager.getFunctionTypes(searchLocations, function(data) {
		dwr.util.removeAllOptions("functionTypes");
		dwr.util.addOptions("functionTypes", data);
	});
	return false;
}

function searchPubMedInfo() {
	var pubMedId = dwr.util.getValue("pubMedId");
	if (pubMedId != null && pubMedId != 0) {
		return PublicationManager.searchPubMedById(pubMedId, validatePubMedInfo);
	}
	return true;
}

function validatePubMedInfo(publication) {
	if (publication.domainFile.pubMedId == null) {
		alert("Invalid PubMed ID entered.");
		return false;
	}
	return true;
}

function fillPubMedInfo() {
	var pubMedId = dwr.util.getValue("domainFile.pubMedId");
	if (pubMedId != null && pubMedId != 0) {
		PublicationManager.retrievePubMedInfo(pubMedId, populatePubMedInfo);
	}
}

function populatePubMedInfo(publication) {
	if (publication != null) {
		currentPublication = publication;
		dwr.util.setValues(publication);
		// If PubMedId is null in returned pub -> pubMedId not found.
		if (publication.domainFile.pubMedId == null) {
			alert("Invalid PubMed ID entered.");
			populateAuthors(false);
			show("addAuthor");
			show("fileSection");
		} else {
			document.getElementById("domainFile.digitalObjectId").readOnly = true;
			document.getElementById("domainFile.title").readOnly = true;
			document.getElementById("domainFile.journalName").readOnly = true;
			document.getElementById("domainFile.year").readOnly = true;
			document.getElementById("domainFile.volume").readOnly = true;
			document.getElementById("domainFile.startPage").readOnly = true;
			document.getElementById("domainFile.endPage").readOnly = true;
			populateAuthors(true);
			hide("addAuthor");
			hide("fileSection"); //disable file upload
		}
	} else {
		sessionTimeout();
	}
}

function populateAuthors(hideEdit) {
	var authors = currentPublication.authors;
	dwr.util.removeAllRows("authorRows", {
		filter : function(tr) {
			return (tr.id != "pattern" && tr.id != "patternHeader");
		}
	});
	var author, id;
	if (authors.length > 0) {
		show("authorTable");
	} else {
		hide("authorTable");
	}
	for ( var i = 0; i < authors.length; i++) {
		author = authors[i];
		if (author.id == null || author.id == "") {
			author.id = -1000 - numberOfAuthors;
		}
		id = author.id;
		dwr.util.cloneNode("pattern", {
			idSuffix : id
		});
		dwr.util.setValue("id" + id, author.id);
		dwr.util.setValue("firstNameValue" + id, author.firstName);
		dwr.util.setValue("lastNameValue" + id, author.lastName);
		dwr.util.setValue("initialsValue" + id, author.initial);
		$("pattern" + id).style.display = "";
		if (authorCache[id] == null) {
			numberOfAuthors++;
		}
		authorCache[id] = author;
		if (hideEdit == true) {
			hide("edit" + id);
		}
	}
}

function addAuthor() {
	var author = {
		id : null,
		firstName : null,
		lastName : null,
		initial : null
	};
	dwr.util.getValues(author);
	if (author.id == null || author.id == "") {
		author.id = -1000 - numberOfAuthors;
	}

	if (author.firstName != "" || author.lastName != "" || author.initial != "") {
		PublicationManager.addAuthor(author, function(publication) {
			if (publication == null) {
				sessionTimeout();
			}
			currentPublication = publication;
		});
		window.setTimeout("populateAuthors()", 200);
	} else {
		alert("Please fill in values");
	}
}
function clearAuthor() {
	var author = {
		id : null,
		firstName : "",
		lastName : "",
		initial : ""
	};
	dwr.util.setValues(author);
	hide("deleteAuthor");
}
function editAuthor(eleid) {
	// we were an id of the form "edit{id}", eg "edit42". We lookup the "42"
	var author = authorCache[eleid.substring(4)];
	dwr.util.setValues(author);
	// document.getElementById("manufacturer").focus(); this doesn't work in IE
	show("deleteAuthor");
}
function deleteTheAuthor() {
	var eleid = document.getElementById("id").value;
	// we were an id of the form "delete{id}", eg "delete42". We lookup the "42"
	// var author = authorCache[eleid.substring(6)];
	if (eleid != "") {
		var author = authorCache[eleid];
		if (confirm("Are you sure you want to delete '" + author.firstName
				+ " " + author.lastName + "'?")) {
			PublicationManager.deleteAuthor(author, function(publication) {
				if (publication == null) {
					sessionTimeout();
				}
				currentPublication = publication;
			});
			window.setTimeout("populateAuthors()", 200);
			closeSubmissionForm("Author");
		}
	}
}
<commit_msg>updated validation of pubmed and submission of publication search.<commit_after>var authorCache = {};
var currentPublication = null;
var numberOfAuthors = 0; // number of unique authors in the cache, used to
// generate author id

function clearPublication() {
	// clear submission form first
	PublicationManager.clearPublication( function(publication) {
		dwr.util.setValues(publication);
		currentPublication = publication;
		// not sure if we need to clear status, description, samples, file, and
			// visibility
			populateAuthors(false);
		});
}

function showAuthors(publicationId) {

}
function updateSubmitFormBasedOnCategory() {
	var category = dwr.util.getValue("category");
	if (category != "report" && category != "book chapter" && category != "") {
		show("pubMedRow", true);
		show("doiRow", true);
		show("journalRow", true);
		show("volumePageRow", true);
	} else {
		hide("pubMedRow");
		hide("doiRow");
		hide("journalRow");
		hide("volumePageRow");
	}
	// if report, set publish status to published
	if (category == "report") {
		dwr.util.setValue("status", "published");
	}
}

function enableAutoFields() {
	document.getElementById("domainFile.digitalObjectId").readOnly = false;
	document.getElementById("domainFile.title").readOnly = false;
	document.getElementById("domainFile.journalName").readOnly = false;
	document.getElementById("domainFile.year").readOnly = false;
	document.getElementById("domainFile.volume").readOnly = false;
	document.getElementById("domainFile.startPage").readOnly = false;
	document.getElementById("domainFile.endPage").readOnly = false;
	show("addAuthor");
	show("fileSection");
}

function updateSearchFormBasedOnCategory() {
	var category = dwr.util.getValue("publicationCategory");
	if (category != "report" && category != "book chapter" && category != "") {
		show("pubMedRow", true);
	} else {
		hide("pubMedRow");
	}
}

function showSampleNameDropdown() {
	// display progress.gif while waiting for the response.
	show("loaderImg");
	hide("browseSampleNames");
	var selected = dwr.util.getValue("allSampleNameSelect");
	PublicationManager.getAllSampleNames( function(data) {
		dwr.util.removeAllOptions("allSampleNameSelect");
		dwr.util.addOptions("allSampleNameSelect", data);
		dwr.util.setValue("allSampleNameSelect", selected);
		hide("loaderImg");
		show("allSampleNameSelect");
	});
}

function setPublicationDropdowns() {
	var searchLocations = getSelectedOptions(document
			.getElementById("searchLocations"));
	PublicationManager.getPublicationCategories(searchLocations,
			function(data) {
				dwr.util.removeAllOptions("publicationCategories");
				dwr.util.addOptions("publicationCategories", data);
			});
	SampleManager.getNanomaterialEntityTypes(searchLocations, function(data) {
		dwr.util.removeAllOptions("nanomaterialEntityTypes");
		dwr.util.addOptions("nanomaterialEntityTypes", data);
	});
	SampleManager.getFunctionalizingEntityTypes(searchLocations,
			function(data) {
				dwr.util.removeAllOptions("functionalizingEntityTypes");
				dwr.util.addOptions("functionalizingEntityTypes", data);
			});

	SampleManager.getFunctionTypes(searchLocations, function(data) {
		dwr.util.removeAllOptions("functionTypes");
		dwr.util.addOptions("functionTypes", data);
	});
	return false;
}

function searchPublication() {
	var pubMedId = dwr.util.getValue("pubMedId");
	if (pubMedId != null && pubMedId != 0) {
	   PublicationManager.searchPubMedById(pubMedId, validatePubMedInfo);
	}
}

function validatePubMedInfo(publication) {
	if (publication.domainFile.pubMedId == null) {
		alert("Invalid PubMed ID entered.");
	}
	else {
		submitAction(document.forms[0], "searchPublication", "search", 1);
	}
}

function fillPubMedInfo() {
	var pubMedId = dwr.util.getValue("domainFile.pubMedId");
	if (pubMedId != null && pubMedId != 0) {
		PublicationManager.retrievePubMedInfo(pubMedId, populatePubMedInfo);
	}
}

function populatePubMedInfo(publication) {
	if (publication != null) {
		currentPublication = publication;
		dwr.util.setValues(publication);
		// If PubMedId is null in returned pub -> pubMedId not found.
		if (publication.domainFile.pubMedId == null) {
			alert("Invalid PubMed ID entered.");
			populateAuthors(false);
			show("addAuthor");
			show("fileSection");
		} else {
			document.getElementById("domainFile.digitalObjectId").readOnly = true;
			document.getElementById("domainFile.title").readOnly = true;
			document.getElementById("domainFile.journalName").readOnly = true;
			document.getElementById("domainFile.year").readOnly = true;
			document.getElementById("domainFile.volume").readOnly = true;
			document.getElementById("domainFile.startPage").readOnly = true;
			document.getElementById("domainFile.endPage").readOnly = true;
			populateAuthors(true);
			hide("addAuthor");
			hide("fileSection"); // disable file upload
		}
	} else {
		sessionTimeout();
	}
}

function populateAuthors(hideEdit) {
	var authors = currentPublication.authors;
	dwr.util.removeAllRows("authorRows", {
		filter : function(tr) {
			return (tr.id != "pattern" && tr.id != "patternHeader");
		}
	});
	var author, id;
	if (authors.length > 0) {
		show("authorTable");
	} else {
		hide("authorTable");
	}
	for ( var i = 0; i < authors.length; i++) {
		author = authors[i];
		if (author.id == null || author.id == "") {
			author.id = -1000 - numberOfAuthors;
		}
		id = author.id;
		dwr.util.cloneNode("pattern", {
			idSuffix : id
		});
		dwr.util.setValue("id" + id, author.id);
		dwr.util.setValue("firstNameValue" + id, author.firstName);
		dwr.util.setValue("lastNameValue" + id, author.lastName);
		dwr.util.setValue("initialsValue" + id, author.initial);
		$("pattern" + id).style.display = "";
		if (authorCache[id] == null) {
			numberOfAuthors++;
		}
		authorCache[id] = author;
		if (hideEdit == true) {
			hide("edit" + id);
		}
	}
}

function addAuthor() {
	var author = {
		id : null,
		firstName : null,
		lastName : null,
		initial : null
	};
	dwr.util.getValues(author);
	if (author.id == null || author.id == "") {
		author.id = -1000 - numberOfAuthors;
	}

	if (author.firstName != "" || author.lastName != "" || author.initial != "") {
		PublicationManager.addAuthor(author, function(publication) {
			if (publication == null) {
				sessionTimeout();
			}
			currentPublication = publication;
		});
		window.setTimeout("populateAuthors()", 200);
	} else {
		alert("Please fill in values");
	}
}
function clearAuthor() {
	var author = {
		id : null,
		firstName : "",
		lastName : "",
		initial : ""
	};
	dwr.util.setValues(author);
	hide("deleteAuthor");
}
function editAuthor(eleid) {
	// we were an id of the form "edit{id}", eg "edit42". We lookup the "42"
	var author = authorCache[eleid.substring(4)];
	dwr.util.setValues(author);
	// document.getElementById("manufacturer").focus(); this doesn't work in IE
	show("deleteAuthor");
}
function deleteTheAuthor() {
	var eleid = document.getElementById("id").value;
	// we were an id of the form "delete{id}", eg "delete42". We lookup the "42"
	// var author = authorCache[eleid.substring(6)];
	if (eleid != "") {
		var author = authorCache[eleid];
		if (confirm("Are you sure you want to delete '" + author.firstName
				+ " " + author.lastName + "'?")) {
			PublicationManager.deleteAuthor(author, function(publication) {
				if (publication == null) {
					sessionTimeout();
				}
				currentPublication = publication;
			});
			window.setTimeout("populateAuthors()", 200);
			closeSubmissionForm("Author");
		}
	}
}
<|endoftext|>


<commit_before>/*global describe, it*/

var assert = require('assert'),
	templates = require('./../../lib/templates.js'),
	data = require('./../data.json'),
	fs = require('fs'),
	path = require('path'),
	async = require('async'),
	winston = require('winston'),

	TEMPLATES_DIRECTORY = path.join(__dirname, '../templates/');

function prepare(callback) {
	var raw = {},
		expected = {};

	fs.readdir(TEMPLATES_DIRECTORY, function(err, files) {
		async.each(files, function(file, next) {
			fs.readFile(path.join(TEMPLATES_DIRECTORY, file), 'utf-8', function(err, html) {
				if (file.match(/\.html?/)) {
					expected[file.replace(/\.html?/, '')] = html;
				} else if (file.match(/\.tpl?/)) {
					raw[file.replace(/\.tpl?/, '')] = html;
				}

				next();
			});
		}, function(err) {
			if (err) {
				throw new Error(err);
			}

			for (var key in raw) {
				if (raw.hasOwnProperty(key)) {
					if (typeof expected[key] === 'undefined') {
						winston.warn('Missing expected file: ' + key + '.html');
						delete raw[key];
					}
				}
			}

			callback(raw, expected);
		});

	});
}

function test(raw, expected) {
	describe('templates.js', function() {
		var keys = Object.keys(raw);

		async.each(keys, function(key, next) {
			it(key, function() {
				assert.equal(templates.parse(raw[key], data), expected[key]);
				next();
			});
		}, function(err) {
			if (err) {
				throw new Error(err);
			}
		});
	});
}

prepare(test);<commit_msg>added some logging to tests<commit_after>/*global describe, it*/

var assert = require('assert'),
	templates = require('./../../lib/templates.js'),
	data = require('./../data.json'),
	fs = require('fs'),
	path = require('path'),
	async = require('async'),
	winston = require('winston'),

	TEMPLATES_DIRECTORY = path.join(__dirname, '../templates/');

function prepare(callback) {
	var raw = {},
		expected = {};

	fs.readdir(TEMPLATES_DIRECTORY, function(err, files) {
		async.each(files, function(file, next) {
			fs.readFile(path.join(TEMPLATES_DIRECTORY, file), 'utf-8', function(err, html) {
				if (file.match(/\.html?/)) {
					expected[file.replace(/\.html?/, '')] = html;
				} else if (file.match(/\.tpl?/)) {
					raw[file.replace(/\.tpl?/, '')] = html;
				}

				next();
			});
		}, function(err) {
			if (err) {
				throw new Error(err);
			}

			for (var key in raw) {
				if (raw.hasOwnProperty(key)) {
					if (typeof expected[key] === 'undefined') {
						winston.warn('Missing expected file: ' + key + '.html');
						delete raw[key];
					}
				}
			}

			callback(raw, expected);
		});

	});
}

function test(raw, expected) {
	describe('templates.js', function() {
		var keys = Object.keys(raw);

		async.each(keys, function(key, next) {
			it(key, function() {
				var parsed = templates.parse(raw[key], data);
				if (parsed !== expected[key]) {
					fs.writeFile(path.join(TEMPLATES_DIRECTORY, key + '.log'), parsed);
				} else {
					fs.unlink(path.join(TEMPLATES_DIRECTORY, key + '.log'));
				}

				assert.equal(parsed, expected[key]);

				next();
			});
		}, function(err) {
			if (err) {
				throw new Error(err);
			}
		});
	});
}

prepare(test);<|endoftext|>


<commit_before>// Event handler for updating the current activities on the subject coordinator dashboards
SC.updateCurrentActivities = function(href) {
    new Ajax.Request(href, {
        postBody: $('current-activities-form').serialize()
    });
}

SC.registerCurrentActivitiesUpdaters = function(href) {
    Event.observe(window, 'load', function() {
        var handler = function() { SC.updateCurrentActivities(href) }

        $('toDate').observe('change', handler)
        var browser=navigator.appName;
        if (browser=="Microsoft Internet Explorer") {
            $('toDate').observe('keypress', function(e) {
                if(e.keyCode == 13) {
                    SC.updateCurrentActivities(href)
                }
            })
        }

        $$('input.activity-type').each(function(input) {
            input.observe('click', handler)
        })

        $$('option.activity-type').each(function(option) {
            option.observe('click', handler)
        })
        var handler1 = function(evt) {
            Event.stop(evt)
        }
        $('current-activities-form').observe('submit', handler1)
    })
}

function selectAll(selectBox, selectAll) {
    var box = $(selectBox);
    for (var i = 0; i < box.options.length; i++) {
        box.options[i].selected = selectAll;
    }
}
<commit_msg>Commit for bugs #1005. Added timeout of 3 seconds to check for updates on the date field.<commit_after>// Event handler for updating the current activities on the subject coordinator dashboards
SC.updateCurrentActivities = function(href) {
    new Ajax.Request(href, {
        postBody: $('current-activities-form').serialize()
    });
}

var timeout = 3000;
var delay;
SC.registerCurrentActivitiesUpdaters = function(href) {
    Event.observe(window, 'load', function() {
        var toDateValueOld = $('toDate').value;
        delay = function() { timeoutFunction(toDateValueOld, href) };
        setTimeout(delay, timeout);

        var handler = function() { SC.updateCurrentActivities(href) }

//        $('toDate').observe('change', handler)

        var browser=navigator.appName;
        if (browser=="Microsoft Internet Explorer") {
            $('toDate').observe('keypress', function(e) {
                if(e.keyCode == 13) {
                    SC.updateCurrentActivities(href)
                }
            })
        }

        $$('input.activity-type').each(function(input) {
            input.observe('click', handler)
        })

        $$('option.activity-type').each(function(option) {
            option.observe('click', handler)
        })
        var handler1 = function(evt) {
            Event.stop(evt)
        }
        $('current-activities-form').observe('submit', handler1)
    })
}

function timeoutFunction(toDateValueOld, href) {
  var toDateValueNew = $('toDate').value;
  if (toDateValueOld != toDateValueNew) {
    SC.updateCurrentActivities(href)
  }
  delay = function() {timeoutFunction(toDateValueNew, href)};
  setTimeout(delay, timeout)
}

function selectAll(selectBox, selectAll) {
    var box = $(selectBox);
    for (var i = 0; i < box.options.length; i++) {
        box.options[i].selected = selectAll;
    }
}
<|endoftext|>


<commit_before>
/** Note: This file doesn't contain any unit tests. It has some architecture for
 * performing common test function.*/

const RG = require('../client/src/battles');
const expect = require('chai').expect;

const RGTest = {
};

RGTest.rng = new RG.Random();

/* Creates a mock-level for unit tests. */
RGTest.createMockLevel = function(cols, rows) {
    const level = {cols: cols, rows: rows,
        map: {
            getCell: function(x, y) {
                return { x: x, y: y };
            },
            hasXY: function() {
                return true;
            },
            isPassable: function(x, y) {
                return x > -1 && y > -1;
            }
        },
        getMap: function() {return this.map;},

        addActor: function(actor, x, y) {
            actor.setXY(x, y);
            actor.setLevel(this);
        }
    };
    return level;
};

RGTest.createLevel = function(type, cols, rows) {
    return RG.FACT.createLevel('arena', cols, rows);
};

RGTest.equipItem = function(actor, item) {
    const invEq = actor.getInvEq();
    invEq.addItem(item);
    expect(invEq.equipItem(item)).to.equal(true);
};

/* Wraps an object into a cell for later use. Some functions require a map cell
* instead of taking the object directly, so this is useful. */
RGTest.wrapObjWithCell = function(obj) {
    const cell = RG.FACT.createFloorCell();
    cell.setExplored(true); // Otherwise returns darkness
    const propType = obj.getPropType();
    cell.setProp(propType, obj);
    return cell;
};

RGTest.getMeAWizard = function(conf = {}) {
    const wizard = new RG.Actor.Rogue('wizard');
    wizard.setType(conf.type || 'human');
    const brain = new RG.Brain.SpellCaster(wizard);
    wizard.setBrain(brain);

    wizard._spellbook = new RG.Spell.SpellBook(wizard);
    const spell = RG.FACT.createSpell('FrostBolt');
    spell.setPower(conf.power || 11);
    spell.setRange(conf.range || 7);
    spell.setDice([RG.FACT.createDie([1, 2, 3])]);
    wizard._spellbook.addSpell(spell);

    const spellPower = new RG.Component.SpellPower();
    spellPower.setPP(30);
    spellPower.setMaxPP(40);
    wizard.add('SpellPower', spellPower);
    return wizard;

};

RGTest.checkActorXY = function(actor, x, y) {
    expect(actor.getX(), `X must be ${x}`).to.equal(x);
    expect(actor.getY(), `Y must be ${y}`).to.equal(y);
};

RGTest.checkChar = function(obj, expChar) {
    const cell = RGTest.wrapObjWithCell(obj);
    expect(RG.getCellChar(cell)).to.equal(expChar);
};

RGTest.checkCSSClassName = function(obj, expClass) {
    const cell = RGTest.wrapObjWithCell(obj);
    expect(RG.getStyleClassForCell(cell)).to.equal(expClass);

};

RGTest.expectEqualHealth = function(o1, o2) {
    expect(o1.get('Health').getHP()).to.equal(o2.get('Health').getHP());
};

// Expect that branches b1 and b2 are connected by number of connections
// given by nConns.
RGTest.expectConnected = function(b1, b2, nConns) {
    let connFound = 0;
    const b1Stairs = b1.getStairsOther();
    const b2Stairs = b2.getStairsOther();
    expect(b1Stairs, 'B1 must have stairs').to.have.length.above(0);
    expect(b2Stairs, 'B2 must have stairs').to.have.length.above(0);

    b1Stairs.forEach(stair1 => {
        const s1TargetID = stair1.getTargetLevel().getID();
        expect(stair1.getTargetStairs()).not.to.be.empty;
        b2Stairs.forEach(stair2 => {
            const s2SourceID = stair2.getSrcLevel().getID();
            if (s1TargetID === s2SourceID) {
                // stair1 should be the target of stair2
                if (stair2.getTargetStairs() === stair1) {
                    ++connFound;
                }
                expect(stair2.getTargetStairs()).not.to.be.empty;
            }
        });
    });
    expect(connFound, `Connections between branches must be ${nConns}`)
        .to.equal(nConns);
};

/* Adds each entity into the level. */
RGTest.wrapIntoLevel = function(arr) {
    const level = RG.FACT.createLevel('empty', 20, 20);
    arr.forEach(ent => {
        const x = RGTest.rng.getUniformInt(0, 19);
        const y = RGTest.rng.getUniformInt(0, 19);
        if (ent.getPropType() === RG.TYPE_ACTOR) {
            level.addActor(ent, x, y);
        }
        if (ent.getPropType() === RG.TYPE_ITEM) {
            level.addItem(ent, x, y);
        }
    });
    return level;
};

/* Moves entity from its current position to x,y. */
RGTest.moveEntityTo = function(ent, x, y) {
    const map = ent.getLevel().getMap();
    const xOld = ent.getX();
    const yOld = ent.getY();
    const propType = ent.getPropType();
    if (map.removeProp(xOld, yOld, propType, ent)) {
        map.setProp(x, y, propType, ent);
        ent.setXY(x, y);
        return true;
    }
    throw new Error(`Cannot move entity to ${x}, ${y}`);
};

/* Equips all given items for the given actor, and checks that everything
 * succeeds. */
RGTest.equipItems = function(ent, items) {
    const inv = ent.getInvEq();
    items.forEach(item => {
        inv.addItem(item);
        if (!inv.equipItem(item)) {
            throw new Error(`Cannot equip item ${item}`);
        }
    });
};

module.exports = RGTest;
<commit_msg>Added verifyStairsConnectivity().<commit_after>
/** Note: This file doesn't contain any unit tests. It has some architecture for
 * performing common test function.*/

const RG = require('../client/src/battles');
const expect = require('chai').expect;

const RGTest = {};

RGTest.rng = new RG.Random();

/* Creates a mock-level for unit tests. */
RGTest.createMockLevel = function(cols, rows) {
    const level = {cols: cols, rows: rows,
        map: {
            getCell: function(x, y) {
                return { x: x, y: y };
            },
            hasXY: function() {
                return true;
            },
            isPassable: function(x, y) {
                return x > -1 && y > -1;
            }
        },
        getMap: function() {return this.map;},

        addActor: function(actor, x, y) {
            actor.setXY(x, y);
            actor.setLevel(this);
        }
    };
    return level;
};

RGTest.createLevel = function(type, cols, rows) {
    return RG.FACT.createLevel('arena', cols, rows);
};

RGTest.equipItem = function(actor, item) {
    const invEq = actor.getInvEq();
    invEq.addItem(item);
    expect(invEq.equipItem(item)).to.equal(true);
};

/* Wraps an object into a cell for later use. Some functions require a map cell
* instead of taking the object directly, so this is useful. */
RGTest.wrapObjWithCell = function(obj) {
    const cell = RG.FACT.createFloorCell();
    cell.setExplored(true); // Otherwise returns darkness
    const propType = obj.getPropType();
    cell.setProp(propType, obj);
    return cell;
};

RGTest.getMeAWizard = function(conf = {}) {
    const wizard = new RG.Actor.Rogue('wizard');
    wizard.setType(conf.type || 'human');
    const brain = new RG.Brain.SpellCaster(wizard);
    wizard.setBrain(brain);

    wizard._spellbook = new RG.Spell.SpellBook(wizard);
    const spell = RG.FACT.createSpell('FrostBolt');
    spell.setPower(conf.power || 11);
    spell.setRange(conf.range || 7);
    spell.setDice([RG.FACT.createDie([1, 2, 3])]);
    wizard._spellbook.addSpell(spell);

    const spellPower = new RG.Component.SpellPower();
    spellPower.setPP(30);
    spellPower.setMaxPP(40);
    wizard.add('SpellPower', spellPower);
    return wizard;

};

RGTest.checkActorXY = function(actor, x, y) {
    expect(actor.getX(), `X must be ${x}`).to.equal(x);
    expect(actor.getY(), `Y must be ${y}`).to.equal(y);
};

RGTest.checkChar = function(obj, expChar) {
    const cell = RGTest.wrapObjWithCell(obj);
    expect(RG.getCellChar(cell)).to.equal(expChar);
};

RGTest.checkCSSClassName = function(obj, expClass) {
    const cell = RGTest.wrapObjWithCell(obj);
    expect(RG.getStyleClassForCell(cell)).to.equal(expClass);

};

RGTest.expectEqualHealth = function(o1, o2) {
    expect(o1.get('Health').getHP()).to.equal(o2.get('Health').getHP());
};

RGTest.verifyStairsConnectivity = function(stairs) {
    let connVerified = 0;
    stairs.forEach(s => {
        expect(s.getTargetStairs()).not.to.be.empty;
        expect(s.getTargetLevel()).not.to.be.empty;
        expect(s.getSrcLevel()).not.to.be.empty;
        ++connVerified;
    });
    console.log(`verifyStairsConnectivity ${connVerified} connections OK`);
};

// Expect that branches b1 and b2 are connected by number of connections
// given by nConns.
RGTest.expectConnected = function(b1, b2, nConns) {
    let connFound = 0;
    const b1Stairs = b1.getStairsOther();
    const b2Stairs = b2.getStairsOther();
    expect(b1Stairs, 'B1 must have stairs').to.have.length.above(0);
    expect(b2Stairs, 'B2 must have stairs').to.have.length.above(0);

    b1Stairs.forEach(stair1 => {
        const s1TargetID = stair1.getTargetLevel().getID();
        expect(stair1.getTargetStairs()).not.to.be.empty;
        b2Stairs.forEach(stair2 => {
            const s2SourceID = stair2.getSrcLevel().getID();
            if (s1TargetID === s2SourceID) {
                // stair1 should be the target of stair2
                if (stair2.getTargetStairs() === stair1) {
                    ++connFound;
                }
                expect(stair2.getTargetStairs()).not.to.be.empty;
            }
        });
    });
    expect(connFound, `Connections between branches must be ${nConns}`)
        .to.equal(nConns);
};

/* Adds each entity into the level. */
RGTest.wrapIntoLevel = function(arr) {
    const level = RG.FACT.createLevel('empty', 20, 20);
    arr.forEach(ent => {
        const x = RGTest.rng.getUniformInt(0, 19);
        const y = RGTest.rng.getUniformInt(0, 19);
        if (ent.getPropType() === RG.TYPE_ACTOR) {
            level.addActor(ent, x, y);
        }
        if (ent.getPropType() === RG.TYPE_ITEM) {
            level.addItem(ent, x, y);
        }
    });
    return level;
};

/* Moves entity from its current position to x,y. */
RGTest.moveEntityTo = function(ent, x, y) {
    const map = ent.getLevel().getMap();
    const xOld = ent.getX();
    const yOld = ent.getY();
    const propType = ent.getPropType();
    if (map.removeProp(xOld, yOld, propType, ent)) {
        map.setProp(x, y, propType, ent);
        ent.setXY(x, y);
        return true;
    }
    throw new Error(`Cannot move entity to ${x}, ${y}`);
};

/* Equips all given items for the given actor, and checks that everything
 * succeeds. */
RGTest.equipItems = function(ent, items) {
    const inv = ent.getInvEq();
    items.forEach(item => {
        inv.addItem(item);
        if (!inv.equipItem(item)) {
            throw new Error(`Cannot equip item ${item}`);
        }
    });
};

module.exports = RGTest;
<|endoftext|>