mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 10:35:48 +00:00
Cleaned up toolbar annotation updates
Change-Id: I8cefd6c871ed6d1ad71f64eb66236de1b8b719b5
This commit is contained in:
parent
26e0f6ed5f
commit
169b7e754d
|
@ -11,24 +11,24 @@ ve.ce.Surface = function( $container, model ) {
|
|||
|
||||
// Properties
|
||||
this.model = model;
|
||||
this.documentView = new ve.ce.Document( model.getDocument() );
|
||||
this.contextView = new ve.ui.Context( this );
|
||||
|
||||
// Properties
|
||||
this.documentView = null; // See initialization below
|
||||
this.contextView = null; // See initialization below
|
||||
this.$ = $container;
|
||||
this.clipboard = {};
|
||||
|
||||
// Driven by mousedown and mouseup events
|
||||
this.isMouseDown = false;
|
||||
this.range = {
|
||||
anchorNode: null,
|
||||
anchorOffset: null,
|
||||
focusNode: null,
|
||||
focusOffset: null
|
||||
'anchorNode': null,
|
||||
'anchorOffset': null,
|
||||
'focusNode': null,
|
||||
'focusOffset': null
|
||||
};
|
||||
|
||||
// init rangy in case of Toshiba...
|
||||
rangy.init();
|
||||
// Tracked using mouse events
|
||||
this.isMouseDown = false;
|
||||
|
||||
// Events
|
||||
this.model.on( 'select', ve.proxy( this.onSelect, this ) );
|
||||
this.model.on( 'transact', ve.proxy( this.onTransact, this ) );
|
||||
this.$.on( {
|
||||
'keypress': ve.proxy( this.onKeyPress, this ),
|
||||
'keydown': ve.proxy( this.onKeyDown, this ),
|
||||
|
@ -47,27 +47,34 @@ ve.ce.Surface = function( $container, model ) {
|
|||
this.$.on( 'beforepaste', ve.proxy( this.onPaste, this ) );
|
||||
}
|
||||
|
||||
this.model.on( 'select', ve.proxy( this.onSelect, this ) );
|
||||
|
||||
|
||||
// Initialization
|
||||
this.$.append( this.documentView.documentNode.$ );
|
||||
|
||||
try {
|
||||
document.execCommand( "enableObjectResizing", false, false );
|
||||
document.execCommand( "enableInlineTableEditing", false, false );
|
||||
} catch (e) { }
|
||||
document.execCommand( 'enableObjectResizing', false, false );
|
||||
document.execCommand( 'enableInlineTableEditing', false, false );
|
||||
} catch ( e ) {
|
||||
// Silently ignore
|
||||
}
|
||||
// Initialize rangy in case of Toshiba...
|
||||
rangy.init();
|
||||
// Must be initialized after select and transact listeners are added to model so respond first
|
||||
this.documentView = new ve.ce.Document( model.getDocument() );
|
||||
this.contextView = new ve.ui.Context( this );
|
||||
this.$.append( this.documentView.documentNode.$ );
|
||||
};
|
||||
|
||||
|
||||
/* Methods */
|
||||
|
||||
ve.ce.Surface.prototype.onSelect = function( e ) {
|
||||
console.log("onSelect", e);
|
||||
ve.ce.Surface.prototype.onSelect = function( range ) {
|
||||
//console.log( 'onSelect', range );
|
||||
};
|
||||
|
||||
ve.ce.Surface.prototype.onTransact = function( tx ) {
|
||||
//console.log( 'onTransact', tx );
|
||||
this.showSelection( this.model.getSelection() );
|
||||
};
|
||||
|
||||
ve.ce.Surface.prototype.onKeyPress = function( e ) {
|
||||
console.log('onKeyPress');
|
||||
//console.log( 'onKeyPress' );
|
||||
switch ( e.which ) {
|
||||
// Enter
|
||||
case 13:
|
||||
|
@ -78,13 +85,12 @@ ve.ce.Surface.prototype.onKeyPress = function( e ) {
|
|||
};
|
||||
|
||||
ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||
console.log('onKeyDown');
|
||||
//console.log( 'onKeyDown' );
|
||||
// Prevent all interactions coming from keyboard when mouse is down (possibly selecting)
|
||||
if ( this.isMouseDown === true ) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ( e.keyCode ) {
|
||||
// Left arrow
|
||||
case 37:
|
||||
|
@ -94,12 +100,9 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
|||
break;
|
||||
// Backspace
|
||||
case 8:
|
||||
|
||||
tx = ve.dm.Transaction.newFromRemoval( this.documentView.model, this.model.getSelection() );
|
||||
ve.dm.TransactionProcessor.commit( this.documentView.model, tx );
|
||||
this.showCursor(this.model.getSelection().start);
|
||||
|
||||
|
||||
e.preventDefault();
|
||||
break;
|
||||
// Delete
|
||||
|
@ -111,7 +114,6 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
|||
|
||||
ve.ce.Surface.prototype.onMouseDown = function( e ) {
|
||||
this.isMouseDown = true;
|
||||
|
||||
// TODO: Add special handling for clicking on images and alien nodes
|
||||
var $leaf = $( e.target ).closest( '.ve-ce-leafNode' );
|
||||
};
|
||||
|
|
|
@ -494,7 +494,7 @@ ve.dm.Document.prototype.getDataFromNode = function( node ) {
|
|||
*
|
||||
* @method
|
||||
* @param {Integer} offset Offset to get annotations for
|
||||
* @returns {Object[]} A copy of all annotation objects offset is covered by
|
||||
* @returns {Object} A copy of all annotation objects offset is covered by
|
||||
*/
|
||||
ve.dm.Document.prototype.getAnnotationsFromOffset = function( offset ) {
|
||||
var annotations;
|
||||
|
@ -516,7 +516,7 @@ ve.dm.Document.prototype.getAnnotationsFromOffset = function( offset ) {
|
|||
|
||||
if ( ve.isPlainObject( annotations ) ) {
|
||||
//return ve.getObjectValues( annotations );
|
||||
return annotations;
|
||||
return ve.extendObject( {}, annotations );
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
@ -642,99 +642,59 @@ ve.dm.Document.getMatchingAnnotations = function( annotations, pattern ) {
|
|||
return matches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an annotation from annotations that match a regular expression.
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @param {Array} annotations Annotations to search through
|
||||
* @param {RegExp} pattern Regular expression pattern to match with
|
||||
* @returns {Object} Annotation object
|
||||
*/
|
||||
ve.dm.Document.getMatchingAnnotation = function( annotations, pattern ) {
|
||||
if ( !( pattern instanceof RegExp ) ) {
|
||||
throw 'Invalid Pattern. Pattern not instance of RegExp';
|
||||
}
|
||||
if ( ve.isPlainObject( annotations ) ) {
|
||||
for ( var hash in annotations ) {
|
||||
if ( pattern.test( annotations[hash].type ) ){
|
||||
return annotations[hash];
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quick check for annotation inside annotations object
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @param {Object} annotations Annotations to search through
|
||||
* @param {Object} pattern Regular expression pattern to match with
|
||||
* @returns {Boolean} if annotation in annotations object
|
||||
*/
|
||||
ve.dm.Document.annotationsContainAnnotation = function( annotations, annotation ) {
|
||||
var contains = false;
|
||||
$.each(annotations, function(i, val){
|
||||
if ( ve.compareObjects(val, annotation) ) {
|
||||
contains = true;
|
||||
}
|
||||
});
|
||||
return contains;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets an array of common annnotations across a range.
|
||||
*
|
||||
* @method
|
||||
* @param {Integer} offset Offset to get annotations for
|
||||
* @returns {Object[]} A copy of all annotation objects offset is covered by
|
||||
* @param {Boolean} [all] Get all annotations found within the range, not just those that cover it
|
||||
* @returns {Object} A copy of all annotation objects offset is covered by
|
||||
*/
|
||||
ve.dm.Document.prototype.getAnnotationsFromRange = function( range ) {
|
||||
var currentChar = {},
|
||||
annotations = {},
|
||||
charCount = 0,
|
||||
map = {};
|
||||
|
||||
ve.dm.Document.prototype.getAnnotationsFromRange = function( range, all ) {
|
||||
range.normalize();
|
||||
|
||||
var annotations = {},
|
||||
count = 0,
|
||||
left,
|
||||
right,
|
||||
hash;
|
||||
// Shorcut for zero-length ranges
|
||||
if ( range.getLength() === 0 ) {
|
||||
return this.getAnnotationsFromOffset( range.to );
|
||||
return {};
|
||||
}
|
||||
|
||||
for ( var i = range.start; i < range.end; i++ ) {
|
||||
// skip non characters
|
||||
// There's at least one character, get it's annotations
|
||||
left = this.getAnnotationsFromOffset( range.start );
|
||||
// Shorcut for single character ranges
|
||||
if ( range.getLength() === 1 ) {
|
||||
return left;
|
||||
}
|
||||
// Iterator over the range, looking for annotations, starting at the 2nd character
|
||||
for ( var i = range.start + 1; i < range.end; i++ ) {
|
||||
// Skip non character data
|
||||
if ( ve.dm.Document.isElementData( this.data, i ) ) {
|
||||
continue;
|
||||
}
|
||||
//current character annotations
|
||||
currentChar = this.data[i][1];
|
||||
// if a non annotated character, no commonality.
|
||||
if ( currentChar === undefined ) {
|
||||
return annotations;
|
||||
// Current character annotations
|
||||
right = this.getAnnotationsFromOffset( i );
|
||||
if ( all && right !== undefined ) {
|
||||
ve.extendObject( left, right );
|
||||
} else if ( !all ) {
|
||||
// A non annotated character indicates there's no full coverage
|
||||
if ( right === undefined ) {
|
||||
return {};
|
||||
}
|
||||
charCount++;
|
||||
// if current char annotations are not the same as previous char.
|
||||
if ( ve.compareObjects( map, currentChar ) === false) {
|
||||
//retain common annotations
|
||||
if ( charCount > 1 ) {
|
||||
// look for annotation in map
|
||||
for ( var a in currentChar ) {
|
||||
if( map[a] === undefined ) {
|
||||
delete currentChar[a];
|
||||
// Exclude annotations that are in left but not right
|
||||
for ( hash in left ) {
|
||||
if ( right[hash] === undefined ) {
|
||||
delete left[hash];
|
||||
}
|
||||
}
|
||||
// If we've reduced left down to nothing, just stop looking
|
||||
if ( ve.isEmptyObject( left ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//save map
|
||||
map = currentChar;
|
||||
}
|
||||
// build array of annotations
|
||||
for ( var key in map ) {
|
||||
annotations[key] = map[key];
|
||||
}
|
||||
return annotations;
|
||||
return left;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,15 +103,6 @@ ve.dm.Surface.prototype.transact = function( transaction ) {
|
|||
*/
|
||||
ve.dm.Surface.prototype.annotate = function( method, annotation ) {
|
||||
var selection = this.getSelection();
|
||||
|
||||
if ( method === 'toggle' ) {
|
||||
var annotations = this.getDocument().getAnnotationsFromRange( selection );
|
||||
if ( annotation in annotations ) {
|
||||
method = 'clear';
|
||||
} else {
|
||||
method = 'set';
|
||||
}
|
||||
}
|
||||
if ( this.selection.getLength() ) {
|
||||
var tx = ve.dm.Transaction.newFromAnnotation(
|
||||
this.getDocument(), selection, method, annotation
|
||||
|
|
|
@ -24,10 +24,10 @@ ve.ui.LinkInspector = function( toolbar, context ) {
|
|||
}
|
||||
|
||||
var surfaceModel = _this.context.getSurfaceView().getModel(),
|
||||
annotation = _this.getSelectedLinkAnnotation();
|
||||
annotations = _this.getSelectedLinkAnnotations();
|
||||
// If link annotation exists, clear it.
|
||||
if ( annotation !== undefined ) {
|
||||
surfaceModel.annotate( 'clear', annotation );
|
||||
for ( var hash in annotations ) {
|
||||
surfaceModel.annotate( 'clear', annotations[hash] );
|
||||
}
|
||||
|
||||
_this.$locationInput.val( '' );
|
||||
|
@ -46,7 +46,7 @@ ve.ui.LinkInspector = function( toolbar, context ) {
|
|||
|
||||
/* Methods */
|
||||
|
||||
ve.ui.LinkInspector.prototype.getSelectedLinkAnnotation = function(){
|
||||
ve.ui.LinkInspector.prototype.getSelectedLinkAnnotations = function(){
|
||||
var surfaceView = this.context.getSurfaceView(),
|
||||
surfaceModel = surfaceView.getModel(),
|
||||
documentModel = surfaceModel.getDocument(),
|
||||
|
@ -54,9 +54,9 @@ ve.ui.LinkInspector.prototype.getSelectedLinkAnnotation = function(){
|
|||
|
||||
if ( data.length ) {
|
||||
if ( ve.isPlainObject( data[0][1] ) ) {
|
||||
var annotation = ve.dm.Document.getMatchingAnnotation( data[0][1], /link\/.*/ );
|
||||
if ( ve.isPlainObject(annotation) ) {
|
||||
return annotation;
|
||||
var annotations = ve.dm.Document.getMatchingAnnotations( data[0][1], /link\/.*/ );
|
||||
for ( var hash in annotations ) {
|
||||
return annotations[hash];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,10 +64,12 @@ ve.ui.LinkInspector.prototype.getSelectedLinkAnnotation = function(){
|
|||
};
|
||||
|
||||
ve.ui.LinkInspector.prototype.getTitleFromSelection = function() {
|
||||
var annotation = this.getSelectedLinkAnnotation();
|
||||
|
||||
if ( annotation && annotation.data && annotation.data.title ) {
|
||||
return annotation.data.title;
|
||||
var annotations = this.getSelectedLinkAnnotations();
|
||||
for ( var hash in annotations ) {
|
||||
// Use the first one that has a title (there should only be one, but this is just in case)
|
||||
if ( annotations[hash].data && annotations[hash].data.title ) {
|
||||
return annotations[hash].data.title;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -96,11 +98,11 @@ ve.ui.LinkInspector.prototype.onClose = function( accept ) {
|
|||
return;
|
||||
}
|
||||
var surfaceModel = this.context.getSurfaceView().getModel(),
|
||||
annotation = this.getSelectedLinkAnnotation();
|
||||
annotations = this.getSelectedLinkAnnotations();
|
||||
|
||||
// Clear link annotation if it exists
|
||||
if ( annotation !== undefined ) {
|
||||
surfaceModel.annotate( 'clear', annotation );
|
||||
for ( var hash in annotations ) {
|
||||
surfaceModel.annotate( 'clear', annotations[hash] );
|
||||
}
|
||||
surfaceModel.annotate( 'set', { 'type': 'link/wikiLink', 'data': { 'title': title } } );
|
||||
}
|
||||
|
|
|
@ -46,13 +46,16 @@ ve.ui.AnnotationButtonTool.prototype.onClick = function() {
|
|||
};
|
||||
|
||||
ve.ui.AnnotationButtonTool.prototype.updateState = function( annotations, nodes ) {
|
||||
if ( ve.dm.Document.annotationsContainAnnotation(annotations, this.annotation) ) {
|
||||
this.$.addClass( 'es-toolbarButtonTool-down' );
|
||||
this.active = true;
|
||||
return;
|
||||
}
|
||||
var matches = ve.dm.Document.getMatchingAnnotations(
|
||||
annotations, new RegExp( '^' + this.annotation.type + '$' )
|
||||
);
|
||||
if ( ve.isEmptyObject( matches ) ) {
|
||||
this.$.removeClass( 'es-toolbarButtonTool-down' );
|
||||
this.active = false;
|
||||
} else {
|
||||
this.$.addClass( 'es-toolbarButtonTool-down' );
|
||||
this.active = true;
|
||||
}
|
||||
};
|
||||
|
||||
/* Registration */
|
||||
|
|
|
@ -18,7 +18,7 @@ ve.ui.ClearButtonTool = function( toolbar, name, title ) {
|
|||
|
||||
/* Methods */
|
||||
|
||||
ve.ui.ClearButtonTool.prototype.getAnnotation = function(){
|
||||
ve.ui.ClearButtonTool.prototype.getAnnotations = function(){
|
||||
var surfaceView = this.toolbar.getSurfaceView(),
|
||||
surfaceModel = surfaceView.getModel(),
|
||||
documentModel = surfaceModel.getDocument(),
|
||||
|
@ -26,10 +26,7 @@ ve.ui.ClearButtonTool.prototype.getAnnotation = function(){
|
|||
|
||||
if ( data.length ) {
|
||||
if ( ve.isPlainObject( data[0][1] ) ) {
|
||||
var annotation = ve.dm.Document.getMatchingAnnotation( data[0][1], this.pattern );
|
||||
if ( ve.isPlainObject( annotation ) ) {
|
||||
return annotation;
|
||||
}
|
||||
return ve.dm.Document.getMatchingAnnotations( data[0][1], this.pattern );
|
||||
}
|
||||
}
|
||||
return ;
|
||||
|
@ -37,9 +34,11 @@ ve.ui.ClearButtonTool.prototype.getAnnotation = function(){
|
|||
|
||||
ve.ui.ClearButtonTool.prototype.onClick = function() {
|
||||
var surfaceView = this.toolbar.getSurfaceView(),
|
||||
model = surfaceView.getModel();
|
||||
|
||||
model.annotate( 'clear', this.getAnnotation() );
|
||||
model = surfaceView.getModel(),
|
||||
annotations = this.getAnnotations();
|
||||
for ( var hash in annotations ) {
|
||||
model.annotate( 'clear', annotations[hash] );
|
||||
}
|
||||
surfaceView.showSelection( model.getSelection() );
|
||||
surfaceView.contextView.closeInspector();
|
||||
};
|
||||
|
|
|
@ -32,27 +32,26 @@ ve.ui.Toolbar = function( $container, surfaceView, config ) {
|
|||
|
||||
/* Methods */
|
||||
|
||||
ve.ui.Toolbar.prototype.updateTools = function( e ) {
|
||||
var _this = this,
|
||||
model = _this.surfaceView.getModel(),
|
||||
/**
|
||||
* Triggers update events on all tools.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.ui.Toolbar.prototype.updateTools = function() {
|
||||
var model = this.surfaceView.getModel(),
|
||||
doc = model.getDocument(),
|
||||
annotations,
|
||||
nodes = [],
|
||||
range = model.getSelection(),
|
||||
startNode,
|
||||
endNode;
|
||||
|
||||
// On transact: set e, and redraw selection
|
||||
if ( e.from === undefined ) {
|
||||
e = model.getSelection();
|
||||
this.surfaceView.showSelection( e );
|
||||
}
|
||||
|
||||
if( e !== null ) {
|
||||
if ( e.from === e.to ){
|
||||
nodes.push( doc.getNodeFromOffset( e.from ) );
|
||||
if ( range !== null ) {
|
||||
if ( range.from === range.to ){
|
||||
nodes.push( doc.getNodeFromOffset( range.from ) );
|
||||
} else {
|
||||
startNode = doc.getNodeFromOffset( e.from );
|
||||
endNode = doc.getNodeFromOffset ( e.end );
|
||||
startNode = doc.getNodeFromOffset( range.from );
|
||||
endNode = doc.getNodeFromOffset ( range.end );
|
||||
// These should be different, alas just in case.
|
||||
if ( startNode === endNode ) {
|
||||
nodes.push( startNode );
|
||||
|
@ -67,22 +66,24 @@ ve.ui.Toolbar.prototype.updateTools = function( e ) {
|
|||
}
|
||||
}
|
||||
// Update Context
|
||||
if ( e.getLength() > 0 ) {
|
||||
_this.surfaceView.contextView.set();
|
||||
if ( range.getLength() > 0 ) {
|
||||
this.surfaceView.contextView.set();
|
||||
annotations = doc.getAnnotationsFromRange( range );
|
||||
} else {
|
||||
_this.surfaceView.contextView.clear();
|
||||
this.surfaceView.contextView.clear();
|
||||
annotations = doc.getAnnotationsFromOffset(
|
||||
doc.getNearestContentOffset( range.start - 1 )
|
||||
);
|
||||
}
|
||||
|
||||
annotations = doc.getAnnotationsFromRange( e );
|
||||
// Update state
|
||||
for ( i = 0; i < _this.tools.length; i++ ) {
|
||||
_this.tools[i].updateState( annotations, nodes );
|
||||
for ( i = 0; i < this.tools.length; i++ ) {
|
||||
this.tools[i].updateState( annotations, nodes );
|
||||
}
|
||||
} else {
|
||||
// Clear state
|
||||
_this.surfaceView.contextView.clear();
|
||||
for ( i = 0; i < _this.tools.length; i++ ) {
|
||||
_this.tools[i].clearState();
|
||||
this.surfaceView.contextView.clear();
|
||||
for ( i = 0; i < this.tools.length; i++ ) {
|
||||
this.tools[i].clearState();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -205,12 +205,9 @@ test( 'getAnnotationsFromOffset', 1, function() {
|
|||
} );
|
||||
|
||||
test( 'getAnnotationsFromRange', 1, function() {
|
||||
var doc,
|
||||
range,
|
||||
annotations,
|
||||
cases = [
|
||||
var cases = [
|
||||
{
|
||||
'msg': 'all bold',
|
||||
'msg': 'single annotations',
|
||||
'data': [
|
||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||
['b', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ]
|
||||
|
@ -218,38 +215,41 @@ test( 'getAnnotationsFromRange', 1, function() {
|
|||
'expected': { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } }
|
||||
},
|
||||
{
|
||||
'msg': 'bold and italic',
|
||||
'msg': 'mutliple annotations',
|
||||
'data': [
|
||||
['a',
|
||||
[
|
||||
'a',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
],
|
||||
['b',
|
||||
[
|
||||
'b',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
]
|
||||
],
|
||||
'expected':
|
||||
{
|
||||
'expected': {
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
'msg': 'bold and italic',
|
||||
'msg': 'lowest common coverage',
|
||||
'data': [
|
||||
['a',
|
||||
[
|
||||
'a',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
],
|
||||
['b',
|
||||
[
|
||||
'b',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
||||
|
@ -257,22 +257,67 @@ test( 'getAnnotationsFromRange', 1, function() {
|
|||
}
|
||||
]
|
||||
],
|
||||
'expected':
|
||||
{
|
||||
'expected': {
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
},
|
||||
{
|
||||
'msg': 'none common, non annotated character at end',
|
||||
'msg': 'no common coverage due to plain character at the start',
|
||||
'data': [
|
||||
['a',
|
||||
['a'],
|
||||
[
|
||||
'b',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
||||
'{"type":"textStyle/underline"}': { 'type': 'textStyle/underline'}
|
||||
}
|
||||
],
|
||||
[
|
||||
'c',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
]
|
||||
],
|
||||
'expected': {}
|
||||
},
|
||||
{
|
||||
'msg': 'no common coverage due to plain character in the middle',
|
||||
'data': [
|
||||
[
|
||||
'a',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
||||
'{"type":"textStyle/underline"}': { 'type': 'textStyle/underline'}
|
||||
}
|
||||
],
|
||||
['b'],
|
||||
[
|
||||
'c',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
]
|
||||
],
|
||||
'expected': {}
|
||||
},
|
||||
{
|
||||
'msg': 'no common coverage due to plain character at the end',
|
||||
'data': [
|
||||
[
|
||||
'a',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
],
|
||||
['b',
|
||||
[
|
||||
'b',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
||||
|
@ -284,27 +329,7 @@ test( 'getAnnotationsFromRange', 1, function() {
|
|||
'expected': {}
|
||||
},
|
||||
{
|
||||
'msg': 'none common, reverse of previous',
|
||||
'data': [
|
||||
['a'],
|
||||
['b',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
||||
'{"type":"textStyle/underline"}': { 'type': 'textStyle/underline'}
|
||||
}
|
||||
],
|
||||
['c',
|
||||
{
|
||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||
}
|
||||
]
|
||||
],
|
||||
'expected': {}
|
||||
},
|
||||
{
|
||||
'msg': 'all different',
|
||||
'msg': 'no common coverage due to mismatched annotations',
|
||||
'data': [
|
||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ]
|
||||
|
@ -312,22 +337,78 @@ test( 'getAnnotationsFromRange', 1, function() {
|
|||
'expected': {}
|
||||
},
|
||||
{
|
||||
'msg': 'no annotations',
|
||||
'msg': 'annotations are collected using all with mismatched annotations',
|
||||
'data': [
|
||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ]
|
||||
],
|
||||
'all': true,
|
||||
'expected': {
|
||||
'{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' }
|
||||
}
|
||||
},
|
||||
{
|
||||
'msg': 'annotations are collected using all, even with a plain character at the start',
|
||||
'data': [
|
||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ],
|
||||
['c']
|
||||
],
|
||||
'all': true,
|
||||
'expected': {
|
||||
'{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' }
|
||||
}
|
||||
},
|
||||
{
|
||||
'msg': 'annotations are collected using all, even with a plain character at the middle',
|
||||
'data': [
|
||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ],
|
||||
['c']
|
||||
],
|
||||
'all': true,
|
||||
'expected': {
|
||||
'{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' }
|
||||
}
|
||||
},
|
||||
{
|
||||
'msg': 'annotations are collected using all, even with a plain character at the end',
|
||||
'data': [
|
||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ],
|
||||
['c']
|
||||
],
|
||||
'all': true,
|
||||
'expected': {
|
||||
'{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||
'{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' }
|
||||
}
|
||||
},
|
||||
{
|
||||
'msg': 'no common coverage from all plain characters',
|
||||
'data': ['a', 'b'],
|
||||
'expected': {}
|
||||
},
|
||||
{
|
||||
'msg': 'no common coverage using all from all plain characters',
|
||||
'data': ['a', 'b'],
|
||||
'all': true,
|
||||
'expected': {}
|
||||
}
|
||||
];
|
||||
|
||||
expect( cases.length );
|
||||
|
||||
for ( var i = 0; i < cases.length; i++ ) {
|
||||
doc = new ve.dm.Document ( cases[i].data );
|
||||
range = new ve.Range( 0, doc.getData().length );
|
||||
annotations = doc.getAnnotationsFromRange( range );
|
||||
var doc = new ve.dm.Document ( cases[i].data );
|
||||
deepEqual(
|
||||
annotations, cases[i].expected, cases[i].msg
|
||||
doc.getAnnotationsFromRange( new ve.Range( 0, cases[i].data.length ), cases[i].all ),
|
||||
cases[i].expected,
|
||||
cases[i].msg
|
||||
);
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
|
|
Loading…
Reference in a new issue