text: // this code is from test-agent might use native dom events
  // or something else in the future to replace this.
  define(function(require, exports, module) {
  'use strict';
  
  /**
   * @param {Object} list of events to add onto responder.
   */
  function Responder(events) {
    this._$events = Object.create(null);
  
    if (typeof(events) !== 'undefined') {
      this.addEventListener(events);
    }
  }
  module.exports = Responder;
  
  /**
   * Stringifies request to websocket
   *
   *
   * @param {String} command command name.
   * @param {Object} data object to be sent over the wire.
   * @return {String} json object.
   */
  Responder.stringify = function stringify(command, data) {
    return JSON.stringify([command, data]);
  };
  
  /**
   * Parses request from WebSocket.
   *
   * @param {String} json json string to translate.
   * @return {Object} ex: { event: 'test', data: {} }.
   */
  Responder.parse = function parse(json) {
    var data;
    try {
      data = (json.forEach) ? json : JSON.parse(json);
    } catch (e) {
      throw new Error('Could not parse json: "' + json + '"');
    }
  
    return data;
  };
  
  Responder.prototype = {
    parse: Responder.parse,
    stringify: Responder.stringify,
  
    /**
     * Events on this instance
     *
     * @type Object
     */
    events: null,
  
    /**
     * Recieves json string event and dispatches an event.
     *
     * @param {String|Object} json data object to respond to.
     * @param {String} json.event event to emit.
     * @param {Object} json.data data to emit with event.
     * @param {Object} [params] option number of params to pass to emit.
     * @return {Object} result of WebSocketCommon.parse.
     */
    respond: function respond(json) {
      var event = Responder.parse(json);
      var args = Array.prototype.slice.call(arguments).slice(1);
      this.emit.apply(this, event.concat(args));
  
      return event;
    },
  
    /**
     * Adds an event listener to this object.
     *
     *
     * @param {String} type event name.
     * @param {Function} callback event callback.
     */
    addEventListener: function addEventListener(type, callback) {
      var event;
  
      if (typeof(callback) === 'undefined' && typeof(type) === 'object') {
        for (event in type) {
          if (type.hasOwnProperty(event)) {
            this.addEventListener(event, type[event]);
          }
        }
  
        return this;
      }
  
      if (!(type in this._$events)) {
        this._$events[type] = [];
      }
  
      this._$events[type].push(callback);
  
      return this;
    },
  
    /**
     * Adds an event listener which will
     * only fire once and then remove itself.
     *
     *
     * @param {String} type event name.
     * @param {Function} callback fired when event is emitted.
     */
    once: function once(type, callback) {
      var self = this;
      function onceCb() {
        /*jshint validthis:true */
        self.removeEventListener(type, onceCb);
        callback.apply(this, arguments);
      }
  
      this.addEventListener(type, onceCb);
  
      return this;
    },
  
    /**
     * Emits an event.
     *
     * Accepts any number of additional arguments to pass unto
     * event listener.
     *
     * @param {String} eventName name of the event to emit.
     * @param {Object} [arguments] additional arguments to pass.
     */
    emit: function emit() {
      var args = Array.prototype.slice.call(arguments),
          event = args.shift(),
          eventList,
          self = this;
  
      if (event in this._$events) {
        eventList = this._$events[event];
  
        eventList.forEach(function(callback) {
          if (typeof(callback) === 'object' && callback.handleEvent) {
            callback.handleEvent({ type: event, data: args });
          } else {
            callback.apply(self, args);
          }
        });
      }
  
      return this;
    },
  
    /**
     * Removes all event listeners for a given event type
     *
     *
     * @param {String} event event type to remove.
     */
    removeAllEventListeners: function removeAllEventListeners(name) {
      if (name in this._$events) {
        //reuse array
        this._$events[name].length = 0;
      }
  
      return this;
    },
  
    /**
     * Removes a single event listener from a given event type
     * and callback function.
     *
     *
     * @param {String} eventName event name.
     * @param {Function} callback same instance of event handler.
     */
    removeEventListener: function removeEventListener(name, callback) {
      var i, length, events;
  
      if (!(name in this._$events)) {
        return false;
      }
  
      events = this._$events[name];
  
      for (i = 0, length = events.length; i < length; i++) {
        if (events[i] && events[i] === callback) {
          events.splice(i, 1);
          return true;
        }
      }
  
      return false;
    }
  
  };
  
  Responder.prototype.on = Responder.prototype.addEventListener;
  Responder.prototype.off = Responder.prototype.removeEventListener;
  
  });
  