diff --git a/modules/ve/ce/ve.ce.Surface.js b/modules/ve/ce/ve.ce.Surface.js index de4b467b55..bf24cd9388 100644 --- a/modules/ve/ce/ve.ce.Surface.js +++ b/modules/ve/ce/ve.ce.Surface.js @@ -184,6 +184,7 @@ ve.ce.Surface.static.getClipboardHash = function ( $elements ) { * Get the coordinates of the selection anchor. * * @method + * @returns {Object|null} { 'start': { 'x': ..., 'y': ... }, 'end': { 'x': ..., 'y': ... } } */ ve.ce.Surface.prototype.getSelectionRect = function () { var sel, rect, $span, lineHeight, startRange, startOffset, endRange, endOffset, focusedOffset; diff --git a/modules/ve/ui/ve.ui.Context.js b/modules/ve/ui/ve.ui.Context.js index 2a34601a53..05a272bb1c 100644 --- a/modules/ve/ui/ve.ui.Context.js +++ b/modules/ve/ui/ve.ui.Context.js @@ -294,6 +294,14 @@ ve.ui.Context.prototype.updateDimensions = function ( transition ) { // We're on top of a selected text // Get the position of the cursor cursorPosition = surface.getSelectionRect(); + if ( !cursorPosition ) { + // The surface apparently isn't selected, so getSelectionRect() returned null. + // This shouldn't happen because the context is only supposed to be displayed in + // response to a selection, but for some reason this does happen in phantomjs. + // We can't update the context position if we don't know where the selection is, + // so just bail. + return this; + } // Correct for surface offset: position = { diff --git a/modules/ve/ui/ve.ui.SurfaceToolbar.js b/modules/ve/ui/ve.ui.SurfaceToolbar.js index d120338ff9..d76c7c9617 100644 --- a/modules/ve/ui/ve.ui.SurfaceToolbar.js +++ b/modules/ve/ui/ve.ui.SurfaceToolbar.js @@ -130,10 +130,14 @@ ve.ui.SurfaceToolbar.prototype.onWindowResize = function () { * the cursor is obscured by the toolbar. */ ve.ui.SurfaceToolbar.prototype.onSurfaceViewKeyUp = function () { - var cursorPos = this.surface.view.getSelectionRect(), - barHeight = this.$bar.height(), - scrollTo = this.$bar.offset().top - barHeight + ( cursorPos.end.y - cursorPos.start.y ), - obscured = cursorPos.start.y - this.$window.scrollTop() < barHeight; + var barHeight, scrollTo, obscured, cursorPos = this.surface.view.getSelectionRect(); + if ( !cursorPos ) { + return; + } + + barHeight = this.$bar.height(); + scrollTo = this.$bar.offset().top - barHeight + ( cursorPos.end.y - cursorPos.start.y ); + obscured = cursorPos.start.y - this.$window.scrollTop() < barHeight; // If toolbar is floating and cursor is obscured, scroll cursor into view if ( obscured && this.floating ) {