Mooeypoo has uploaded a new change for review. https://gerrit.wikimedia.org/r/82461
Change subject: [WIP] Creating StickeredNode ...................................................................... [WIP] Creating StickeredNode StickerNode and StickerWidget will be used as menus over the top of a block to give access to menu functionality and inspectors. This is mainly for LanguageBlockNode functionality but can later be used for tables as well. Change-Id: Id97c3840d26a39cb5f6b4cea7a89e89b05b45325 --- M VisualEditor.php M modules/ve/ce/nodes/ve.ce.LanguageBlockNode.js A modules/ve/ce/ve.ce.StickeredNode.js M modules/ve/ui/styles/ve.ui.Widget.css A modules/ve/ui/ve.ui.Sticker.js A modules/ve/ui/widgets/ve.ui.StickerWidget.js 6 files changed, 377 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/61/82461/1 diff --git a/VisualEditor.php b/VisualEditor.php index e39b4de..8fd65c2 100644 --- a/VisualEditor.php +++ b/VisualEditor.php @@ -727,6 +727,9 @@ 've/ui/tools/buttons/ve.ui.SubscriptButtonTool.js', 've/ui/tools/buttons/ve.ui.SuperscriptButtonTool.js', 've/ui/tools/buttons/ve.ui.UnderlineButtonTool.js', + 've/ce/ve.ce.StickeredNode.js', + 've/ui/ve.ui.Sticker.js', + 've/ui/widgets/ve.ui.StickerWidget.js', 've/ce/nodes/ve.ce.LanguageBlockNode.js', 've/dm/nodes/ve.dm.LanguageBlockNode.js', ), diff --git a/modules/ve/ce/nodes/ve.ce.LanguageBlockNode.js b/modules/ve/ce/nodes/ve.ce.LanguageBlockNode.js index e081f35..f0c5c90 100644 --- a/modules/ve/ce/nodes/ve.ce.LanguageBlockNode.js +++ b/modules/ve/ce/nodes/ve.ce.LanguageBlockNode.js @@ -21,6 +21,9 @@ // Events this.model.connect( this, { 'update': 'onUpdate' } ); + // Mixin constructors + ve.ce.StickeredNode.call( this ); + this.$.attr( 'lang', model.getAttribute( 'lang' ) ); this.$.attr( 'dir', model.getAttribute( 'dir' ) ); @@ -32,6 +35,8 @@ /* Inheritance */ ve.inheritClass( ve.ce.LanguageBlockNode, ve.ce.BranchNode ); + +ve.mixinClass( ve.ce.LanguageBlockNode, ve.ce.StickeredNode ); /* Static Properties */ @@ -55,7 +60,6 @@ this.$.attr( 'dir', this.model.getAttribute( 'dir' ) ); // this.updateTagName(); }; - /* Registration */ ve.ce.nodeFactory.register( ve.ce.LanguageBlockNode ); diff --git a/modules/ve/ce/ve.ce.StickeredNode.js b/modules/ve/ce/ve.ce.StickeredNode.js new file mode 100644 index 0000000..ff1fe7c --- /dev/null +++ b/modules/ve/ce/ve.ce.StickeredNode.js @@ -0,0 +1,48 @@ +/*! + * VisualEditor ContentEditable FocusableNode class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * ContentEditable stamped node. + * + * Node that pops a sticky menu at the top. + * + * @param {jQuery} [$stickered=this.$] description here + */ +ve.ce.StickeredNode = function VeCeStickeredNode( $stickered ) { + this.$stickered = $stickered || this.$; + + this.$stickered.addClass( 've-ce-stickeredNode' ); + + this.$stickered.on( 'mouseenter', ve.bind( this.onMouseEnter, this ) ); + this.$stickered.on( 'mouseleave', ve.bind( this.onMouseLeave, this ) ); + + this.surface = null; + this.sticker = null; + + this.focused = false; + // Events + this.connect( this, { + 'setup': 'onStickeredSetup', +/// 'resize': 'onFocusableResize', +// 'rerender': 'onFocusableRerender', +// 'live': 'onFocusableLive' + } ); +} + +ve.ce.StickeredNode.prototype.onStickeredSetup = function () { + this.surface = this.root.getSurface(); + // Create Sticker: + this.sticker = new ve.ui.Sticker( this.surface.getSurface(), { '$$': this.$$, '$stickeredNode': this.$ } ); + this.sticker.show( true ); +} + +ve.ce.StickeredNode.prototype.onMouseEnter = function () { + this.focused = true; +}; +ve.ce.StickeredNode.prototype.onMouseLeave = function () { + this.focused = false; +}; diff --git a/modules/ve/ui/styles/ve.ui.Widget.css b/modules/ve/ui/styles/ve.ui.Widget.css index 2bf8ef3..3c78f35 100644 --- a/modules/ve/ui/styles/ve.ui.Widget.css +++ b/modules/ve/ui/styles/ve.ui.Widget.css @@ -575,3 +575,15 @@ border-bottom-left-radius: 0; border-bottom-width: 0; } + +/* ve.ui.StickerWidget.js */ +.ve-ui-sticker, +.ve-ui-sticker-inspectors, +.ve-ui-sticker-menu { + position: absolute; +} + +.ve-ui-stickerWidget { + width: 17.25em; + height: 3em; +} diff --git a/modules/ve/ui/ve.ui.Sticker.js b/modules/ve/ui/ve.ui.Sticker.js new file mode 100644 index 0000000..a8593bf --- /dev/null +++ b/modules/ve/ui/ve.ui.Sticker.js @@ -0,0 +1,205 @@ +/*! + * VisualEditor UserInterface Context class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * UserInterface . + * + * @class + * @extends ve.Element + * + * @constructor + * @param {ve.ui.Surface} surface + * @param {Object} [config] Config options + */ +ve.ui.Sticker = function VeUiSticker( surface, config ) { + // Parent constructor + ve.Element.call( this, config ); + + // Properties + this.$stickeredNode = config.$stickeredNode; + this.surface = surface; + this.inspectors = {}; + this.visible = false; + this.showing = false; + this.selecting = false; + this.relocating = false; + this.embedded = false; + this.selection = null; + this.toolbar = null; + this.popup = new ve.ui.StickerWidget( { + '$$': this.$$, + '$container': this.surface.$, + '$wrapper': this.$, + '$stickeredNode': this.$stickeredNode + } ); + this.$menu = this.$$( '<div>' ); + this.inspectors = new ve.ui.WindowSet( surface, ve.ui.inspectorFactory ); + + // Initialization + this.$.addClass( 've-ui-sticker' ).append( this.popup.$ ); +// this.inspectors.$.addClass( 've-ui-sticker-inspectors' ); + this.popup.$body.append( + this.$menu.addClass( 've-ui-sticker-menu' ), + this.inspectors.$.addClass( 've-ui-sticker-inspectors' ) + ); + + this.$.append( this.popup.$ ); + this.surface.$localOverlay.append( this.$ ); + + // Events +/* this.inspectors.connect( this, { + 'setup': 'onInspectorSetup', + 'open': 'onInspectorOpen', + 'close': 'onInspectorClose' + } );*/ +// this.$.add( this.$menu ) +// .on( 'mousedown', false ); + + this.$$( this.getElementWindow() ).on( { + 'resize': ve.bind( this.updateDimensions, this ) + } ); + +}; + + +/* Inheritance */ + +ve.inheritClass( ve.ui.Sticker, ve.Element ); + +/* Methods */ + +/** + * Handle an inspector being setup. + * + * @method + * @param {ve.ui.Inspector} inspector Inspector that's been setup + */ +ve.ui.Sticker.prototype.onInspectorSetup = function () { +// this.selection = this.surface.getModel().getSelection(); +}; + +/** + * Handle an inspector being opened. + * + * @method + * @param {ve.ui.Inspector} inspector Inspector that's been opened + */ +ve.ui.Sticker.prototype.onInspectorOpen = function () { + // Transition between menu and inspector + this.show( true ); +}; + +/** + * Handle an inspector being closed. + * + * @method + * @param {ve.ui.Inspector} inspector Inspector that's been opened + * @param {boolean} accept Changes have been accepted + */ +ve.ui.Sticker.prototype.onInspectorClose = function () { +// this.updateDimensions(); +}; + +/** + * Gets the surface the context is being used in. + * + * @method + * @returns {ve.ui.Surface} Surface of context + */ +ve.ui.Sticker.prototype.getSurface = function () { + return this.surface; +}; + +/** + * Destroy the context, removing all DOM elements. + * + * @method + * @returns {ve.ui.Context} Context UserInterface + * @chainable + */ +ve.ui.Sticker.prototype.destroy = function () { + this.$.remove(); + return this; +}; + +/** + * Shows the context menu. + * + * @method + * @chainable + */ +ve.ui.Sticker.prototype.show = function ( transition ) { +// var inspector = this.inspectors.getCurrent(); + + this.updateDimensions( true ); + this.popup.show(); + this.$.show(); + this.visible = true; + + return this; +}; + + +/** + * Updates the position and size. + * + * @method + * @chainable + */ +ve.ui.Sticker.prototype.updateDimensions = function ( transition ) { + var $container, focusableOffset, focusableWidth, +// surface = this.surface.getView(), + inspector = this.inspectors.getCurrent(), + position = this.$stickeredNode.position(); + + this.popup.display( + position.left, + position.top, + 200, + 70, + transition + ); + + return this; +}; + +/** + * Hides the context menu. + * + * @method + * @chainable + */ +ve.ui.Sticker.prototype.hide = function () { + var inspector = this.inspectors.getCurrent(); + + if ( inspector ) { + // This will recurse, but inspector will be undefined next time + inspector.close( 'hide' ); + return this; + } + + this.popup.hide(); + this.$.hide(); + this.visible = false; + + return this; +}; + + +/** + * Opens a given inspector. + * + * @method + * @param {string} name Symbolic name of inspector + * @chainable + */ +ve.ui.Sticker.prototype.openInspector = function ( name ) { + if ( !this.inspectors.currentWindow ) { + this.inspectors.open( name ); + } + return this; +}; diff --git a/modules/ve/ui/widgets/ve.ui.StickerWidget.js b/modules/ve/ui/widgets/ve.ui.StickerWidget.js new file mode 100644 index 0000000..74691c2 --- /dev/null +++ b/modules/ve/ui/widgets/ve.ui.StickerWidget.js @@ -0,0 +1,104 @@ +/*! + * VisualEditor UserInterface PopupWidget class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * Creates an ve.ui.StickerWidget object. + * + * @class + * @extends ve.ui.Widget + * + * @constructor + * @param {Object} [config] Config options + * @cfg {jQuery} [$container] Container to make sticker positioned relative to + */ +ve.ui.StickerWidget = function VeUiStickerWidget( config ) { + // Config intialization + config = config || {}; + + // Parent constructor + ve.ui.Widget.call( this, config ); + + // Properties + this.visible = false; + this.$body = this.$$( '<div>' ); + this.transitionTimeout = null; + this.align = config.align || 'left'; + + this.$stickeredNode = config.$stickeredNode; + this.$wrapper = config.$wrapper || this.$; + + // Events + this.$.add( this.$body )//.add( this.$callout ) + .on( 'mousedown', function ( e ) { + // Cancel only local mousedown events + return e.target !== this; + } ); + + // Initialization + this.$body.addClass( 've-ui-stickerWidget' ); + this.$body.append("StickeredNode"); + this.$.append( this.$body ); +}; + +/* Inheritance */ + +ve.inheritClass( ve.ui.StickerWidget, ve.ui.Widget ); + + +/** + * Check if the sticker is visible. + * + * @method + * @returns {boolean} Popup is visible + */ +ve.ui.StickerWidget.prototype.isVisible = function () { + return this.visible; +}; + +/** + * Show the sticker. + * + * @method + * @chainable + */ +ve.ui.StickerWidget.prototype.show = function () { + this.$.show(); + this.visible = true; + return this; +}; + +/** + * Show the sticker. + * + * @method + * @chainable + */ +ve.ui.StickerWidget.prototype.hide = function () { + this.$.hide(); + this.visible = false; + this.emit( 'hide' ); + return this; +}; + + +/** + * Updates the position and size. + * + * @method + * @chainable + */ +ve.ui.StickerWidget.prototype.display = function ( x, y, width, height, transition ) { + this.$body.css( { + 'position': 'absolute', + 'left': x, + 'top': y, + 'width': width, + 'height': height === undefined ? 'auto' : height + } ); + + return this; +}; -- To view, visit https://gerrit.wikimedia.org/r/82461 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id97c3840d26a39cb5f6b4cea7a89e89b05b45325 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Mooeypoo <mor...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits