summaryrefslogtreecommitdiff
path: root/vendor/oojs/oojs-ui/src/elements/ButtonElement.js
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/oojs/oojs-ui/src/elements/ButtonElement.js')
-rw-r--r--vendor/oojs/oojs-ui/src/elements/ButtonElement.js263
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;
+};