docs: function (el, selector, eventName, func) {
  			if (!el) {
  				this.off();
  
  				var cls = this.constructor,
  					bindings = this._bindings,
  					actions = cls.actions,
  					element = this.constructor.unwrapElement(this.element),
  					destroyCB = Control._shifter(this, "destroy"),
  					funcName, ready;
  
  				for (funcName in actions) {
  					// Only push if we have the action and no option is `undefined`
  					if ( actions.hasOwnProperty(funcName) ) {
  						ready = actions[funcName] || cls._action(funcName, this.options, this);
  						if( ready ) {
  							bindings.control[funcName]  = ready.processor(ready.delegate || element,
  								ready.parts[2], ready.parts[1], funcName, this);
  						}
  					}
  				}
  
  				// Set up the ability to `destroy` the control later.
  				var removalDisposal = domMutate.onNodeRemoval(element, function () {
  					var doc = element.ownerDocument;
  					var ownerNode = doc.contains ? doc : doc.documentElement;
  					if (!ownerNode || ownerNode.contains(element) === false) {
  						destroyCB();
  					}
  				});
  				bindings.user.push(function () {
  					if (removalDisposal) {
  						removalDisposal();
  						removalDisposal = undefined;
  					}
  				});
  				return bindings.user.length;
  			}
  
  			// if `el` is a string, use that as `selector` and re-set it to this control's element...
  			if (typeof el === 'string') {
  				func = eventName;
  				eventName = selector;
  				selector = el;
  				el = this.element;
  			}
  
  			// ...otherwise, set `selector` to null
  			if (func === undefined) {
  				func = eventName;
  				eventName = selector;
  				selector = null;
  			}
  
  			if (typeof func === 'string') {
  				func = Control._shifter(this, func);
  			}
  
  			this._bindings.user.push(binder(el, eventName, func, selector));
  
  			return this._bindings.user.length;
  		}