Divec has uploaded a new change for review.
https://gerrit.wikimedia.org/r/76743
Change subject: Use native left/right char cursoring in text nodes
......................................................................
Use native left/right char cursoring in text nodes
modules/ve/ce/ve.ce.Surface.js
* Document the purpose of handleLeftOrRightArrowKey
* Native left/right cursoring happens if inside text node
modules/ve/ve.js
* Revert cluster-aware splitting to trivial javascript code unit splitting.
* Rewrite ve.splitClusters as a trivial compatibility method (needs removing
soon).
demos/ve/pages/multibyte.html
demos/ve/pages/unicode.html
* replace file with more comprehensive tests
modules/ve/test/ve.test.js
* Remove test of grapheme-based splitting (no longer used)
Change-Id: I74a8fdb15b502103176cb3765eb1129f6b6a1c6f
---
D demos/ve/pages/multibyte.html
A demos/ve/pages/unicode.html
M modules/ve/ce/ve.ce.Surface.js
M modules/ve/test/ve.test.js
M modules/ve/ve.js
5 files changed, 51 insertions(+), 62 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/43/76743/1
diff --git a/demos/ve/pages/multibyte.html b/demos/ve/pages/multibyte.html
deleted file mode 100644
index 979b312..0000000
--- a/demos/ve/pages/multibyte.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<p>12𨋢456789𨋢bc</p>
-<p>「𨋢」字響<tt>香港</tt>衍生出好多新詞,好似:𨋢<tt>香港</tt> abc</p>
-<p>abc</p>
-<p>one c̀ombining accent</p>
-<p>two ç̀ombining accents</p>
-<p>def</p>
\ No newline at end of file
diff --git a/demos/ve/pages/unicode.html b/demos/ve/pages/unicode.html
new file mode 100644
index 0000000..8213a59
--- /dev/null
+++ b/demos/ve/pages/unicode.html
@@ -0,0 +1,3 @@
+<h1>Above FFFF: 12𨋢456789𨋢bc</h1>
+<h1>TT / wordbreak:「𨋢」係一個<tt>香港字</tt> 呢啲瀏覽器:真係好<tt>麻煩</tt>嘅喎!</h1>
+<h1>Cluster test: ക്ത്ര faç̀on</h1>
diff --git a/modules/ve/ce/ve.ce.Surface.js b/modules/ve/ce/ve.ce.Surface.js
index 113b257..ba3aa14 100644
--- a/modules/ve/ce/ve.ce.Surface.js
+++ b/modules/ve/ce/ve.ce.Surface.js
@@ -987,6 +987,16 @@
/**
* @method
+ * At times we can't rely on the browser's native Left/Right handling. For
instance:
+ * * To prevent cursoring into an image caption
+ * * Or into a template in IE (which does not respect contenteditable=false
inside contenteditable=true)
+ * * To allow selection of elements (e.g. placing the cursor "on image")
+ * * To prevent the cursor disappearing on some browsers in places like
<table>|<tr>
+ * * To handle backwards selection in IE (which cannot be set
programmatically, so needs faking)
+ * * To give more consistency between browsers
+ *
+ * On the other hand, the browser's native handling is positively required to
handle cursoring
+ * over multi-codepoint Indic grapheme clusters, combining accents etc.
*/
ve.ce.Surface.prototype.handleLeftOrRightArrowKey = function ( e ) {
var selection, range, direction;
@@ -994,6 +1004,13 @@
// As we are not able to handle it programmatically (because we don't
know at which offsets
// lines starts and ends) let it happen natively.
if ( e.metaKey ) {
+ return;
+ }
+
+ // If we're cursoring by character, within a text node, then use native
browser handling
+ // in order to handle grapheme clusters correctly.
+ if ( ! e.altKey && ! e.ctrlKey && this.willMoveInsideTextNode(
+ e.keyCode === ve.Keys.LEFT ? 'backward' : 'forward' ) ) {
return;
}
@@ -1020,6 +1037,29 @@
this.surfaceObserver.start();
};
+ve.ce.Surface.prototype.willMoveInsideTextNode = function ( direction ) {
+ var range, node, backward = direction === 'backward',
+ sel = rangy.getSelection( this.getElementDocument() );
+ if ( sel.rangeCount === 0 ) {
+ return false;
+ }
+ // If moving backwards, get first range; if moving forwards, get last
range
+ range = backward ? sel.getRangeAt( 0 ) : sel.getRangeAt( sel.rangeCount
- 1 );
+ node = backward ? range.startContainer : range.endContainer;
+ if ( node.nodeType !== node.TEXT_NODE ) {
+ return false;
+ }
+
+ // Kludge: in Chrome, cursoring left splits the text node in two for
some reason.
+ // So, normalize the parent to heal the splits. But this may make the
node vanish,
+ // so we must obtain it a second time. Hence the sense of déjà vu below.
+ node.parentElement.normalize();
+ range = backward ? sel.getRangeAt( 0 ) : sel.getRangeAt( sel.rangeCount
- 1 );
+ node = backward ? range.startContainer : range.endContainer;
+
+ return backward ? range.startOffset > 0 : range.endOffset <
node.nodeValue.length;
+};
+
/**
* @method
*/
diff --git a/modules/ve/test/ve.test.js b/modules/ve/test/ve.test.js
index c87ba9c..9dd2bbc 100644
--- a/modules/ve/test/ve.test.js
+++ b/modules/ve/test/ve.test.js
@@ -444,53 +444,3 @@
assert.equalDomElement( $( 'body', doc ).get( 0 ),
expectedBody, cases[key].msg + ' (body)' );
}
} );
-
-// ve.splitClusters: Tested upstream (UnicodeJS)
-
-// TODO: ve.isUnattachedCombiningMark
-
-// TODO: ve.getByteOffset
-
-// TODO: ve.getCharacterOffset
-
-QUnit.test( 'graphemeSafeSubstring', function ( assert ) {
- var i, text = '12𨋢45𨋢789𨋢bc', cases = [
- {
- 'msg': 'start and end inside multibyte',
- 'start': 3,
- 'end': 12,
- 'expected': [ '𨋢45𨋢789𨋢', '45𨋢789' ]
- },
- {
- 'msg': 'start and end next to multibyte',
- 'start': 4,
- 'end': 11,
- 'expected': [ '45𨋢789', '45𨋢789' ]
- },
- {
- 'msg': 'complete string',
- 'start': 0,
- 'end': text.length,
- 'expected': [ text, text ]
- },
- {
- 'msg': 'collapsed selection inside multibyte',
- 'start': 3,
- 'end': 3,
- 'expected': [ '𨋢', '' ]
- }
- ];
- QUnit.expect( cases.length * 2 );
- for ( i = 0; i < cases.length; i++ ) {
- assert.equal(
- ve.graphemeSafeSubstring( text, cases[i].start,
cases[i].end, true ),
- cases[i].expected[0],
- cases[i].msg + ' (outer)'
- );
- assert.equal(
- ve.graphemeSafeSubstring( text, cases[i].start,
cases[i].end, false ),
- cases[i].expected[1],
- cases[i].msg + ' (inner)'
- );
- }
-} );
diff --git a/modules/ve/ve.js b/modules/ve/ve.js
index 21391f8..c39bab5 100644
--- a/modules/ve/ve.js
+++ b/modules/ve/ve.js
@@ -578,12 +578,14 @@
return ve.init.platform.getMessage.apply( ve.init.platform,
arguments );
};
- /**
- * @method
- * @inheritdoc unicodeJS.graphemebreak#splitClusters
- * @see unicodeJS.graphemebreak#splitClusters
- */
- ve.splitClusters = unicodeJS.graphemebreak.splitClusters;
+ /**
+ * Compatibility method. We no longer split into clusters at this level.
+ *
+ * TODO: strip out calls to splitClusters then delete this method.
+ */
+ ve.splitClusters = function ( text ) {
+ return text.split( '' );
+ };
/**
* Determine if the text consists of only unattached combining marks.
--
To view, visit https://gerrit.wikimedia.org/r/76743
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I74a8fdb15b502103176cb3765eb1129f6b6a1c6f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Divec <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits