docs: function (sourceEvent, newName, canBubble, target, relatedTarget) {
          // Considering touch events are almost like super mouse events
          var evObj;
  
          if (document.createEvent && supportsMouseEvents) {
              evObj = document.createEvent('MouseEvents');
              // TODO: Replace 'initMouseEvent' with 'new MouseEvent'
              evObj.initMouseEvent(newName, canBubble, true, window, 1, sourceEvent.screenX, sourceEvent.screenY,
                  sourceEvent.clientX, sourceEvent.clientY, sourceEvent.ctrlKey, sourceEvent.altKey,
                  sourceEvent.shiftKey, sourceEvent.metaKey, sourceEvent.button, relatedTarget || sourceEvent.relatedTarget);
          } else {
              evObj = document.createEventObject();
              evObj.screenX = sourceEvent.screenX;
              evObj.screenY = sourceEvent.screenY;
              evObj.clientX = sourceEvent.clientX;
              evObj.clientY = sourceEvent.clientY;
              evObj.ctrlKey = sourceEvent.ctrlKey;
              evObj.altKey = sourceEvent.altKey;
              evObj.shiftKey = sourceEvent.shiftKey;
              evObj.metaKey = sourceEvent.metaKey;
              evObj.button = sourceEvent.button;
              evObj.relatedTarget = relatedTarget || sourceEvent.relatedTarget;
          }
          // offsets
          if (evObj.offsetX === undefined) {
              if (sourceEvent.offsetX !== undefined) {
  
                  // For Opera which creates readonly properties
                  if (Object && Object.defineProperty !== undefined) {
                      Object.defineProperty(evObj, 'offsetX', {
                          writable: true
                      });
                      Object.defineProperty(evObj, 'offsetY', {
                          writable: true
                      });
                  }
  
                  evObj.offsetX = sourceEvent.offsetX;
                  evObj.offsetY = sourceEvent.offsetY;
              } else if (Object && Object.defineProperty !== undefined) {
                  Object.defineProperty(evObj, 'offsetX', {
                      get: function () {
                          if (this.currentTarget && this.currentTarget.offsetLeft) {
                              return sourceEvent.clientX - this.currentTarget.offsetLeft;
                          }
                          return sourceEvent.clientX;
                      }
                  });
                  Object.defineProperty(evObj, 'offsetY', {
                      get: function () {
                          if (this.currentTarget && this.currentTarget.offsetTop) {
                              return sourceEvent.clientY - this.currentTarget.offsetTop;
                          }
                          return sourceEvent.clientY;
                      }
                  });
              }
              else if (sourceEvent.layerX !== undefined) {
                  evObj.offsetX = sourceEvent.layerX - sourceEvent.currentTarget.offsetLeft;
                  evObj.offsetY = sourceEvent.layerY - sourceEvent.currentTarget.offsetTop;
              }
          }
  
          // adding missing properties
  
          if (sourceEvent.isPrimary !== undefined)
              evObj.isPrimary = sourceEvent.isPrimary;
          else
              evObj.isPrimary = true;
  
          if (sourceEvent.pressure)
              evObj.pressure = sourceEvent.pressure;
          else {
              var button = 0;
  
              if (sourceEvent.which !== undefined)
                  button = sourceEvent.which;
              else if (sourceEvent.button !== undefined) {
                  button = sourceEvent.button;
              }
              evObj.pressure = (button === 0) ? 0 : 0.5;
          }
  
          if (sourceEvent.rotation)
              evObj.rotation = sourceEvent.rotation;
          else
              evObj.rotation = 0;
  
          // Timestamp
          if (sourceEvent.hwTimestamp)
              evObj.hwTimestamp = sourceEvent.hwTimestamp;
          else
              evObj.hwTimestamp = 0;
  
          // Tilts
          if (sourceEvent.tiltX)
              evObj.tiltX = sourceEvent.tiltX;
          else
              evObj.tiltX = 0;
  
          if (sourceEvent.tiltY)
              evObj.tiltY = sourceEvent.tiltY;
          else
              evObj.tiltY = 0;
  
          // Width and Height
          if (sourceEvent.height)
              evObj.height = sourceEvent.height;
          else
              evObj.height = 0;
  
          if (sourceEvent.width)
              evObj.width = sourceEvent.width;
          else
              evObj.width = 0;
  
          // preventDefault
          evObj.preventDefault = function () {
              if (sourceEvent.preventDefault !== undefined)
                  sourceEvent.preventDefault();
          };
  
          // stopPropagation
          if (evObj.stopPropagation !== undefined) {
              var current = evObj.stopPropagation;
              evObj.stopPropagation = function () {
                  if (sourceEvent.stopPropagation !== undefined)
                      sourceEvent.stopPropagation();
                  current.call(this);
              };
          }
  
          // Pointer values
          evObj.pointerId = sourceEvent.pointerId;
          evObj.pointerType = sourceEvent.pointerType;
  
          switch (evObj.pointerType) {// Old spec version check
          case 2:
              evObj.pointerType = POINTER_TYPE_TOUCH;
              break;
          case 3:
              evObj.pointerType = POINTER_TYPE_PEN;
              break;
          case 4:
              evObj.pointerType = POINTER_TYPE_MOUSE;
              break;
          }
  
          // Fire event
          if (target)
              target.dispatchEvent(evObj);
          else if (sourceEvent.target && supportsMouseEvents) {
              sourceEvent.target.dispatchEvent(evObj);
          } else {
              sourceEvent.srcElement.fireEvent('on' + getMouseEquivalentEventName(newName), evObj); // We must fallback to mouse event for very old browsers
          }
      }