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

Reply via email to