function normalizeEvent(el, e, calculate) {

    e = getNativeEvent(e);

    if (e.zrX != null) {
        return e;
    }

    var eventType = e.type;
    var isTouch = eventType && eventType.indexOf('touch') >= 0;

    if (!isTouch) {
        clientToLocal(el, e, e, calculate);
        e.zrDelta = (e.wheelDelta) ? e.wheelDelta / 120 : -(e.detail || 0) / 3;
    }
    else {
        var touch = eventType !== 'touchend'
            ? e.targetTouches[0]
            : e.changedTouches[0];
        touch && clientToLocal(el, touch, e, calculate);
    }

    // Add which for click: 1 === left; 2 === middle; 3 === right; otherwise: 0;
    // See jQuery: https://github.com/jquery/jquery/blob/master/src/event.js
    // If e.which has been defined, it may be readonly,
    // see: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
    var button = e.button;
    if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) {
        e.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0)));
    }
    // [Caution]: `e.which` from browser is not always reliable. For example,
    // when press left button and `mousemove (pointermove)` in Edge, the `e.which`
    // is 65536 and the `e.button` is -1. But the `mouseup (pointerup)` and
    // `mousedown (pointerdown)` is the same as Chrome does.

    return e;
}
Normalize the coordinates of the input event.

Get the `e.zrX` and `e.zrY`, which are relative to the top-left of
the input `el`.
Get `e.zrDelta` if using mouse wheel.
Get `e.which`, see the comment inside this function.

Do not calculate repeatly if `zrX` and `zrY` already exist.

Notice: see comments in `clientToLocal`. check the relationship
between the result coords and the parameters `el` and `calculate`.

@param {HTMLElement} el DOM element.
@param {Event} [e] See `getNativeEvent`.
@param {boolean} [calculate=false] Whether to force calculate
       the coordinates but not use ones provided by browser.
@return {UIEvent} The normalized native UIEvent.