jenkins-bot has submitted this change and it was merged.

Change subject: Initial cursor position: outside any nails
......................................................................


Initial cursor position: outside any nails

Place the initial cursor outside any nailed content, to avoid popping
up context items before the user has deliberately moved their cursor.

Bug: T114376
Change-Id: Ica0b85fa827e9d9bc22152bfb04a279f151c117d
---
M demos/ve/pages/simple.html
M src/ce/ve.ce.Document.js
M src/ce/ve.ce.Surface.js
M tests/ce/ve.ce.Document.test.js
4 files changed, 64 insertions(+), 11 deletions(-)

Approvals:
  Divec: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/demos/ve/pages/simple.html b/demos/ve/pages/simple.html
index 1a0ea1b..2b2844f 100644
--- a/demos/ve/pages/simple.html
+++ b/demos/ve/pages/simple.html
@@ -1,4 +1,4 @@
-<p><b>Lorem Ipsum</b> is simply dummy text of the printing and typesetting 
industry. Lorem Ipsum has been the industry's standard dummy text ever since 
the 1500s, when an unknown printer took a galley of type and scrambled it to 
make a type specimen book. It has survived not only five centuries, but also 
the leap into electronic typesetting, remaining essentially unchanged. It was 
<a href="https://www.mediawiki.org/wiki/VisualEditor";>popularised</a> in the 
1960s with the release of Letraset sheets containing Lorem Ipsum passages, and 
more recently with desktop publishing software like Aldus PageMaker including 
versions of Lorem Ipsum.</p>
+<p><b><a href="https://en.wikipedia.org/wiki/Lorem_ipsum";>Lorem Ipsum</a></b> 
is simply dummy text of the printing and typesetting industry. Lorem Ipsum has 
been the industry's standard dummy text ever since the 1500s, when an unknown 
printer took a galley of type and scrambled it to make a type specimen book. It 
has survived not only five centuries, but also the leap into electronic 
typesetting, remaining essentially unchanged. It was <a 
href="https://www.mediawiki.org/wiki/VisualEditor";>popularised</a> in the 1960s 
with the release of Letraset sheets containing Lorem Ipsum passages, and more 
recently with desktop publishing software like Aldus PageMaker including 
versions of Lorem Ipsum.</p>
 <h2><b>What</b> is <i>Lorem Ipsum?</i></h2>
 <p>Contrary to popular belief, Lorem Ipsum is not simply random text. It has 
roots in a piece of classical Latin literature from 45 BC, making it over 2000 
years old. Richard McClintock, a <a 
href="https://en.wikipedia.org/wiki/Latin";>Latin</a> professor at 
Hampden-Sydney College in <a 
href="https://en.wikipedia.org/wiki/Virginia";>Virginia</a>, looked up one of 
the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and 
going through the cites of the word in classical literature, discovered the 
undoubtable source.</p>
 <h3><b>Look</b> at <i>this headline</i></h3>
diff --git a/src/ce/ve.ce.Document.js b/src/ce/ve.ce.Document.js
index 5a1d69a..91750ee 100644
--- a/src/ce/ve.ce.Document.js
+++ b/src/ce/ve.ce.Document.js
@@ -49,14 +49,14 @@
  * Calculate the DOM location corresponding to a DM offset
  *
  * @param {number} offset Linear model offset
+ * @param {boolean} outsideNail Whether to jump outside nails if directly next 
to them
  * @return {Object} DOM location
  * @return {Node} return.node location node
  * @return {number} return.offset location offset within the node
  * @throws {Error} Offset could not be translated to a DOM element and offset
  */
-ve.ce.Document.prototype.getNodeAndOffset = function ( offset ) {
+ve.ce.Document.prototype.getNodeAndOffset = function ( offset, outsideNail ) {
        var nao, currentNode, nextLeaf, previousLeaf;
-
        // Get the un-unicorn-adjusted result. If it is:
        // - just before pre unicorn (in same branch node), return cursor 
location just after it
        // - just after post unicorn (in same branch node), return cursor 
location just before it
@@ -130,6 +130,28 @@
                // At text offset or slug just after the post unicorn; return 
the point just before it
                return ve.ce.previousCursorOffset( previousLeaf );
        }
+
+       if ( outsideNail ) {
+               if (
+                       nao.offset === currentNode.length &&
+                       nextLeaf &&
+                       nextLeaf.nodeType === Node.ELEMENT_NODE &&
+                       nextLeaf.classList.contains( 've-ce-nail-pre-close' )
+               ) {
+                       // Being outside the nails requested and right next to 
the ending nail: jump outside
+                       return ve.ce.nextCursorOffset( getAdjacentLeaf( 1, 
nextLeaf ) );
+               }
+               if (
+                       nao.offset === 0 &&
+                       previousLeaf &&
+                       previousLeaf.nodeType === Node.ELEMENT_NODE &&
+                       previousLeaf.classList.contains( 've-ce-nail-post-open' 
)
+               ) {
+                       // Being outside the nails requested and right next to 
the starting nail: jump outside
+                       return ve.ce.previousCursorOffset( getAdjacentLeaf( -1, 
previousLeaf ) );
+               }
+       }
+
        return nao;
 };
 
diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index f16ef33..5df0790 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -3155,12 +3155,16 @@
        var anchor, focus,
                dmDoc = this.getModel().getDocument();
 
-       // Anchor/focus at the nearest correct position in the direction that 
grows the selection
+       // Anchor/focus at the nearest correct position in the direction that
+       // grows the selection. If we're not yet fully focused, move the 
selection
+       // outside any nails to avoid popping up a context menu.
        anchor = this.documentView.getNodeAndOffset(
-               dmDoc.getNearestCursorOffset( range.from, range.isBackwards() ? 
1 : -1 )
+               dmDoc.getNearestCursorOffset( range.from, range.isBackwards() ? 
1 : -1 ),
+               !this.focused
        );
        focus = this.documentView.getNodeAndOffset(
-               dmDoc.getNearestCursorOffset( range.to, range.isBackwards() ? 
-1 : 1 )
+               dmDoc.getNearestCursorOffset( range.to, range.isBackwards() ? 
-1 : 1 ),
+               !this.focused
        );
        return new ve.SelectionState( {
                anchorNode: anchor.node,
diff --git a/tests/ce/ve.ce.Document.test.js b/tests/ce/ve.ce.Document.test.js
index 6db066a..d7145db 100644
--- a/tests/ce/ve.ce.Document.test.js
+++ b/tests/ce/ve.ce.Document.test.js
@@ -89,8 +89,35 @@
                        replacement: { path: [ 0 ], innerHtml: '<br>' },
                        data: [ '<paragraph>', '</paragraph>' ],
                        positions: "<div class='ve-ce-branchNode 
ve-ce-documentNode'><p class='ve-ce-branchNode ve-ce-contentBranchNode 
ve-ce-paragraphNode'><br>||</br></p></div>"
+               },
+               {
+                       title: 'Paragraph with links, inside nails',
+                       html: '<p><a href="A">A</a><a href="B">B</a></p>',
+                       data: [ '<paragraph>', 'A', 'B', '</paragraph>' ],
+                       positions: "<div class='ve-ce-branchNode 
ve-ce-documentNode'><p class='ve-ce-branchNode ve-ce-contentBranchNode 
ve-ce-paragraphNode'><img class='ve-ce-nail ve-ce-nail-pre-open'></img><a 
class='ve-ce-linkAnnotation'><img class='ve-ce-nail 
ve-ce-nail-post-open'></img><#text>||A|</#text><img class='ve-ce-nail 
ve-ce-nail-pre-close'></img></a><img class='ve-ce-nail 
ve-ce-nail-post-close'></img><img class='ve-ce-nail 
ve-ce-nail-pre-open'></img><a class='ve-ce-linkAnnotation'><img 
class='ve-ce-nail ve-ce-nail-post-open'></img><#text>B|</#text><img 
class='ve-ce-nail ve-ce-nail-pre-close'></img></a><img class='ve-ce-nail 
ve-ce-nail-post-close'></img></p></div>"
+               },
+               {
+                       title: 'Paragraph with links, outside nails',
+                       html: '<p><a href="A">A</a><a href="B">B</a></p>',
+                       data: [ '<paragraph>', 'A', 'B', '</paragraph>' ],
+                       positions: "<div class='ve-ce-branchNode 
ve-ce-documentNode'><p class='ve-ce-branchNode ve-ce-contentBranchNode 
ve-ce-paragraphNode'>||<img class='ve-ce-nail ve-ce-nail-pre-open'></img><a 
class='ve-ce-linkAnnotation'><img class='ve-ce-nail 
ve-ce-nail-post-open'></img><#text>A</#text><img class='ve-ce-nail 
ve-ce-nail-pre-close'></img></a><img class='ve-ce-nail 
ve-ce-nail-post-close'></img>|<img class='ve-ce-nail 
ve-ce-nail-pre-open'></img><a class='ve-ce-linkAnnotation'><img 
class='ve-ce-nail ve-ce-nail-post-open'></img><#text>B</#text><img 
class='ve-ce-nail ve-ce-nail-pre-close'></img></a><img class='ve-ce-nail 
ve-ce-nail-post-close'></img>|</p></div>",
+                       outsideNails: true
+               },
+               {
+                       title: 'Paragraph with links, non-text nodes, inside 
nails',
+                       html: '<p><a href="A"><b>A<img></b></a></p>',
+                       data: [ '<paragraph>', 'A', '<inlineImage>', 
'</inlineImage>', '</paragraph>' ],
+                       dies: [ 3 ],
+                       positions: "<div class='ve-ce-branchNode 
ve-ce-documentNode'><p class='ve-ce-branchNode ve-ce-contentBranchNode 
ve-ce-paragraphNode'><img class='ve-ce-nail ve-ce-nail-pre-open'></img><a 
class='ve-ce-linkAnnotation'><img class='ve-ce-nail 
ve-ce-nail-post-open'></img><b class='ve-ce-textStyleAnnotation 
ve-ce-boldAnnotation'><#text>||A||</#text><img class='ve-ce-leafNode 
ve-ce-focusableNode ve-ce-imageNode ve-ce-inlineImageNode'></img></b><img 
class='ve-ce-nail ve-ce-nail-pre-close'></img></a><img class='ve-ce-nail 
ve-ce-nail-post-close'></img><span class='ve-ce-branchNode-slug 
ve-ce-branchNode-inlineSlug'>|</span></p></div>"
+               },
+               {
+                       title: 'Paragraph with links, non-text nodes, outside 
nails',
+                       html: '<p><a href="A"><b>A<img></b></a></p>',
+                       data: [ '<paragraph>', 'A', '<inlineImage>', 
'</inlineImage>', '</paragraph>' ],
+                       dies: [ 3 ],
+                       positions: "<div class='ve-ce-branchNode 
ve-ce-documentNode'><p class='ve-ce-branchNode ve-ce-contentBranchNode 
ve-ce-paragraphNode'>||<img class='ve-ce-nail ve-ce-nail-pre-open'></img><a 
class='ve-ce-linkAnnotation'><img class='ve-ce-nail 
ve-ce-nail-post-open'></img><b class='ve-ce-textStyleAnnotation 
ve-ce-boldAnnotation'><#text>A||</#text><img class='ve-ce-leafNode 
ve-ce-focusableNode ve-ce-imageNode ve-ce-inlineImageNode'></img></b><img 
class='ve-ce-nail ve-ce-nail-pre-close'></img></a><img class='ve-ce-nail 
ve-ce-nail-post-close'></img><span class='ve-ce-branchNode-slug 
ve-ce-branchNode-inlineSlug'>|</span></p></div>",
+                       outsideNails: true
                }
-
        ];
        /*jscs:enable validateQuoteMarks */
 
@@ -141,7 +168,7 @@
 
                for ( offset = 0; offset < offsetCount; offset++ ) {
                        try {
-                               position = ceDoc.getNodeAndOffset( offset );
+                               position = ceDoc.getNodeAndOffset( offset, 
test.outsideNails );
                                if ( test.dies && test.dies.indexOf( offset ) 
!== -1 ) {
                                        assert.ok( false, test.title + ' (' + 
offset + ') does not die' );
                                        continue;
@@ -154,12 +181,12 @@
                                continue;
                        }
 
-                       position = ceDoc.getNodeAndOffset( offset );
+                       position = ceDoc.getNodeAndOffset( offset, 
test.outsideNails );
                        assert.strictEqual(
                                ve.test.utils.serializePosition(
                                        rootNode,
-                                       ceDoc.getNodeAndOffset( offset ),
-                                       { ignore: 
'.ve-ce-branchNode-blockSlug>*' }
+                                       ceDoc.getNodeAndOffset( offset, 
test.outsideNails ),
+                                       { ignore: '.ve-ce-branchNode-slug>*' }
                                ),
                                [].concat(
                                        parts.slice( 0, offset + 1 ),

-- 
To view, visit https://gerrit.wikimedia.org/r/260057
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ica0b85fa827e9d9bc22152bfb04a279f151c117d
Gerrit-PatchSet: 9
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: DLynch <[email protected]>
Gerrit-Reviewer: Divec <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to