lib/mouse.js
function Mouse(canvas) {
  /**
* The x coordinate of the cursor relative to the left side of the canvas.
* @member {number}
*/
  this.x = 0;
  /**
   * The y coordinate of the cursor relative to the top of the canvas.
   * @member {number}
   */
  this.y = 0;
  /**
   * The current button states.
   * @member {Array}
   * @private
   */
  this.buttons = [false, false, false];

  /**
   * An array of the current touches on a touch screen device. Each touch has a `x`, `y`, and `id` field.
   * @member {Array}
   */
  this.touches = [];

  /**
   * A function that is called when a mouse button or touch is released.
   * @callback onmouseupHandler
   * @param {number} x The x coordinate of the mouse or touch that was released.
   * @param {number} y The y coordinate of the mouse or touch that was released.
   */
  /**
   * A function that will be called when a mouse button is released, or a touch has stopped.
   * This is useful for opening a URL with {@link Splat.openUrl} to avoid popup blockers.
   * @member {onmouseupHandler}
   */
  this.onmouseup = undefined;

  var self = this;
  canvas.addEventListener("mousedown", function(event) {
    relMouseCoords(canvas, event, self);
    self.buttons[event.button] = true;
    updateTouchFromMouse();
  });
  canvas.addEventListener("mouseup", function(event) {
    relMouseCoords(canvas, event, self);
    self.buttons[event.button] = false;
    updateTouchFromMouse();
    if (self.onmouseup) {
      self.onmouseup(self.x, self.y);
    }
  });
  canvas.addEventListener("mousemove", function(event) {
    relMouseCoords(canvas, event, self);
    updateTouchFromMouse();
  });

  function updateTouchFromMouse() {
    if (self.supportsTouch()) {
      return;
    }
    var idx = touchIndexById("mouse");
    if (self.isPressed(0)) {
      if (idx !== undefined) {
        var touch = self.touches[idx];
        touch.x = self.x;
        touch.y = self.y;
      } else {
        self.touches.push({
          id: "mouse",
          x: self.x,
          y: self.y
        });
      }
    } else if (idx !== undefined) {
      self.touches.splice(idx, 1);
    }
  }
  function updateMouseFromTouch(touch) {
    self.x = touch.x;
    self.y = touch.y;
    if (self.buttons[0] === false) {
      self.buttons[0] = true;
    }
  }
  function touchIndexById(id) {
    for (var i = 0; i < self.touches.length; i++) {
      if (self.touches[i].id === id) {
        return i;
      }
    }
    return undefined;
  }
  function eachChangedTouch(event, onChangeFunc) {
    var touches = event.changedTouches;
    for (var i = 0; i < touches.length; i++) {
      onChangeFunc(touches[i]);
    }
  }
  canvas.addEventListener("touchstart", function(event) {
    eachChangedTouch(event, function(touch) {
      var t = {
        id: touch.identifier
      };
      relMouseCoords(canvas, touch, t);
      if (self.touches.length === 0) {
        t.isMouse = true;
        updateMouseFromTouch(t);
      }
      self.touches.push(t);
    });
  });
  canvas.addEventListener("touchmove", function(event) {
    eachChangedTouch(event, function(touch) {
      var idx = touchIndexById(touch.identifier);
      var t = self.touches[idx];
      relMouseCoords(canvas, touch, t);
      if (t.isMouse) {
        updateMouseFromTouch(t);
      }
    });
  });
  canvas.addEventListener("touchend", function(event) {
    eachChangedTouch(event, function(touch) {
      var idx = touchIndexById(touch.identifier);
      var t = self.touches.splice(idx, 1)[0];
      if (t.isMouse) {
        if (self.touches.length === 0) {
          self.buttons[0] = false;
        } else {
          self.touches[0].isMouse = true;
          updateMouseFromTouch(self.touches[0]);
        }
      }
      if (self.onmouseup) {
        self.onmouseup(t.x, t.y);
      }
    });
  });
}
function Mouse(canvas) {
  /**
* The x coordinate of the cursor relative to the left side of the canvas.
* @member {number}
*/
  this.x = 0;
  /**
   * The y coordinate of the cursor relative to the top of the canvas.
   * @member {number}
   */
  this.y = 0;
  /**
   * The current button states.
   * @member {Array}
   * @private
   */
  this.buttons = [false, false, false];

  /**
   * An array of the current touches on a touch screen device. Each touch has a `x`, `y`, and `id` field.
   * @member {Array}
   */
  this.touches = [];

  /**
   * A function that is called when a mouse button or touch is released.
   * @callback onmouseupHandler
   * @param {number} x The x coordinate of the mouse or touch that was released.
   * @param {number} y The y coordinate of the mouse or touch that was released.
   */
  /**
   * A function that will be called when a mouse button is released, or a touch has stopped.
   * This is useful for opening a URL with {@link Splat.openUrl} to avoid popup blockers.
   * @member {onmouseupHandler}
   */
  this.onmouseup = undefined;

  var self = this;
  canvas.addEventListener("mousedown", function(event) {
    relMouseCoords(canvas, event, self);
    self.buttons[event.button] = true;
    updateTouchFromMouse();
  });
  canvas.addEventListener("mouseup", function(event) {
    relMouseCoords(canvas, event, self);
    self.buttons[event.button] = false;
    updateTouchFromMouse();
    if (self.onmouseup) {
      self.onmouseup(self.x, self.y);
    }
  });
  canvas.addEventListener("mousemove", function(event) {
    relMouseCoords(canvas, event, self);
    updateTouchFromMouse();
  });

  function updateTouchFromMouse() {
    if (self.supportsTouch()) {
      return;
    }
    var idx = touchIndexById("mouse");
    if (self.isPressed(0)) {
      if (idx !== undefined) {
        var touch = self.touches[idx];
        touch.x = self.x;
        touch.y = self.y;
      } else {
        self.touches.push({
          id: "mouse",
          x: self.x,
          y: self.y
        });
      }
    } else if (idx !== undefined) {
      self.touches.splice(idx, 1);
    }
  }
  function updateMouseFromTouch(touch) {
    self.x = touch.x;
    self.y = touch.y;
    if (self.buttons[0] === false) {
      self.buttons[0] = true;
    }
  }
  function touchIndexById(id) {
    for (var i = 0; i < self.touches.length; i++) {
      if (self.touches[i].id === id) {
        return i;
      }
    }
    return undefined;
  }
  function eachChangedTouch(event, onChangeFunc) {
    var touches = event.changedTouches;
    for (var i = 0; i < touches.length; i++) {
      onChangeFunc(touches[i]);
    }
  }
  canvas.addEventListener("touchstart", function(event) {
    eachChangedTouch(event, function(touch) {
      var t = {
        id: touch.identifier
      };
      relMouseCoords(canvas, touch, t);
      if (self.touches.length === 0) {
        t.isMouse = true;
        updateMouseFromTouch(t);
      }
      self.touches.push(t);
    });
  });
  canvas.addEventListener("touchmove", function(event) {
    eachChangedTouch(event, function(touch) {
      var idx = touchIndexById(touch.identifier);
      var t = self.touches[idx];
      relMouseCoords(canvas, touch, t);
      if (t.isMouse) {
        updateMouseFromTouch(t);
      }
    });
  });
  canvas.addEventListener("touchend", function(event) {
    eachChangedTouch(event, function(touch) {
      var idx = touchIndexById(touch.identifier);
      var t = self.touches.splice(idx, 1)[0];
      if (t.isMouse) {
        if (self.touches.length === 0) {
          self.buttons[0] = false;
        } else {
          self.touches[0].isMouse = true;
          updateMouseFromTouch(self.touches[0]);
        }
      }
      if (self.onmouseup) {
        self.onmouseup(t.x, t.y);
      }
    });
  });
}
function Mouse ( canvas ) { /**
* The x coordinate of the cursor relative to the left side of the canvas.
* @member {number}
*/ this . x = 0 ; /**
   * The y coordinate of the cursor relative to the top of the canvas.
   * @member {number}
   */ this . y = 0 ; /**
   * The current button states.
   * @member {Array}
   * @private
   */ this . buttons = [ false , false , false ] ; /**
   * An array of the current touches on a touch screen device. Each touch has a `x`, `y`, and `id` field.
   * @member {Array}
   */ this . touches = [ ] ; /**
   * A function that is called when a mouse button or touch is released.
   * @callback onmouseupHandler
   * @param {number} x The x coordinate of the mouse or touch that was released.
   * @param {number} y The y coordinate of the mouse or touch that was released.
   */ /**
   * A function that will be called when a mouse button is released, or a touch has stopped.
   * This is useful for opening a URL with {@link Splat.openUrl} to avoid popup blockers.
   * @member {onmouseupHandler}
   */ this . onmouseup = undefined ; var self = this ; canvas . addEventListener ( "mousedown" , function ( event ) { relMouseCoords ( canvas , event , self ) ; self . buttons [ event . button ] = true ; updateTouchFromMouse ( ) ; } ) ; canvas . addEventListener ( "mouseup" , function ( event ) { relMouseCoords ( canvas , event , self ) ; self . buttons [ event . button ] = false ; updateTouchFromMouse ( ) ; if ( self . onmouseup ) { self . onmouseup ( self . x , self . y ) ; } } ) ; canvas . addEventListener ( "mousemove" , function ( event ) { relMouseCoords ( canvas , event , self ) ; updateTouchFromMouse ( ) ; } ) ; function updateTouchFromMouse ( ) { if ( self . supportsTouch ( ) ) { return ; } var idx = touchIndexById ( "mouse" ) ; if ( self . isPressed ( 0 ) ) { if ( idx !== undefined ) { var touch = self . touches [ idx ] ; touch . x = self . x ; touch . y = self . y ; } else { self . touches . push ( { id : "mouse" , x : self . x , y : self . y } ) ; } } else if ( idx !== undefined ) { self . touches . splice ( idx , 1 ) ; } } function updateMouseFromTouch ( touch ) { self . x = touch . x ; self . y = touch . y ; if ( self . buttons [ 0 ] === false ) { self . buttons [ 0 ] = true ; } } function touchIndexById ( id ) { for ( var i = 0 ; i < self . touches . length ; i ++ ) { if ( self . touches [ i ] . id === id ) { return i ; } } return undefined ; } function eachChangedTouch ( event , onChangeFunc ) { var touches = event . changedTouches ; for ( var i = 0 ; i < touches . length ; i ++ ) { onChangeFunc ( touches [ i ] ) ; } } canvas . addEventListener ( "touchstart" , function ( event ) { eachChangedTouch ( event , function ( touch ) { var t = { id : touch . identifier } ; relMouseCoords ( canvas , touch , t ) ; if ( self . touches . length === 0 ) { t . isMouse = true ; updateMouseFromTouch ( t ) ; } self . touches . push ( t ) ; } ) ; } ) ; canvas . addEventListener ( "touchmove" , function ( event ) { eachChangedTouch ( event , function ( touch ) { var idx = touchIndexById ( touch . identifier ) ; var t = self . touches [ idx ] ; relMouseCoords ( canvas , touch , t ) ; if ( t . isMouse ) { updateMouseFromTouch ( t ) ; } } ) ; } ) ; canvas . addEventListener ( "touchend" , function ( event ) { eachChangedTouch ( event , function ( touch ) { var idx = touchIndexById ( touch . identifier ) ; var t = self . touches . splice ( idx , 1 ) [ 0 ] ; if ( t . isMouse ) { if ( self . touches . length === 0 ) { self . buttons [ 0 ] = false ; } else { self . touches [ 0 ] . isMouse = true ; updateMouseFromTouch ( self . touches [ 0 ] ) ; } } if ( self . onmouseup ) { self . onmouseup ( t . x , t . y ) ; } } ) ; } ) ; }
Mouse and touch input handling. An instance of Mouse is available as {@link Splat.Game#mouse}.

The first touch will emulates a mouse press with button 0.
This means you can use the mouse ({@link Mouse#isPressed}) APIs and your game will work on touch screens (as long as you only need the left button).

A mouse press will emulate a touch if the device does not support touch.
This means you can use {@link Mouse#touches}, and your game will still work on a PC with a mouse.

@constructor
@param {external:canvas} canvas The canvas to listen for events on.
Mouse and touch input handling . An instance of Mouse is available as { @link Splat . Game#mouse } .