docs: function off(elem, type, fn) {
    // Don't want to add a cache object through getElData if not needed
    if (!Dom.hasElData(elem)) {
      return;
    }
  
    var data = Dom.getElData(elem);
  
    // If no events exist, nothing to unbind
    if (!data.handlers) {
      return;
    }
  
    if (Array.isArray(type)) {
      return _handleMultipleEvents(off, elem, type, fn);
    }
  
    // Utility function
    var removeType = function removeType(t) {
      data.handlers[t] = [];
      _cleanUpEvents(elem, t);
    };
  
    // Are we removing all bound events?
    if (!type) {
      for (var t in data.handlers) {
        removeType(t);
      }
      return;
    }
  
    var handlers = data.handlers[type];
  
    // If no handlers exist, nothing to unbind
    if (!handlers) {
      return;
    }
  
    // If no listener was provided, remove all listeners for type
    if (!fn) {
      removeType(type);
      return;
    }
  
    // We're only removing a single handler
    if (fn.guid) {
      for (var n = 0; n < handlers.length; n++) {
        if (handlers[n].guid === fn.guid) {
          handlers.splice(n--, 1);
        }
      }
    }
  
    _cleanUpEvents(elem, type);
  }