From 640638b1dc66cf3b9af1f03775a00db5b4471692 Mon Sep 17 00:00:00 2001 From: Ed Sanders Date: Mon, 20 Dec 2021 15:58:01 +0000 Subject: [PATCH] ReplyWidget: Document all methods Change-Id: Iab509a7605c3b8e25bcc20fb7176fed23409aed4 --- modules/dt.ui.ReplyWidget.js | 58 +++++++++++++++++++++++++++++- modules/dt.ui.ReplyWidgetPlain.js | 29 ++++++++++++++- modules/dt.ui.ReplyWidgetVisual.js | 27 +++++++++++++- 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/modules/dt.ui.ReplyWidget.js b/modules/dt.ui.ReplyWidget.js index ea3ac7e7a..757a89fe1 100644 --- a/modules/dt.ui.ReplyWidget.js +++ b/modules/dt.ui.ReplyWidget.js @@ -274,6 +274,14 @@ OO.inheritClass( ReplyWidget, OO.ui.Widget ); /* Methods */ +/** + * Create the widget for the reply body + * + * The body widget should implement #setReadOnly, #pushPending and #popPending + * + * @method + * @return {OO.ui.Widget} + */ ReplyWidget.prototype.createReplyBodyWidget = null; /** @@ -285,10 +293,28 @@ ReplyWidget.prototype.createReplyBodyWidget = null; */ ReplyWidget.prototype.focus = null; +/** + * Get value of reply body, HTML or wikitext + * + * @method + * @return {string} + */ ReplyWidget.prototype.getValue = null; +/** + * Check if the reply widget is empy + * + * @method + * @return {boolean} + */ ReplyWidget.prototype.isEmpty = null; +/** + * Get the current input mode of the reply widget, 'source' or 'visual' + * + * @method + * @return {string} + */ ReplyWidget.prototype.getMode = null; /** @@ -518,6 +544,9 @@ ReplyWidget.prototype.setup = function ( data ) { return this; }; +/** + * Perform additional actions once the widget has been setup as is ready for input + */ ReplyWidget.prototype.afterSetup = function () { // Init preview and button state this.onInputChange(); @@ -602,6 +631,12 @@ ReplyWidget.prototype.teardown = function ( abandoned ) { return this; }; +/** + * Handle changes to the watch state of the page + * + * @param {jQuery.Event} e Event + * @param {string} actionPerformed Watch action taken + */ ReplyWidget.prototype.onWatchToggle = function ( e, actionPerformed ) { var widget = this; this.checkboxesPromise.then( function ( checkboxes ) { @@ -615,6 +650,13 @@ ReplyWidget.prototype.onWatchToggle = function ( e, actionPerformed ) { } ); }; +/** + * Handle key down events anywhere in the reply widget + * + * @param {boolean} isMultiline The current input is multiline + * @param {jQuery.Event} e Key down event + * @return {boolean} Return false to prevent default event + */ ReplyWidget.prototype.onKeyDown = function ( isMultiline, e ) { if ( e.which === OO.ui.Keys.ESCAPE ) { this.tryTeardown(); @@ -629,6 +671,9 @@ ReplyWidget.prototype.onKeyDown = function ( isMultiline, e ) { } }; +/** + * Handle input change events anywhere in the reply widget + */ ReplyWidget.prototype.onInputChange = function () { this.updateButtons(); this.storage.set( this.storagePrefix + '/saveable', this.isEmpty() ? '' : '1' ); @@ -715,11 +760,19 @@ ReplyWidget.prototype.preparePreview = function ( wikitext ) { } ); }; +/** + * Update buttons when widget state has changed + */ ReplyWidget.prototype.updateButtons = function () { this.replyButton.setDisabled( this.isEmpty() ); }; -ReplyWidget.prototype.onFirstTransaction = function () { +/** + * Handle the first change in the reply widget + * + * Currently only the first change in the body, used for logging. + */ +ReplyWidget.prototype.onFirstChange = function () { logger( { action: 'firstChange' } ); }; @@ -771,6 +824,9 @@ ReplyWidget.prototype.onUnload = function () { } ); }; +/** + * Handle clicks on the reply button + */ ReplyWidget.prototype.onReplyClick = function () { var widget = this; diff --git a/modules/dt.ui.ReplyWidgetPlain.js b/modules/dt.ui.ReplyWidgetPlain.js index d112ddbdd..ca6d1fe74 100644 --- a/modules/dt.ui.ReplyWidgetPlain.js +++ b/modules/dt.ui.ReplyWidgetPlain.js @@ -55,6 +55,9 @@ OO.inheritClass( ReplyWidgetPlain, require( 'ext.discussionTools.ReplyWidget' ) /* Methods */ +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.createReplyBodyWidget = function ( config ) { var textInput = new OO.ui.MultilineTextInputWidget( $.extend( { rows: 3, @@ -74,12 +77,18 @@ ReplyWidgetPlain.prototype.createReplyBodyWidget = function ( config ) { return textInput; }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.focus = function () { this.replyBodyWidget.focus(); return this; }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.clear = function () { this.replyBodyWidget.setValue( '' ); @@ -89,14 +98,23 @@ ReplyWidgetPlain.prototype.clear = function () { ReplyWidgetPlain.super.prototype.clear.apply( this, arguments ); }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.isEmpty = function () { return utils.htmlTrim( this.replyBodyWidget.getValue() ) === ''; }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.getMode = function () { return 'source'; }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.onInputChange = function () { // Parent method ReplyWidgetPlain.super.prototype.onInputChange.apply( this, arguments ); @@ -105,6 +123,9 @@ ReplyWidgetPlain.prototype.onInputChange = function () { this.storage.set( this.storagePrefix + '/body', wikitext ); }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.setup = function ( data ) { var autosaveValue = this.storage.get( this.storagePrefix + '/body' ); @@ -120,13 +141,16 @@ ReplyWidgetPlain.prototype.setup = function ( data ) { this.replyBodyWidget.setValue( data.value || autosaveValue ); // needs to bind after the initial setValue: - this.replyBodyWidget.once( 'change', this.onFirstTransaction.bind( this ) ); + this.replyBodyWidget.once( 'change', this.onFirstChange.bind( this ) ); this.afterSetup(); return this; }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.teardown = function () { this.replyBodyWidget.disconnect( this ); this.replyBodyWidget.off( 'change' ); @@ -135,6 +159,9 @@ ReplyWidgetPlain.prototype.teardown = function () { return ReplyWidgetPlain.super.prototype.teardown.call( this ); }; +/** + * @inheritdoc + */ ReplyWidgetPlain.prototype.getValue = function () { return this.replyBodyWidget.getValue(); }; diff --git a/modules/dt.ui.ReplyWidgetVisual.js b/modules/dt.ui.ReplyWidgetVisual.js index 5baa66708..e2ad0c648 100644 --- a/modules/dt.ui.ReplyWidgetVisual.js +++ b/modules/dt.ui.ReplyWidgetVisual.js @@ -18,6 +18,7 @@ require( './dt-ve/dt.ce.PingNode.js' ); * @param {CommentItem} comment * @param {CommentDetails} commentDetails * @param {Object} [config] + * @param {string} [config.mode] Default edit mode, 'source' or 'visual' */ function ReplyWidgetVisual( commentController, comment, commentDetails, config ) { this.defaultMode = config.mode; @@ -35,12 +36,18 @@ OO.inheritClass( ReplyWidgetVisual, require( 'ext.discussionTools.ReplyWidget' ) /* Methods */ +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.createReplyBodyWidget = function ( config ) { return new CommentTargetWidget( this, $.extend( { defaultMode: this.defaultMode }, config ) ); }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.getValue = function () { if ( this.getMode() === 'source' ) { return this.replyBodyWidget.target.getSurface().getModel().getDom(); @@ -49,6 +56,9 @@ ReplyWidgetVisual.prototype.getValue = function () { } }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.clear = function () { this.replyBodyWidget.clear(); @@ -58,17 +68,26 @@ ReplyWidgetVisual.prototype.clear = function () { ReplyWidgetVisual.super.prototype.clear.apply( this, arguments ); }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.isEmpty = function () { var surface = this.replyBodyWidget.target.getSurface(); return !( surface && surface.getModel().getDocument().data.hasContent() ); }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.getMode = function () { return this.replyBodyWidget.target.getSurface() ? this.replyBodyWidget.target.getSurface().getMode() : this.defaultMode; }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.setup = function ( data ) { var widget = this, target = this.replyBodyWidget.target; @@ -98,7 +117,7 @@ ReplyWidgetVisual.prototype.setup = function ( data ) { widget.afterSetup(); // This needs to bind after surfaceReady so any initial population doesn't trigger it early: - widget.replyBodyWidget.once( 'change', widget.onFirstTransaction.bind( widget ) ); + widget.replyBodyWidget.once( 'change', widget.onFirstChange.bind( widget ) ); } ); // Parent method @@ -113,6 +132,9 @@ ReplyWidgetVisual.prototype.setup = function ( data ) { return this; }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.teardown = function () { this.replyBodyWidget.disconnect( this ); this.replyBodyWidget.off( 'change' ); @@ -121,6 +143,9 @@ ReplyWidgetVisual.prototype.teardown = function () { return ReplyWidgetVisual.super.prototype.teardown.call( this ); }; +/** + * @inheritdoc + */ ReplyWidgetVisual.prototype.focus = function () { var targetWidget = this.replyBodyWidget; setTimeout( function () {