/**
 * Element supporting "sequential focus navigation" using the 'tabindex' attribute.
 *
 * @abstract
 * @class
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {jQuery} [$tabIndexed] tabIndexed node, assigned to #$tabIndexed, omit to use #$element
 * @cfg {number|null} [tabIndex=0] Tab index value. Use 0 to use default ordering, use -1 to
 *  prevent tab focusing, use null to suppress the `tabindex` attribute.
 */
OO.ui.TabIndexedElement = function OoUiTabIndexedElement( config ) {
	// Configuration initialization
	config = $.extend( { tabIndex: 0 }, config );

	// Properties
	this.$tabIndexed = null;
	this.tabIndex = null;

	// Events
	this.connect( this, { disable: 'onDisable' } );

	// Initialization
	this.setTabIndex( config.tabIndex );
	this.setTabIndexedElement( config.$tabIndexed || this.$element );
};

/* Setup */

OO.initClass( OO.ui.TabIndexedElement );

/* Methods */

/**
 * Set the element with `tabindex` attribute.
 *
 * If an element is already set, it will be cleaned up before setting up the new element.
 *
 * @param {jQuery} $tabIndexed Element to set tab index on
 * @chainable
 */
OO.ui.TabIndexedElement.prototype.setTabIndexedElement = function ( $tabIndexed ) {
	var tabIndex = this.tabIndex;
	// Remove attributes from old $tabIndexed
	this.setTabIndex( null );
	// Force update of new $tabIndexed
	this.$tabIndexed = $tabIndexed;
	this.tabIndex = tabIndex;
	return this.updateTabIndex();
};

/**
 * Set tab index value.
 *
 * @param {number|null} tabIndex Tab index value or null for no tab index
 * @chainable
 */
OO.ui.TabIndexedElement.prototype.setTabIndex = function ( tabIndex ) {
	tabIndex = typeof tabIndex === 'number' ? tabIndex : null;

	if ( this.tabIndex !== tabIndex ) {
		this.tabIndex = tabIndex;
		this.updateTabIndex();
	}

	return this;
};

/**
 * Update the `tabindex` attribute, in case of changes to tab index or
 * disabled state.
 *
 * @chainable
 */
OO.ui.TabIndexedElement.prototype.updateTabIndex = function () {
	if ( this.$tabIndexed ) {
		if ( this.tabIndex !== null ) {
			// Do not index over disabled elements
			this.$tabIndexed.attr( {
				tabindex: this.isDisabled() ? -1 : this.tabIndex,
				// ChromeVox and NVDA do not seem to inherit this from parent elements
				'aria-disabled': this.isDisabled().toString()
			} );
		} else {
			this.$tabIndexed.removeAttr( 'tabindex aria-disabled' );
		}
	}
	return this;
};

/**
 * Handle disable events.
 *
 * @param {boolean} disabled Element is disabled
 */
OO.ui.TabIndexedElement.prototype.onDisable = function () {
	this.updateTabIndex();
};

/**
 * Get tab index value.
 *
 * @return {number|null} Tab index value
 */
OO.ui.TabIndexedElement.prototype.getTabIndex = function () {
	return this.tabIndex;
};

@@ -4,88 +4,960 @@
 %0A * 
-Element supporting %22sequential focus navigation%22 using the 'tabi
+The TabIndexedElement class is an attribute mixin used to add additional functionality to an%0A * element created by another class. The mixin provides a %E2%80%98tabIndex%E2%80%99 property, which specifies the%0A * order in which users will navigate through the focusable elements via the %22tab%22 key.%0A *%0A *     @example%0A *     // TabIndexedElement is mixed into the ButtonWidget class%0A *     // to provide a tabIndex property.%0A *     var button1 = new OO.ui.ButtonWidget( %7B%0A *         label : 'fourth',%0A *         tabIndex : 4%0A *     %7D );%0A *     var button2 = new OO.ui.ButtonWidget( %7B%0A *         label : 'second',%0A *         tabIndex : 2%0A *     %7D );%0A *     var button3 = new OO.ui.ButtonWidget( %7B%0A *         label : 'third',%0A *         tabIndex : 3%0A *     %7D );%0A *     var button4 = new OO.ui.ButtonWidget( %7B%0A *         label : 'first',%0A *         tabI
 ndex
-' attribute.
+ : 1%0A *     %7D );%0A *     $( 'body' ).append( button1.$element, button2.$element, button3.$element, button4.$element );
 %0A *%0A
@@ -3318,24 +3318,36 @@
  events.%0A *%0A
+ * @private%0A
  * @param %7Bb

Add description, example, and mark private method