JGonera has uploaded a new change for review.
https://gerrit.wikimedia.org/r/141085
Change subject: [WIP] Reenable mobile context and style it properly
......................................................................
[WIP] Reenable mobile context and style it properly
Also, attach inspectors to the global surface instead of mobile context.
TODO:
* styling of mobile context
* why do I need to tap references twice?
Change-Id: Ic4f288cdcb248b76ead57c048144c8909a16042d
---
M modules/ve/ui/styles/ve.ui.MobileContext.css
M modules/ve/ui/styles/ve.ui.MobileSurface.css
M modules/ve/ui/ve.ui.Context.js
M modules/ve/ui/ve.ui.DesktopContext.js
M modules/ve/ui/ve.ui.MobileContext.js
M modules/ve/ui/ve.ui.MobileSurface.js
6 files changed, 199 insertions(+), 151 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor
refs/changes/85/141085/1
diff --git a/modules/ve/ui/styles/ve.ui.MobileContext.css
b/modules/ve/ui/styles/ve.ui.MobileContext.css
index d68b1f7..5cc3ba8 100644
--- a/modules/ve/ui/styles/ve.ui.MobileContext.css
+++ b/modules/ve/ui/styles/ve.ui.MobileContext.css
@@ -5,16 +5,19 @@
* @license The MIT License (MIT); see LICENSE.txt
*/
-.ve-ui-mobileContext-visible {
- position: absolute;
- top: 0;
- width: 100%;
- height: 100%;
+.ve-ui-mobileContext {
+ position: fixed;
+ top: 3.35em;
background: #fff;
+ width: 100%;
+ -webkit-transform: translate3d(0, -200%, 0);
+ transform: translate3d(0, -200%, 0);
+
+ -webkit-transition: -webkit-transform .3s, opacity .3s;
+ transition: transform .3s, opacity .3s;
}
-/* inspector styles */
-
-.ve-ui-mobileContext .oo-ui-frame {
- width: 100%;
+.ve-ui-mobileContext-visible {
+ -webkit-transform: none;
+ transform: none;
}
diff --git a/modules/ve/ui/styles/ve.ui.MobileSurface.css
b/modules/ve/ui/styles/ve.ui.MobileSurface.css
index d344664..c3064fe 100644
--- a/modules/ve/ui/styles/ve.ui.MobileSurface.css
+++ b/modules/ve/ui/styles/ve.ui.MobileSurface.css
@@ -9,6 +9,7 @@
/*csslint compatible-vendor-prefixes:false */
.ve-ui-mobileSurface-overlay-global {
+ background: #fff;
height: 100%;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
@@ -26,3 +27,9 @@
height: 100%;
overflow: hidden;
}
+
+/* inspector styles */
+
+.ve-ui-mobileSurface-overlay-global-visible .oo-ui-frame {
+ width: 100%;
+}
diff --git a/modules/ve/ui/ve.ui.Context.js b/modules/ve/ui/ve.ui.Context.js
index 0274798..a973f1a 100644
--- a/modules/ve/ui/ve.ui.Context.js
+++ b/modules/ve/ui/ve.ui.Context.js
@@ -25,6 +25,20 @@
this.inspectors = new ve.ui.WindowSet(
ve.ui.windowFactory, { '$': this.$, '$contextOverlay':
this.$element }
);
+ this.context = new ve.ui.ContextWidget( { '$': this.$ } );
+ this.afterModelChangeTimeout = null;
+ this.afterModelChangeRange = null;
+
+ // Events
+ this.surface.getModel().connect( this, {
+ 'documentUpdate': 'onModelChange',
+ 'select': 'onModelChange'
+ } );
+ this.inspectors.connect( this, {
+ 'setup': 'onInspectorSetup',
+ 'teardown': 'onInspectorTeardown'
+ } );
+ this.context.connect( this, { 'choose': 'onContextItemChoose' } );
};
/* Inheritance */
@@ -32,6 +46,109 @@
OO.inheritClass( ve.ui.Context, OO.ui.Element );
/* Methods */
+
+/**
+ * Handle context item choose events.
+ *
+ * @param {ve.ui.ContextItemWidget} item Chosen item
+ */
+ve.ui.Context.prototype.onContextItemChoose = function ( item ) {
+ if ( item ) {
+ item.getCommand().execute( this.surface );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.Context.prototype.destroy = function () {
+ // Disconnect events
+ this.surface.getModel().disconnect( this );
+ this.surface.getView().disconnect( this );
+ this.inspectors.disconnect( this );
+
+ // Stop timers
+ clearTimeout( this.afterModelChangeTimeout );
+
+ // Parent method
+ return ve.ui.Context.prototype.destroy.call( this );
+};
+
+/**
+ * Handle selection changes in the model.
+ *
+ * Changes are ignored while the user is selecting text or relocating content,
apart from closing
+ * the popup if it's open. While an inspector is opening or closing, all
changes are ignored so as
+ * to prevent inspectors that change the selection from within their
open/close handlers from
+ * causing issues.
+ *
+ * The response to selection changes is deferred to prevent close handlers
that process
+ * changes from causing this function to recurse. These responses are also
batched for efficiency,
+ * so that if there are three selection changes in the same tick,
afterModelChange() only runs once.
+ *
+ * @method
+ * @param {ve.Range} range Range if triggered by selection change, null
otherwise
+ * @see #afterModelChange
+ */
+ve.ui.Context.prototype.onModelChange = function ( range ) {
+ var win = this.inspectors.getCurrentWindow();
+
+ if ( this.showing || this.hiding || ( win && ( win.isOpening() ||
win.isClosing() ) ) ) {
+ clearTimeout( this.afterModelChangeTimeout );
+ this.afterModelChangeTimeout = null;
+ this.afterModelChangeRange = null;
+ } else {
+ if ( this.afterModelChangeTimeout === null ) {
+ this.afterModelChangeTimeout = setTimeout( ve.bind(
this.afterModelChange, this ) );
+ }
+ if ( range instanceof ve.Range ) {
+ this.afterModelChangeRange = range;
+ }
+ }
+};
+
+/**
+ * Updates the context menu.
+ *
+ * @method
+ * @param {boolean} [transition=false] Use a smooth transition
+ * @chainable
+ */
+ve.ui.Context.prototype.update = function ( transition ) {
+ var i, len, match, matches,
+ items = [],
+ fragment = this.surface.getModel().getFragment( null, false ),
+ selection = fragment.getRange(),
+ inspector = this.inspectors.getCurrentWindow();
+
+ if ( inspector && selection && selection.equals( this.selection ) ) {
+ // There's an inspector, and the selection hasn't changed,
update the position
+ this.show( transition );
+ } else {
+ // No inspector is open, or the selection has changed, show a
menu of available inspectors
+ matches = ve.ui.toolFactory.getToolsForFragment( fragment );
+ if ( matches.length ) {
+ // There's at least one inspectable annotation, build a
menu and show it
+ this.context.clearItems();
+ for ( i = 0, len = matches.length; i < len; i++ ) {
+ match = matches[i];
+ items.push( new ve.ui.ContextItemWidget(
+ match.tool.static.name, match.tool,
match.model, { '$': this.$ }
+ ) );
+ }
+ this.context.addItems( items );
+ this.show( transition );
+ } else if ( this.visible ) {
+ // Nothing to inspect
+ this.hide();
+ }
+ }
+
+ // Remember selection for next time
+ this.selection = selection && selection.clone();
+
+ return this;
+};
/**
* Get the surface the context is being used in.
@@ -78,6 +195,24 @@
};
/**
+* Handle an inspector setup event.
+*
+* @method
+*/
+ve.ui.Context.prototype.onInspectorSetup = function () {
+ throw new Error( 've.ui.Context.onInspectorSetup must be overridden in
subclass' );
+};
+
+/**
+* Handle an inspector teardown event.
+*
+* @method
+*/
+ve.ui.Context.prototype.onInspectorTeardown = function () {
+ throw new Error( 've.ui.Context.onInspectorTeardown must be overridden
in subclass' );
+};
+
+/**
* Hide the context.
*
* @method
diff --git a/modules/ve/ui/ve.ui.DesktopContext.js
b/modules/ve/ui/ve.ui.DesktopContext.js
index 70926d1..87d8ca7 100644
--- a/modules/ve/ui/ve.ui.DesktopContext.js
+++ b/modules/ve/ui/ve.ui.DesktopContext.js
@@ -28,9 +28,6 @@
this.relocating = false;
this.embedded = false;
this.selection = null;
- this.context = new ve.ui.ContextWidget( { '$': this.$ } );
- this.afterModelChangeTimeout = null;
- this.afterModelChangeRange = null;
this.$menu = this.$( '<div>' );
this.popup = new OO.ui.PopupWidget( {
'$': this.$,
@@ -38,10 +35,6 @@
} );
// Events
- this.surface.getModel().connect( this, {
- 'documentUpdate': 'onModelChange',
- 'select': 'onModelChange'
- } );
this.surface.getView().connect( this, {
'selectionStart': 'onSelectionStart',
'selectionEnd': 'onSelectionEnd',
@@ -51,11 +44,6 @@
'blur': 'onSurfaceBlur',
'position': 'onSurfacePosition'
} );
- this.inspectors.connect( this, {
- 'setup': 'onInspectorSetup',
- 'teardown': 'onInspectorTeardown'
- } );
- this.context.connect( this, { 'choose': 'onContextItemChoose' } );
this.$element.add( this.$menu )
.on( 'mousedown', false );
@@ -76,71 +64,11 @@
/* Methods */
/**
- * Handle context item choose events.
- *
- * @param {ve.ui.ContextItemWidget} item Chosen item
- */
-ve.ui.DesktopContext.prototype.onContextItemChoose = function ( item ) {
- if ( item ) {
- item.getCommand().execute( this.surface );
- }
-};
-
-/**
- * @inheritdoc
- */
-ve.ui.DesktopContext.prototype.destroy = function () {
- // Disconnect events
- this.surface.getModel().disconnect( this );
- this.surface.getView().disconnect( this );
- this.inspectors.disconnect( this );
-
- // Stop timers
- clearTimeout( this.afterModelChangeTimeout );
-
- // Parent method
- return ve.ui.Context.prototype.destroy.call( this );
-};
-
-/**
* Handle window resize events.
*/
ve.ui.DesktopContext.prototype.onWindowResize = function () {
// Update, no transition
this.update( false );
-};
-
-/**
- * Handle selection changes in the model.
- *
- * Changes are ignored while the user is selecting text or relocating content,
apart from closing
- * the popup if it's open. While an inspector is opening or closing, all
changes are ignored so as
- * to prevent inspectors that change the selection from within their
open/close handlers from
- * causing issues.
- *
- * The response to selection changes is deferred to prevent close handlers
that process
- * changes from causing this function to recurse. These responses are also
batched for efficiency,
- * so that if there are three selection changes in the same tick,
afterModelChange() only runs once.
- *
- * @method
- * @param {ve.Range} range Range if triggered by selection change, null
otherwise
- * @see #afterModelChange
- */
-ve.ui.DesktopContext.prototype.onModelChange = function ( range ) {
- var win = this.inspectors.getCurrentWindow();
-
- if ( this.showing || this.hiding || ( win && ( win.isOpening() ||
win.isClosing() ) ) ) {
- clearTimeout( this.afterModelChangeTimeout );
- this.afterModelChangeTimeout = null;
- this.afterModelChangeRange = null;
- } else {
- if ( this.afterModelChangeTimeout === null ) {
- this.afterModelChangeTimeout = setTimeout( ve.bind(
this.afterModelChange, this ) );
- }
- if ( range instanceof ve.Range ) {
- this.afterModelChangeRange = range;
- }
- }
};
/**
@@ -252,11 +180,7 @@
};
/**
- * Handle an inspector setup event.
- *
- * @method
- * @param {ve.ui.Inspector} inspector Inspector that's been setup
- * @param {Object} [config] Inspector opening information
+ * @inheritdoc
*/
ve.ui.DesktopContext.prototype.onInspectorSetup = function () {
this.selection = this.surface.getModel().getSelection();
@@ -264,60 +188,13 @@
};
/**
- * Handle an inspector teardown event.
- *
- * @method
- * @param {ve.ui.Inspector} inspector Inspector that's been torn down
- * @param {Object} [config] Inspector closing information
+ * @inheritdoc
*/
ve.ui.DesktopContext.prototype.onInspectorTeardown = function () {
this.update();
if ( this.getSurface().getModel().getSelection() ) {
this.getSurface().getView().focus();
}
-};
-
-/**
- * Updates the context menu.
- *
- * @method
- * @param {boolean} [transition=false] Use a smooth transition
- * @chainable
- */
-ve.ui.DesktopContext.prototype.update = function ( transition ) {
- var i, len, match, matches,
- items = [],
- fragment = this.surface.getModel().getFragment( null, false ),
- selection = fragment.getRange(),
- inspector = this.inspectors.getCurrentWindow();
-
- if ( inspector && selection && selection.equals( this.selection ) ) {
- // There's an inspector, and the selection hasn't changed,
update the position
- this.show( transition );
- } else {
- // No inspector is open, or the selection has changed, show a
menu of available inspectors
- matches = ve.ui.toolFactory.getToolsForFragment( fragment );
- if ( matches.length ) {
- // There's at least one inspectable annotation, build a
menu and show it
- this.context.clearItems();
- for ( i = 0, len = matches.length; i < len; i++ ) {
- match = matches[i];
- items.push( new ve.ui.ContextItemWidget(
- match.tool.static.name, match.tool,
match.model, { '$': this.$ }
- ) );
- }
- this.context.addItems( items );
- this.show( transition );
- } else if ( this.visible ) {
- // Nothing to inspect
- this.hide();
- }
- }
-
- // Remember selection for next time
- this.selection = selection && selection.clone();
-
- return this;
};
/**
diff --git a/modules/ve/ui/ve.ui.MobileContext.js
b/modules/ve/ui/ve.ui.MobileContext.js
index 625f3f6..c85e9f5 100644
--- a/modules/ve/ui/ve.ui.MobileContext.js
+++ b/modules/ve/ui/ve.ui.MobileContext.js
@@ -19,15 +19,12 @@
// Parent constructor
ve.ui.Context.call( this, surface, config );
- // Events
- this.inspectors.connect( this, {
- 'setup': 'show',
- 'teardown': 'hide'
- } );
-
// Initialization
this.$element
.addClass( 've-ui-mobileContext' )
+ .append( this.context.$element );
+
+ this.surface.$globalOverlay
.append( this.inspectors.$element );
};
@@ -38,6 +35,41 @@
/* Methods */
/**
+ * Deferred response to one or more select events.
+ *
+ * Update the context menu for the new selection, except if the user is
selecting or relocating
+ * content. If the popup is open, close it, even while selecting or relocating.
+ */
+ve.ui.MobileContext.prototype.afterModelChange = function () {
+ var win = this.inspectors.getCurrentWindow(),
+ selectionChange = !!this.afterModelChangeRange,
+ moving = selectionChange && !( win && ( win.isOpening() ||
win.isClosing() ) );
+
+ this.afterModelChangeTimeout = null;
+ this.afterModelChangeRange = null;
+
+ // TODO this is the only big difference between MobileContext and
DesktopContext
+ // merge this code somehow?
+ this.hide();
+
+ this.update( !moving );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.MobileContext.prototype.onInspectorSetup = function () {
+ this.surface.showGlobalOverlay();
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.MobileContext.prototype.onInspectorTeardown = function () {
+ this.surface.hideGlobalOverlay();
+};
+
+/**
* Shows the context.
*
* @method
@@ -45,19 +77,13 @@
*/
ve.ui.MobileContext.prototype.show = function () {
this.$element.addClass( 've-ui-mobileContext-visible' );
- this.surface.showGlobalOverlay();
+ return this;
};
/**
* @inheritdoc
*/
ve.ui.MobileContext.prototype.hide = function () {
- var self = this;
-
- this.surface.hideGlobalOverlay();
- // Make sure that the context is hidden only after the transition
- // of global overlay finishes (see ve.ui.MobileSurface.css).
- setTimeout( function () {
- self.$element.removeClass( 've-ui-mobileContext-visible' );
- }, 300 );
+ this.$element.removeClass( 've-ui-mobileContext-visible' );
+ return this;
};
diff --git a/modules/ve/ui/ve.ui.MobileSurface.js
b/modules/ve/ui/ve.ui.MobileSurface.js
index 0df6f92..8a6fb27 100644
--- a/modules/ve/ui/ve.ui.MobileSurface.js
+++ b/modules/ve/ui/ve.ui.MobileSurface.js
@@ -29,8 +29,8 @@
} );
// Initialization
- this.$globalOverlay.append( this.context.$element )
- .addClass( 've-ui-mobileSurface-overlay
ve-ui-mobileSurface-overlay-global' );
+ this.$globalOverlay.addClass( 've-ui-mobileSurface-overlay
ve-ui-mobileSurface-overlay-global' );
+ this.$localOverlay.append( this.context.$element );
};
/* Inheritance */
--
To view, visit https://gerrit.wikimedia.org/r/141085
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic4f288cdcb248b76ead57c048144c8909a16042d
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: JGonera <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits