Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/extensions/VisualEditor/lib/ve/src/ui/ve.ui.Surface.js
Ðазад
/*! * VisualEditor UserInterface Surface class. * * @copyright See AUTHORS.txt */ /** * A surface is a top-level object which contains both a surface model and a surface view. * * @class * @abstract * @extends OO.ui.Widget * * @constructor * @param {ve.init.Target} target Target the surface belongs to * @param {HTMLDocument|Array|ve.dm.ElementLinearData|ve.dm.Document|ve.dm.Surface} dataOrDocOrSurface Document data, document model, or surface model to edit * @param {Object} [config] Configuration options * @param {ve.dm.BranchNode} [config.attachedRoot] Node to surface, if ve.dm.Document passed in * @param {string} config.mode Editing mode, either "visual" or "source" * @param {jQuery} [config.$scrollContainer] The scroll container of the surface * @param {jQuery} [config.$scrollListener] The scroll listener of the surface * @param {jQuery} [config.$overlayContainer] Clipping container for local overlays, defaults to surface view * @param {number} [config.overlayPadding] Padding beween local overlays and clipping container * @param {ve.ui.CommandRegistry} [config.commandRegistry] Command registry to use * @param {ve.ui.SequenceRegistry} [config.sequenceRegistry] Sequence registry to use * @param {ve.ui.DataTransferHandlerFactory} [config.dataTransferHandlerFactory] Data transfer handler factory to use * @param {string[]|null} [config.includeCommands] List of commands to include, null for all registered commands * @param {string[]} [config.excludeCommands] List of commands to exclude * @param {Object} [config.importRules={}] Import rules * @param {boolean} [config.multiline=true] Multi-line surface * @param {string} [config.placeholder] Placeholder text to display when the surface is empty * @param {string} [config.readOnly=false] Surface is read-only * @param {string} [config.nullSelectionOnBlur=true] Surface selection is set to null on blur * @param {string} [config.inDialog=''] The name of the dialog this surface is in * @param {boolean} [config.inTargetWidget=false] The surface is in a target widget */ ve.ui.Surface = function VeUiSurface( target, dataOrDocOrSurface, config ) { config = config || {}; // Parent constructor ve.ui.Surface.super.call( this, config ); // Properties this.target = target; this.$scrollContainer = config.$scrollContainer || $( this.getClosestScrollableElementContainer() ); this.$scrollListener = config.$scrollListener || $( this.getElementWindow() ); this.inDialog = config.inDialog || ''; this.inTargetWidget = !!config.inTargetWidget; this.mode = config.mode; // The following classes are used here: // * ve-ui-overlay-global-mobile // * ve-ui-overlay-global-desktop this.globalOverlay = new ve.ui.Overlay( { classes: [ 've-ui-overlay-global', 've-ui-overlay-global-' + ( OO.ui.isMobile() ? 'mobile' : 'desktop' ) ] } ); this.localOverlay = new ve.ui.Overlay( { classes: [ 've-ui-overlay-local' ] } ); this.$selections = $( '<div>' ).addClass( 've-ui-surface-selections' ); this.$blockers = $( '<div>' ); this.$controls = $( '<div>' ); this.$menus = $( '<div>' ); this.$placeholder = $( '<div>' ).addClass( 've-ui-surface-placeholder' ); this.commandRegistry = config.commandRegistry || ve.ui.commandRegistry; this.sequenceRegistry = config.sequenceRegistry || ve.ui.sequenceRegistry; this.dataTransferHandlerFactory = config.dataTransferHandlerFactory || ve.ui.dataTransferHandlerFactory; this.commands = OO.simpleArrayDifference( config.includeCommands || this.commandRegistry.getNames(), config.excludeCommands || [] ); this.triggerListener = new ve.TriggerListener( this.commands, this.commandRegistry ); if ( dataOrDocOrSurface instanceof ve.dm.Surface ) { this.model = dataOrDocOrSurface; } else { let documentModel; if ( dataOrDocOrSurface instanceof ve.dm.Document ) { // ve.dm.Document documentModel = dataOrDocOrSurface; } else if ( dataOrDocOrSurface instanceof ve.dm.ElementLinearData || Array.isArray( dataOrDocOrSurface ) ) { // LinearData or raw linear data documentModel = new ve.dm.Document( dataOrDocOrSurface ); } else { // HTMLDocument documentModel = ve.dm.converter.getModelFromDom( dataOrDocOrSurface ); } this.model = this.createModel( documentModel, config.attachedRoot ); } this.view = this.createView( this.model ); this.dialogs = this.createDialogWindowManager(); this.importRules = config.importRules || {}; this.multiline = config.multiline !== false; this.context = this.createContext( { $popupContainer: config.$overlayContainer, popupPadding: config.overlayPadding } ); this.progresses = []; this.showProgressDebounced = ve.debounce( this.showProgress.bind( this ) ); this.scrollSelectionIntoViewDebounced = ve.debounce( this.scrollSelectionIntoView.bind( this ), 500 ); this.debugBar = null; this.placeholder = null; this.placeholderVisible = false; this.setPlaceholder( config.placeholder ); this.setReadOnly( !!config.readOnly ); this.nullSelectionOnBlur = config.nullSelectionOnBlur !== false; this.completion = new ve.ui.CompletionWidget( this ); // Deprecated, use this.padding.top this.toolbarHeight = 0; this.padding = { top: 0, right: 0, bottom: 0, left: 0 }; // Intiailised on first use this.toolbarDialogs = {}; // Events this.getModel().connect( this, { select: 'onModelSelect', blur: 'onModelBlur', focus: 'onModelFocus' } ); this.getModel().getDocument().connect( this, { transact: 'onDocumentTransact' } ); this.getView().connect( this, { position: 'onViewPosition', activation: 'onViewActivation' } ); this.getContext().connect( this, { resize: ve.debounce( this.onContextResize.bind( this ) ) } ); // Initialization if ( OO.ui.isMobile() ) { // Mobile context is almost fullscreen and must appear on top of other elements (T308716) this.globalOverlay.$element.append( this.context.$element ); } else { this.$menus.append( this.context.$element ); } this.$menus.append( this.completion.$element ); this.$element // The following classes are used here: // * ve-ui-surface-visual // * ve-ui-surface-source .addClass( 've-ui-surface ve-ui-surface-' + this.mode ) .append( this.view.$element ); if ( this.mode === 'source' ) { // Separate class to make it easier to override this.getView().$element.add( this.$placeholder ) .addClass( 've-ui-surface-source-font' ); } this.view.$element.after( this.localOverlay.$element ); this.localOverlay.$element.append( this.$selections, this.$blockers, this.$controls, this.$menus ); this.globalOverlay.$element.append( this.dialogs.$element ); }; /* Inheritance */ OO.inheritClass( ve.ui.Surface, OO.ui.Widget ); /* Events */ /** * When a surface has been initialized * * @event ve.ui.Surface#ready */ /** * When a surface is destroyed. * * @event ve.ui.Surface#destroy */ /** * The surface was scrolled programmatically * as a result of a native selection change * * @event ve.ui.Surface#scroll */ /** * The surface has been submitted by user action, e.g. Ctrl+Enter * * @event ve.ui.Surface#submit */ /** * The surface has been cancelled by user action, e.g. Escape * * @event ve.ui.Surface#cancel */ /** * The surface read-only state has changed * * @event ve.ui.Surface#readOnly * @param {boolean} readOnly The surface is read-only */ /* Methods */ /** * Destroy the surface, releasing all memory and removing all DOM elements. * * @return {ve.ui.Surface} * @chainable * @fires ve.ui.Surface#destroy */ ve.ui.Surface.prototype.destroy = function () { // Destroy the ce.Surface, the ui.Context and window managers this.context.destroy(); this.dialogs.destroy(); for ( const side in this.toolbarDialogs ) { this.toolbarDialogs[ side ].destroy(); } this.view.destroy(); if ( this.debugBar ) { this.debugBar.destroy(); } // Disconnect events this.dialogs.disconnect( this ); this.context.getInspectors().disconnect( this ); // Remove DOM elements this.$element.remove(); this.globalOverlay.$element.remove(); // Let others know we have been destroyed this.emit( 'destroy' ); return this; }; /** * Initialize surface. * * This must be called after the surface has been attached to the DOM. * * @return {ve.ui.Surface} * @chainable * @fires ve.ui.Surface#ready */ ve.ui.Surface.prototype.initialize = function () { $( OO.ui.getTeleportTarget() ).append( this.globalOverlay.$element ); if ( ve.debug ) { this.setupDebugBar(); } // The following classes are used here: // * ve-ui-surface-dir-ltr // * ve-ui-surface-dir-rtl this.$element.addClass( 've-ui-surface-dir-' + this.getDir() ); this.getView().initialize(); this.getModel().initialize(); this.emit( 'ready' ); return this; }; /** * Get the target the surface belongs to * * @return {ve.init.Target} */ ve.ui.Surface.prototype.getTarget = function () { return this.target; }; /** * Get the DOM representation of the surface's current state. * * @return {HTMLDocument|string} HTML document (visual mode) or text (source mode) */ ve.ui.Surface.prototype.getDom = function () { return this.getModel().getDom(); }; /** * Get the HTML representation of the surface's current state. * * @return {string} HTML */ ve.ui.Surface.prototype.getHtml = function () { return this.getModel().getHtml(); }; /** * Get the surface's editing mode * * @return {string} Editing mode */ ve.ui.Surface.prototype.getMode = function () { return this.mode; }; /** * Create a context. * * @param {Object} config Configuration options * @return {ve.ui.LinearContext} */ ve.ui.Surface.prototype.createContext = function ( config ) { return OO.ui.isMobile() ? new ve.ui.MobileContext( this, config ) : new ve.ui.DesktopContext( this, config ); }; /** * Create a dialog window manager. * * @return {ve.ui.WindowManager} Dialog window manager */ ve.ui.Surface.prototype.createDialogWindowManager = function () { return OO.ui.isMobile() ? new ve.ui.MobileWindowManager( this, { factory: ve.ui.windowFactory, overlay: this.globalOverlay } ) : new ve.ui.SurfaceWindowManager( this, { factory: ve.ui.windowFactory } ); }; /** * Create a surface model * * @param {ve.dm.Document} doc Document model * @param {ve.dm.BranchNode} [attachedRoot] Node to surface * @return {ve.dm.Surface} Surface model */ ve.ui.Surface.prototype.createModel = function ( doc, attachedRoot ) { return new ve.dm.Surface( doc, attachedRoot, { sourceMode: this.getMode() === 'source' } ); }; /** * Create a surface view * * @param {ve.dm.Surface} model Surface model * @return {ve.ce.Surface} Surface view */ ve.ui.Surface.prototype.createView = function ( model ) { return new ve.ce.Surface( model, this ); }; /** * Set up the debug bar and insert it into the DOM. */ ve.ui.Surface.prototype.setupDebugBar = function () { this.debugBar = new ve.ui.DebugBar( this ); this.$element.append( this.debugBar.$element ); }; /** * Get the bounding rectangle of the surface, relative to the viewport. * * @return {Object|null} Object with top, bottom, left, right, width and height properties. * Null if the surface is not attached. */ ve.ui.Surface.prototype.getBoundingClientRect = function () { // We would use getBoundingClientRect(), but in iOS7 that's relative to the // document rather than to the viewport return this.$element[ 0 ].getClientRects()[ 0 ] || null; }; /** * Get vertical measurements of the visible area of the surface viewport * * @return {Object|null} Object with top, left, bottom, and height properties. Null if the surface is not attached. */ ve.ui.Surface.prototype.getViewportDimensions = function () { const rect = this.getBoundingClientRect(); if ( !rect ) { return null; } const top = Math.max( this.getPadding().top - rect.top, 0 ); const bottom = $( this.getElementWindow() ).height() - rect.top; return { top: top, left: rect.left, bottom: bottom, height: bottom - top }; }; /** * Get the surface model. * * @return {ve.dm.Surface} Surface model */ ve.ui.Surface.prototype.getModel = function () { return this.model; }; /** * Get the surface view. * * @return {ve.ce.Surface} Surface view */ ve.ui.Surface.prototype.getView = function () { return this.view; }; /** * Get the context menu. * * @return {ve.ui.LinearContext} Context user interface */ ve.ui.Surface.prototype.getContext = function () { return this.context; }; /** * Get dialogs window set. * * @return {ve.ui.WindowManager} Dialogs window set */ ve.ui.Surface.prototype.getDialogs = function () { return this.dialogs; }; /** * Get toolbar dialogs window set. * * @param {string} [position='side'] Get the toolbar dialogs window set for a specific position * @return {ve.ui.WindowManager} Toolbar dialogs window set */ ve.ui.Surface.prototype.getToolbarDialogs = function ( position ) { position = position || 'side'; this.toolbarDialogs[ position ] = this.toolbarDialogs[ position ] || new ve.ui.ToolbarDialogWindowManager( this, { factory: ve.ui.windowFactory, modal: false } ); return this.toolbarDialogs[ position ]; }; /** * Get the local overlay. * * Local overlays are attached to the same frame as the surface. * * @return {ve.ui.Overlay} Local overlay */ ve.ui.Surface.prototype.getLocalOverlay = function () { return this.localOverlay; }; /** * Get the global overlay. * * Global overlays are attached to the top-most frame. * * @return {ve.ui.Overlay} Global overlay */ ve.ui.Surface.prototype.getGlobalOverlay = function () { return this.globalOverlay; }; /** * @inheritdoc */ ve.ui.Surface.prototype.setDisabled = function ( disabled ) { if ( disabled ) { OO.ui.warnDeprecation( 'Surfaces can\'t be disabled, only set to readOnly' ); } }; /** * Set the read-only state of the surface * * @param {boolean} readOnly Make surface read-only * @fires ve.ui.Surface#readOnly */ ve.ui.Surface.prototype.setReadOnly = function ( readOnly ) { this.readOnly = !!readOnly; this.model.setReadOnly( readOnly ); this.view.setReadOnly( readOnly ); this.emit( 'readOnly', readOnly ); }; /** * Check if the surface is read-only * * @return {boolean} */ ve.ui.Surface.prototype.isReadOnly = function () { return this.readOnly; }; /** * Give focus to the surface */ ve.ui.Surface.prototype.focus = function () { this.getView().focus(); }; /** * Handle transact events from the document model * * @param {ve.dm.Transaction} Transaction */ ve.ui.Surface.prototype.onDocumentTransact = function () { if ( this.placeholder ) { this.updatePlaceholder(); } }; /** * Handle select events from the model */ ve.ui.Surface.prototype.onModelSelect = function () { // eslint-disable-next-line no-bitwise if ( this.getView().dragging ^ OO.ui.isMobile() ) { // Allow native scroll behavior while dragging, as the start/end // points are unreliable until we're finished. Without this, trying to // drag a selection larger than a single screen will sometimes lock // the viewport in place, as it tries to keep the wrong end of the // selection on-screen. // On mobile the dragging flag is essentially reversed in meaning, as // it is set during mouse down, which happens when you are tapping // to select, but when you drag selection handles no mousedown event // occurs (or any event other 'selectionchange') so the flag is unset. return; } const synchronizer = this.getModel().synchronizer; // Don't scroll to this user's cursor due to another user's changes being applied if ( !( synchronizer && synchronizer.applying ) ) { this.scrollSelectionIntoViewDebounced(); } }; /** * Scroll the selection into view * * Called in response to selection events. * * This is done for all selections, even native ones, to account * for the extra padding of the floating toolbar. * * @param {ve.dm.Selection} [selectionModel] Optional selection model, defaults to current selection * @param {Object} [scrollConfig] Scroll config options, passed to ve.scrollIntoView * @fires ve.ui.Surface#scroll */ ve.ui.Surface.prototype.scrollSelectionIntoView = function ( selectionModel, scrollConfig ) { selectionModel = selectionModel || this.getModel().getSelection(); const view = this.getView(), selectionView = view.getSelection( selectionModel ), isNative = selectionView.isNativeCursor(); // We only care about the focus end of the selection, the anchor never // moves and should be allowed off screen. let clientRect = selectionView.getSelectionFocusRect(); const surfaceRect = this.getBoundingClientRect(); if ( !clientRect || !surfaceRect ) { return; } // We want viewport-relative coordinates, so we need to translate it clientRect = ve.translateRect( clientRect, surfaceRect.left, surfaceRect.top ); const padding = ve.copy( this.getPadding() ); let animate = true; if ( isNative ) { animate = false; if ( OO.ui.isMobile() && !selectionModel.isCollapsed() ) { const profile = $.client.profile(); // Assume that if the selection has been expanded, then a context menu is visible // above the selection. We don't want this to obscure the toolbar so add on an // estimate of its height. // Previously we applied this fix to iOS, even though scrolling closed the context, // because the user could touch the selection to re-open it. However sometime between // iOS 12 and 12.3, scrolling stopped closing the context, but it doesn't move it either, // so this fix became useless. // Older versions of Android draw the context menu in the address bar and so // don't need to be fixed. if ( profile.name === 'android' && profile.versionNumber >= 6 ) { padding.top += 60; } // Also assume there are selection handles below on Android. (T204718) if ( profile.name === 'android' || profile.name === 'firefox' ) { padding.bottom += 30; } } } else { // Don't attempt to scroll non-native selections into view if they // are taller than the viewport (T305862). const viewportDimensions = this.getViewportDimensions(); if ( clientRect.height > viewportDimensions.height ) { return; } } // Add some minimum padding so the selection doesn't touch the edge of the viewport padding.top += 5; padding.bottom += 5; padding.left += 5; padding.right += 5; ve.scrollIntoView( clientRect, ve.extendObject( { animate: animate, scrollContainer: this.$scrollContainer[ 0 ], padding: padding }, scrollConfig ) ).then( () => { if ( isNative ) { // TODO: This event has only even been emitted for native selection // scroll changes. Perhaps rename it. this.emit( 'scroll' ); } } ); }; // Deprecated alias ve.ui.Surface.prototype.scrollCursorIntoView = ve.ui.Surface.prototype.scrollSelectionIntoView; /** * Set placeholder text * * @param {string} [placeholder] Placeholder text, clears placeholder if not set */ ve.ui.Surface.prototype.setPlaceholder = function ( placeholder ) { this.placeholder = placeholder; if ( this.placeholder ) { this.$placeholder.prependTo( this.$element ); this.updatePlaceholder(); const documentView = this.getView().getDocument(); this.$placeholder.prop( { dir: documentView.getDir(), lang: documentView.getLang() } ); } else { this.$placeholder.detach(); this.placeholderVisible = false; this.getView().$element.css( 'min-height', '' ); } this.getView().attachedRoot.$element.attr( 'aria-label', this.placeholder || null ); }; /** * Update placeholder rendering */ ve.ui.Surface.prototype.updatePlaceholder = function () { const hasContent = this.getModel().getDocument().data.hasContent(); this.$placeholder.toggleClass( 'oo-ui-element-hidden', hasContent ); this.placeholderVisible = !hasContent; if ( !hasContent ) { // Use a clone of the first node in the document so the placeholder // styling matches the text the users sees when they start typing const firstNode = this.getView().attachedRoot.children[ 0 ]; let $wrapper; if ( firstNode ) { $wrapper = firstNode.$element.clone(); if ( ve.debug ) { // In debug mode a background colour from the render animation may be present $wrapper.removeAttr( 'style' ); } } else { $wrapper = $( '<p>' ); } this.$placeholder.empty().append( $wrapper.text( this.placeholder ) ); } else { this.getView().$element.css( 'min-height', '' ); } }; /** * Handle position events from the view * * @param {boolean} [wasSynchronizing] */ ve.ui.Surface.prototype.onViewPosition = function ( wasSynchronizing ) { const padding = {}; for ( const side in this.toolbarDialogs ) { ve.extendObject( padding, this.toolbarDialogs[ side ].getSurfacePadding() ); } if ( Object.keys( padding ).length ) { this.setPadding( padding ); this.adjustVisiblePadding(); // Don't scroll to this user's cursor due to another user's changes being applied if ( !wasSynchronizing ) { this.scrollSelectionIntoView(); } } if ( this.placeholderVisible ) { this.getView().$element.css( 'min-height', this.$placeholder.outerHeight() ); } }; /** * Get list of commands available on this surface. * * @return {string[]} Commands */ ve.ui.Surface.prototype.getCommands = function () { return this.commands; }; /** * Execute an action or command * * This is a compatability wrapper for executeCommandWithSource. * * @param {ve.ui.Trigger|string} triggerOrAction Trigger or symbolic name of action * @param {string} [method] Action method name * @param {...any} [args] Additional arguments for action * @return {boolean} Action or command was executed */ ve.ui.Surface.prototype.execute = function ( triggerOrAction, method, ...args ) { return this.executeWithSource( triggerOrAction, method, false, ...args ); }; /** * Execute an action or command * * @param {ve.ui.Trigger|string} triggerOrAction Trigger or symbolic name of action * @param {string} [method] Action method name * @param {string} [source] Action source, for logging * @param {...any} [args] Additional arguments for action * @return {boolean} Action or command was executed */ ve.ui.Surface.prototype.executeWithSource = function ( triggerOrAction, method, source, ...args ) { if ( triggerOrAction instanceof ve.ui.Trigger ) { const command = this.triggerListener.getCommandByTrigger( triggerOrAction.toString() ); if ( command ) { // Have command call execute with action arguments return command.execute( this, false, source ); } } else if ( typeof triggerOrAction === 'string' && typeof method === 'string' ) { // Validate method if ( ve.ui.actionFactory.doesActionSupportMethod( triggerOrAction, method ) ) { // Create an action object and execute the method on it const obj = ve.ui.actionFactory.create( triggerOrAction, this, source ); const ret = obj[ method ]( ...args ); return ret === undefined || !!ret; } } return false; }; /** * Execute a command by name * * @param {string} commandName Command name * @return {boolean} The command was executed */ ve.ui.Surface.prototype.executeCommand = function ( commandName ) { const command = this.commandRegistry.lookup( commandName ); if ( command ) { return command.execute( this ); } return false; }; // Deprecated, use #setPadding ve.ui.Surface.prototype.setToolbarHeight = function ( toolbarHeight ) { this.setPadding( { top: toolbarHeight } ); }; /** * @typedef {Object} Padding * @memberof ve.ui.Surface * @property {number} [top] Top padding * @property {number} [right] Right padding * @property {number} [bottom] Bottom padding * @property {number} [left] Left padding */ /** * Set content area padding. * * When UI components obscure the surface (e.g. the toolbar), * set the appropriate amount of padding here so that * scroll-into-view calculations can be adjusted. * * @param {ve.ui.Surface.Padding} padding Padding object. Omit properties to leave unchanged. */ ve.ui.Surface.prototype.setPadding = function ( padding ) { ve.extendObject( this.padding, padding ); // Deprecated, use this.padding.top this.toolbarHeight = this.padding.top; }; /** * Get the current content area padding * * Padding in this context means areas of the surface which are * rendered but are obsured by some other UI element, e.g. a * floating toolbar (but not a static toolbar). * * This can be used when deciding how to position other floating * UI elements, e.g. to avoid rendering a context menu under * a floating toolbar. * * @return {ve.ui.Surface.Padding} */ ve.ui.Surface.prototype.getPadding = function () { return this.padding; }; /** * Handle resize events from the context */ ve.ui.Surface.prototype.onContextResize = function () { const padding = this.context.getSurfacePadding(); if ( padding ) { this.setPadding( padding ); this.adjustVisiblePadding(); this.scrollSelectionIntoView(); } }; /** * Handle surface model blur events */ ve.ui.Surface.prototype.onModelBlur = function () { this.adjustVisiblePadding(); }; /** * Handle surface model focus events */ ve.ui.Surface.prototype.onModelFocus = function () { this.adjustVisiblePadding(); }; /** * Handle surface view activation events */ ve.ui.Surface.prototype.onViewActivation = function () { this.adjustVisiblePadding(); }; /** * Adjust visible padding on the surface to allow the whole document * to be scrolled to. */ ve.ui.Surface.prototype.adjustVisiblePadding = function () { if ( OO.ui.isMobile() && !this.inTargetWidget ) { const keyboardShown = this.getView().hasNativeCursorSelection(); let bottom; if ( ve.init.platform.constructor.static.isIos() && keyboardShown ) { // iOS needs a whole extra page of padding when the virtual keyboard is shown. // Note: we keep this padding when surface is deactivated-but-shown-as-activated // so that the view doesn't shift when e.g. opening a toolbar toolgroup popup. bottom = $( window ).height() - this.getPadding().top; } else { // otherwise just add padding to account for the context bottom = this.getPadding().bottom; } this.getView().$attachedRootNode.css( 'padding-bottom', bottom ); this.scrollSelectionIntoView(); } }; /** * Create a progress bar in the progress dialog * * @param {jQuery.Promise} progressCompletePromise Promise which resolves when the progress action is complete * @param {jQuery|string|Function} label Progress bar label * @param {boolean} nonCancellable Progress item can't be cancelled * @return {jQuery.Promise} Promise which resolves with a progress bar widget and fails if cancelled */ ve.ui.Surface.prototype.createProgress = function ( progressCompletePromise, label, nonCancellable ) { const progressBarDeferred = ve.createDeferred(); this.progresses.push( { label: label, cancellable: !nonCancellable, progressCompletePromise: progressCompletePromise, progressBarDeferred: progressBarDeferred } ); this.showProgressDebounced(); return progressBarDeferred.promise(); }; ve.ui.Surface.prototype.showProgress = function () { const progresses = this.progresses; this.dialogs.openWindow( 'progress', { progresses: progresses, $returnFocusTo: null } ); this.progresses = []; }; /** * Get sanitization rules for rich paste * * @return {Object} Import rules */ ve.ui.Surface.prototype.getImportRules = function () { return this.importRules; }; /** * Check if the surface is multi-line * * @return {boolean} Surface is multi-line */ ve.ui.Surface.prototype.isMultiline = function () { return this.multiline; }; /** * Surface 'dir' property (GUI/User-Level Direction) * * @return {string} 'ltr' or 'rtl' */ ve.ui.Surface.prototype.getDir = function () { return this.$element.css( 'direction' ); }; /** * Get the name of the dialog this surface is in * * @return {string} The name of the dialog this surface is in */ ve.ui.Surface.prototype.getInDialog = function () { return this.inDialog; };
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка