/** * ButtonWidget is a generic widget for buttons. A wide variety of looks, * feels, and functionality can be customized via the class’s configuration options * and methods. Please see the [OOjs UI documentation on MediaWiki] [1] for more information * and examples. * * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches * * @example * // A button widget * var button = new OO.ui.ButtonWidget( { * label: 'Button with Icon', * icon: 'remove', * iconTitle: 'Remove' * } ); * $( 'body' ).append( button.$element ); * * NOTE: HTML form buttons should use the OO.ui.ButtonInputWidget class. * * @class * @extends OO.ui.Widget * @mixins OO.ui.ButtonElement * @mixins OO.ui.IconElement * @mixins OO.ui.IndicatorElement * @mixins OO.ui.LabelElement * @mixins OO.ui.TitledElement * @mixins OO.ui.FlaggedElement * @mixins OO.ui.TabIndexedElement * * @constructor * @param {Object} [config] Configuration options * @cfg {string} [href] Hyperlink to visit when the button is clicked. * @cfg {string} [target] The frame or window in which to open the hyperlink. * @cfg {boolean} [noFollow] Search engine traversal hint (default: true) */ OO.ui.ButtonWidget = function OoUiButtonWidget( config ) { // Configuration initialization config = config || {}; // Parent constructor OO.ui.ButtonWidget.super.call( this, config ); // Mixin constructors OO.ui.ButtonElement.call( this, config ); OO.ui.IconElement.call( this, config ); OO.ui.IndicatorElement.call( this, config ); OO.ui.LabelElement.call( this, config ); OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) ); OO.ui.FlaggedElement.call( this, config ); OO.ui.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) ); // Properties this.href = null; this.target = null; this.noFollow = false; // Events this.connect( this, { disable: 'onDisable' } ); // Initialization this.$button.append( this.$icon, this.$label, this.$indicator ); this.$element .addClass( 'oo-ui-buttonWidget' ) .append( this.$button ); this.setHref( config.href ); this.setTarget( config.target ); this.setNoFollow( config.noFollow ); }; /* Setup */ OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatorElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabelElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TitledElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggedElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TabIndexedElement ); /* Methods */ /** * @inheritdoc */ OO.ui.ButtonWidget.prototype.onMouseDown = function ( e ) { if ( !this.isDisabled() ) { // Remove the tab-index while the button is down to prevent the button from stealing focus this.$button.removeAttr( 'tabindex' ); } return OO.ui.ButtonElement.prototype.onMouseDown.call( this, e ); }; /** * @inheritdoc */ OO.ui.ButtonWidget.prototype.onMouseUp = function ( e ) { if ( !this.isDisabled() ) { // Restore the tab-index after the button is up to restore the button's accessibility this.$button.attr( 'tabindex', this.tabIndex ); } return OO.ui.ButtonElement.prototype.onMouseUp.call( this, e ); }; /** * Get hyperlink location. * * @return {string} Hyperlink location */ OO.ui.ButtonWidget.prototype.getHref = function () { return this.href; }; /** * Get hyperlink target. * * @return {string} Hyperlink target */ OO.ui.ButtonWidget.prototype.getTarget = function () { return this.target; }; /** * Get search engine traversal hint. * * @return {boolean} Whether search engines should avoid traversing this hyperlink */ OO.ui.ButtonWidget.prototype.getNoFollow = function () { return this.noFollow; }; /** * Set hyperlink location. * * @param {string|null} href Hyperlink location, null to remove */ OO.ui.ButtonWidget.prototype.setHref = function ( href ) { href = typeof href === 'string' ? href : null; if ( href !== this.href ) { this.href = href; this.updateHref(); } return this; }; /** * Update the `href` attribute, in case of changes to href or * disabled state. * * @private * @chainable */ OO.ui.ButtonWidget.prototype.updateHref = function () { if ( this.href !== null && !this.isDisabled() ) { this.$button.attr( 'href', this.href ); } else { this.$button.removeAttr( 'href' ); } return this; }; /** * Handle disable events. * * @private * @param {boolean} disabled Element is disabled */ OO.ui.ButtonWidget.prototype.onDisable = function () { this.updateHref(); }; /** * Set hyperlink target. * * @param {string|null} target Hyperlink target, null to remove */ OO.ui.ButtonWidget.prototype.setTarget = function ( target ) { target = typeof target === 'string' ? target : null; if ( target !== this.target ) { this.target = target; if ( target !== null ) { this.$button.attr( 'target', target ); } else { this.$button.removeAttr( 'target' ); } } return this; }; /** * Set search engine traversal hint. * * @param {boolean} noFollow True if search engines should avoid traversing this hyperlink */ OO.ui.ButtonWidget.prototype.setNoFollow = function ( noFollow ) { noFollow = typeof noFollow === 'boolean' ? noFollow : true; if ( noFollow !== this.noFollow ) { this.noFollow = noFollow; if ( noFollow ) { this.$button.attr( 'rel', 'nofollow' ); } else { this.$button.removeAttr( 'rel' ); } } return this; };