diff options
Diffstat (limited to 'vendor/oojs/oojs-ui/src/elements/ButtonElement.js')
-rw-r--r-- | vendor/oojs/oojs-ui/src/elements/ButtonElement.js | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/vendor/oojs/oojs-ui/src/elements/ButtonElement.js b/vendor/oojs/oojs-ui/src/elements/ButtonElement.js new file mode 100644 index 00000000..6d338ed7 --- /dev/null +++ b/vendor/oojs/oojs-ui/src/elements/ButtonElement.js @@ -0,0 +1,263 @@ +/** + * ButtonElement is often mixed into other classes to generate a button, which is a clickable + * interface element that can be configured with access keys for accessibility. + * See the [OOjs UI documentation on MediaWiki] [1] for examples. + * + * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#Buttons + * @abstract + * @class + * + * @constructor + * @param {Object} [config] Configuration options + * @cfg {jQuery} [$button] The button element created by the class. + * If this configuration is omitted, the button element will use a generated `<a>`. + * @cfg {boolean} [framed=true] Render the button with a frame + * @cfg {string} [accessKey] Button's access key + */ +OO.ui.ButtonElement = function OoUiButtonElement( config ) { + // Configuration initialization + config = config || {}; + + // Properties + this.$button = null; + this.framed = null; + this.accessKey = null; + this.active = false; + this.onMouseUpHandler = this.onMouseUp.bind( this ); + this.onMouseDownHandler = this.onMouseDown.bind( this ); + this.onKeyDownHandler = this.onKeyDown.bind( this ); + this.onKeyUpHandler = this.onKeyUp.bind( this ); + this.onClickHandler = this.onClick.bind( this ); + this.onKeyPressHandler = this.onKeyPress.bind( this ); + + // Initialization + this.$element.addClass( 'oo-ui-buttonElement' ); + this.toggleFramed( config.framed === undefined || config.framed ); + this.setAccessKey( config.accessKey ); + this.setButtonElement( config.$button || $( '<a>' ) ); +}; + +/* Setup */ + +OO.initClass( OO.ui.ButtonElement ); + +/* Static Properties */ + +/** + * Cancel mouse down events. + * + * This property is usually set to `true` to prevent the focus from changing when the button is clicked. + * Classes such as {@link OO.ui.DraggableElement DraggableElement} and {@link OO.ui.ButtonOptionWidget ButtonOptionWidget} + * use a value of `false` so that dragging behavior is possible and mousedown events can be handled by a + * parent widget. + * + * @static + * @inheritable + * @property {boolean} + */ +OO.ui.ButtonElement.static.cancelButtonMouseDownEvents = true; + +/* Events */ + +/** + * A 'click' event is emitted when the button element is clicked. + * + * @event click + */ + +/* Methods */ + +/** + * Set the button element. + * + * This method is used to retarget a button mixin so that its functionality applies to + * the specified button element instead of the one created by the class. If a button element + * is already set, the method will remove the mixin’s effect on that element. + * + * @param {jQuery} $button Element to use as button + */ +OO.ui.ButtonElement.prototype.setButtonElement = function ( $button ) { + if ( this.$button ) { + this.$button + .removeClass( 'oo-ui-buttonElement-button' ) + .removeAttr( 'role accesskey' ) + .off( { + mousedown: this.onMouseDownHandler, + keydown: this.onKeyDownHandler, + click: this.onClickHandler, + keypress: this.onKeyPressHandler + } ); + } + + this.$button = $button + .addClass( 'oo-ui-buttonElement-button' ) + .attr( { role: 'button', accesskey: this.accessKey } ) + .on( { + mousedown: this.onMouseDownHandler, + keydown: this.onKeyDownHandler, + click: this.onClickHandler, + keypress: this.onKeyPressHandler + } ); +}; + +/** + * Handles mouse down events. + * + * @protected + * @param {jQuery.Event} e Mouse down event + */ +OO.ui.ButtonElement.prototype.onMouseDown = function ( e ) { + if ( this.isDisabled() || e.which !== 1 ) { + return; + } + this.$element.addClass( 'oo-ui-buttonElement-pressed' ); + // Run the mouseup handler no matter where the mouse is when the button is let go, so we can + // reliably remove the pressed class + this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true ); + // Prevent change of focus unless specifically configured otherwise + if ( this.constructor.static.cancelButtonMouseDownEvents ) { + return false; + } +}; + +/** + * Handles mouse up events. + * + * @protected + * @param {jQuery.Event} e Mouse up event + */ +OO.ui.ButtonElement.prototype.onMouseUp = function ( e ) { + if ( this.isDisabled() || e.which !== 1 ) { + return; + } + this.$element.removeClass( 'oo-ui-buttonElement-pressed' ); + // Stop listening for mouseup, since we only needed this once + this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true ); +}; + +/** + * Handles mouse click events. + * + * @protected + * @param {jQuery.Event} e Mouse click event + * @fires click + */ +OO.ui.ButtonElement.prototype.onClick = function ( e ) { + if ( !this.isDisabled() && e.which === 1 ) { + if ( this.emit( 'click' ) ) { + return false; + } + } +}; + +/** + * Handles key down events. + * + * @protected + * @param {jQuery.Event} e Key down event + */ +OO.ui.ButtonElement.prototype.onKeyDown = function ( e ) { + if ( this.isDisabled() || ( e.which !== OO.ui.Keys.SPACE && e.which !== OO.ui.Keys.ENTER ) ) { + return; + } + this.$element.addClass( 'oo-ui-buttonElement-pressed' ); + // Run the keyup handler no matter where the key is when the button is let go, so we can + // reliably remove the pressed class + this.getElementDocument().addEventListener( 'keyup', this.onKeyUpHandler, true ); +}; + +/** + * Handles key up events. + * + * @protected + * @param {jQuery.Event} e Key up event + */ +OO.ui.ButtonElement.prototype.onKeyUp = function ( e ) { + if ( this.isDisabled() || ( e.which !== OO.ui.Keys.SPACE && e.which !== OO.ui.Keys.ENTER ) ) { + return; + } + this.$element.removeClass( 'oo-ui-buttonElement-pressed' ); + // Stop listening for keyup, since we only needed this once + this.getElementDocument().removeEventListener( 'keyup', this.onKeyUpHandler, true ); +}; + +/** + * Handles key press events. + * + * @protected + * @param {jQuery.Event} e Key press event + * @fires click + */ +OO.ui.ButtonElement.prototype.onKeyPress = function ( e ) { + if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) { + if ( this.emit( 'click' ) ) { + return false; + } + } +}; + +/** + * Check if button has a frame. + * + * @return {boolean} Button is framed + */ +OO.ui.ButtonElement.prototype.isFramed = function () { + return this.framed; +}; + +/** + * Render the button with or without a frame. Omit the `framed` parameter to toggle the button frame on and off. + * + * @param {boolean} [framed] Make button framed, omit to toggle + * @chainable + */ +OO.ui.ButtonElement.prototype.toggleFramed = function ( framed ) { + framed = framed === undefined ? !this.framed : !!framed; + if ( framed !== this.framed ) { + this.framed = framed; + this.$element + .toggleClass( 'oo-ui-buttonElement-frameless', !framed ) + .toggleClass( 'oo-ui-buttonElement-framed', framed ); + this.updateThemeClasses(); + } + + return this; +}; + +/** + * Set the button's access key. + * + * @param {string} accessKey Button's access key, use empty string to remove + * @chainable + */ +OO.ui.ButtonElement.prototype.setAccessKey = function ( accessKey ) { + accessKey = typeof accessKey === 'string' && accessKey.length ? accessKey : null; + + if ( this.accessKey !== accessKey ) { + if ( this.$button ) { + if ( accessKey !== null ) { + this.$button.attr( 'accesskey', accessKey ); + } else { + this.$button.removeAttr( 'accesskey' ); + } + } + this.accessKey = accessKey; + } + + return this; +}; + +/** + * Set the button to its 'active' state. + * + * The active state occurs when a {@link OO.ui.ButtonOptionWidget ButtonOptionWidget} or + * a {@link OO.ui.ToggleButtonWidget ToggleButtonWidget} is pressed. This method does nothing + * for other button types. + * + * @param {boolean} [value] Make button active + * @chainable + */ +OO.ui.ButtonElement.prototype.setActive = function ( value ) { + this.$element.toggleClass( 'oo-ui-buttonElement-active', !!value ); + return this; +}; |