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
|
// Properties
|
||||||
this.model = model;
|
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.$ = $container;
|
||||||
this.clipboard = {};
|
this.clipboard = {};
|
||||||
|
|
||||||
// Driven by mousedown and mouseup events
|
|
||||||
this.isMouseDown = false;
|
|
||||||
this.range = {
|
this.range = {
|
||||||
anchorNode: null,
|
'anchorNode': null,
|
||||||
anchorOffset: null,
|
'anchorOffset': null,
|
||||||
focusNode: null,
|
'focusNode': null,
|
||||||
focusOffset: null
|
'focusOffset': null
|
||||||
};
|
};
|
||||||
|
// Tracked using mouse events
|
||||||
// init rangy in case of Toshiba...
|
this.isMouseDown = false;
|
||||||
rangy.init();
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
this.model.on( 'select', ve.proxy( this.onSelect, this ) );
|
||||||
|
this.model.on( 'transact', ve.proxy( this.onTransact, this ) );
|
||||||
this.$.on( {
|
this.$.on( {
|
||||||
'keypress': ve.proxy( this.onKeyPress, this ),
|
'keypress': ve.proxy( this.onKeyPress, this ),
|
||||||
'keydown': ve.proxy( this.onKeyDown, this ),
|
'keydown': ve.proxy( this.onKeyDown, this ),
|
||||||
|
@ -43,31 +43,38 @@ ve.ce.Surface = function( $container, model ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
if ($.browser.msie) {
|
if ( $.browser.msie ) {
|
||||||
this.$.on('beforepaste', ve.proxy( this.onPaste, this ) );
|
this.$.on( 'beforepaste', ve.proxy( this.onPaste, this ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.model.on( 'select', ve.proxy( this.onSelect, this ) );
|
|
||||||
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
this.$.append( this.documentView.documentNode.$ );
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
document.execCommand( "enableObjectResizing", false, false );
|
document.execCommand( 'enableObjectResizing', false, false );
|
||||||
document.execCommand( "enableInlineTableEditing", false, false );
|
document.execCommand( 'enableInlineTableEditing', false, false );
|
||||||
} catch (e) { }
|
} 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 */
|
/* Methods */
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onSelect = function( e ) {
|
ve.ce.Surface.prototype.onSelect = function( range ) {
|
||||||
console.log("onSelect", e);
|
//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 ) {
|
ve.ce.Surface.prototype.onKeyPress = function( e ) {
|
||||||
console.log('onKeyPress');
|
//console.log( 'onKeyPress' );
|
||||||
switch ( e.which ) {
|
switch ( e.which ) {
|
||||||
// Enter
|
// Enter
|
||||||
case 13:
|
case 13:
|
||||||
|
@ -78,13 +85,12 @@ ve.ce.Surface.prototype.onKeyPress = function( e ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onKeyDown = 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)
|
// Prevent all interactions coming from keyboard when mouse is down (possibly selecting)
|
||||||
if ( this.isMouseDown === true ) {
|
if ( this.isMouseDown === true ) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ( e.keyCode ) {
|
switch ( e.keyCode ) {
|
||||||
// Left arrow
|
// Left arrow
|
||||||
case 37:
|
case 37:
|
||||||
|
@ -94,12 +100,9 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
break;
|
break;
|
||||||
// Backspace
|
// Backspace
|
||||||
case 8:
|
case 8:
|
||||||
|
|
||||||
tx = ve.dm.Transaction.newFromRemoval( this.documentView.model, this.model.getSelection() );
|
tx = ve.dm.Transaction.newFromRemoval( this.documentView.model, this.model.getSelection() );
|
||||||
ve.dm.TransactionProcessor.commit( this.documentView.model, tx );
|
ve.dm.TransactionProcessor.commit( this.documentView.model, tx );
|
||||||
this.showCursor(this.model.getSelection().start);
|
this.showCursor(this.model.getSelection().start);
|
||||||
|
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
// Delete
|
// Delete
|
||||||
|
@ -111,7 +114,6 @@ ve.ce.Surface.prototype.onKeyDown = function( e ) {
|
||||||
|
|
||||||
ve.ce.Surface.prototype.onMouseDown = function( e ) {
|
ve.ce.Surface.prototype.onMouseDown = function( e ) {
|
||||||
this.isMouseDown = true;
|
this.isMouseDown = true;
|
||||||
|
|
||||||
// TODO: Add special handling for clicking on images and alien nodes
|
// TODO: Add special handling for clicking on images and alien nodes
|
||||||
var $leaf = $( e.target ).closest( '.ve-ce-leafNode' );
|
var $leaf = $( e.target ).closest( '.ve-ce-leafNode' );
|
||||||
};
|
};
|
||||||
|
|
|
@ -494,7 +494,7 @@ ve.dm.Document.prototype.getDataFromNode = function( node ) {
|
||||||
*
|
*
|
||||||
* @method
|
* @method
|
||||||
* @param {Integer} offset Offset to get annotations for
|
* @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 ) {
|
ve.dm.Document.prototype.getAnnotationsFromOffset = function( offset ) {
|
||||||
var annotations;
|
var annotations;
|
||||||
|
@ -516,7 +516,7 @@ ve.dm.Document.prototype.getAnnotationsFromOffset = function( offset ) {
|
||||||
|
|
||||||
if ( ve.isPlainObject( annotations ) ) {
|
if ( ve.isPlainObject( annotations ) ) {
|
||||||
//return ve.getObjectValues( annotations );
|
//return ve.getObjectValues( annotations );
|
||||||
return annotations;
|
return ve.extendObject( {}, annotations );
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
@ -642,99 +642,59 @@ ve.dm.Document.getMatchingAnnotations = function( annotations, pattern ) {
|
||||||
return matches;
|
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.
|
* Gets an array of common annnotations across a range.
|
||||||
*
|
*
|
||||||
* @method
|
* @method
|
||||||
* @param {Integer} offset Offset to get annotations for
|
* @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 ) {
|
ve.dm.Document.prototype.getAnnotationsFromRange = function( range, all ) {
|
||||||
var currentChar = {},
|
|
||||||
annotations = {},
|
|
||||||
charCount = 0,
|
|
||||||
map = {};
|
|
||||||
|
|
||||||
range.normalize();
|
range.normalize();
|
||||||
|
var annotations = {},
|
||||||
|
count = 0,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
hash;
|
||||||
|
// Shorcut for zero-length ranges
|
||||||
if ( range.getLength() === 0 ) {
|
if ( range.getLength() === 0 ) {
|
||||||
return this.getAnnotationsFromOffset( range.to );
|
return {};
|
||||||
}
|
}
|
||||||
|
// There's at least one character, get it's annotations
|
||||||
for ( var i = range.start; i < range.end; i++ ) {
|
left = this.getAnnotationsFromOffset( range.start );
|
||||||
// skip non characters
|
// 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 ) ) {
|
if ( ve.dm.Document.isElementData( this.data, i ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//current character annotations
|
// Current character annotations
|
||||||
currentChar = this.data[i][1];
|
right = this.getAnnotationsFromOffset( i );
|
||||||
// if a non annotated character, no commonality.
|
if ( all && right !== undefined ) {
|
||||||
if ( currentChar === undefined ) {
|
ve.extendObject( left, right );
|
||||||
return annotations;
|
} else if ( !all ) {
|
||||||
}
|
// A non annotated character indicates there's no full coverage
|
||||||
charCount++;
|
if ( right === undefined ) {
|
||||||
// if current char annotations are not the same as previous char.
|
return {};
|
||||||
if ( ve.compareObjects( map, currentChar ) === false) {
|
}
|
||||||
//retain common annotations
|
// Exclude annotations that are in left but not right
|
||||||
if ( charCount > 1 ) {
|
for ( hash in left ) {
|
||||||
// look for annotation in map
|
if ( right[hash] === undefined ) {
|
||||||
for ( var a in currentChar ) {
|
delete left[hash];
|
||||||
if( map[a] === undefined ) {
|
|
||||||
delete currentChar[a];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If we've reduced left down to nothing, just stop looking
|
||||||
|
if ( ve.isEmptyObject( left ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//save map
|
|
||||||
map = currentChar;
|
|
||||||
}
|
}
|
||||||
// build array of annotations
|
return left;
|
||||||
for ( var key in map ) {
|
|
||||||
annotations[key] = map[key];
|
|
||||||
}
|
|
||||||
return annotations;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -103,15 +103,6 @@ ve.dm.Surface.prototype.transact = function( transaction ) {
|
||||||
*/
|
*/
|
||||||
ve.dm.Surface.prototype.annotate = function( method, annotation ) {
|
ve.dm.Surface.prototype.annotate = function( method, annotation ) {
|
||||||
var selection = this.getSelection();
|
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() ) {
|
if ( this.selection.getLength() ) {
|
||||||
var tx = ve.dm.Transaction.newFromAnnotation(
|
var tx = ve.dm.Transaction.newFromAnnotation(
|
||||||
this.getDocument(), selection, method, annotation
|
this.getDocument(), selection, method, annotation
|
||||||
|
|
|
@ -23,11 +23,11 @@ ve.ui.LinkInspector = function( toolbar, context ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var surfaceModel = _this.context.getSurfaceView().getModel(),
|
var surfaceModel = _this.context.getSurfaceView().getModel(),
|
||||||
annotation = _this.getSelectedLinkAnnotation();
|
annotations = _this.getSelectedLinkAnnotations();
|
||||||
// If link annotation exists, clear it.
|
// If link annotation exists, clear it.
|
||||||
if ( annotation !== undefined ) {
|
for ( var hash in annotations ) {
|
||||||
surfaceModel.annotate( 'clear', annotation );
|
surfaceModel.annotate( 'clear', annotations[hash] );
|
||||||
}
|
}
|
||||||
|
|
||||||
_this.$locationInput.val( '' );
|
_this.$locationInput.val( '' );
|
||||||
|
@ -46,7 +46,7 @@ ve.ui.LinkInspector = function( toolbar, context ) {
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
ve.ui.LinkInspector.prototype.getSelectedLinkAnnotation = function(){
|
ve.ui.LinkInspector.prototype.getSelectedLinkAnnotations = function(){
|
||||||
var surfaceView = this.context.getSurfaceView(),
|
var surfaceView = this.context.getSurfaceView(),
|
||||||
surfaceModel = surfaceView.getModel(),
|
surfaceModel = surfaceView.getModel(),
|
||||||
documentModel = surfaceModel.getDocument(),
|
documentModel = surfaceModel.getDocument(),
|
||||||
|
@ -54,9 +54,9 @@ ve.ui.LinkInspector.prototype.getSelectedLinkAnnotation = function(){
|
||||||
|
|
||||||
if ( data.length ) {
|
if ( data.length ) {
|
||||||
if ( ve.isPlainObject( data[0][1] ) ) {
|
if ( ve.isPlainObject( data[0][1] ) ) {
|
||||||
var annotation = ve.dm.Document.getMatchingAnnotation( data[0][1], /link\/.*/ );
|
var annotations = ve.dm.Document.getMatchingAnnotations( data[0][1], /link\/.*/ );
|
||||||
if ( ve.isPlainObject(annotation) ) {
|
for ( var hash in annotations ) {
|
||||||
return annotation;
|
return annotations[hash];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,12 @@ ve.ui.LinkInspector.prototype.getSelectedLinkAnnotation = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
ve.ui.LinkInspector.prototype.getTitleFromSelection = function() {
|
ve.ui.LinkInspector.prototype.getTitleFromSelection = function() {
|
||||||
var annotation = this.getSelectedLinkAnnotation();
|
var annotations = this.getSelectedLinkAnnotations();
|
||||||
|
for ( var hash in annotations ) {
|
||||||
if ( annotation && annotation.data && annotation.data.title ) {
|
// Use the first one that has a title (there should only be one, but this is just in case)
|
||||||
return annotation.data.title;
|
if ( annotations[hash].data && annotations[hash].data.title ) {
|
||||||
|
return annotations[hash].data.title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -96,11 +98,11 @@ ve.ui.LinkInspector.prototype.onClose = function( accept ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var surfaceModel = this.context.getSurfaceView().getModel(),
|
var surfaceModel = this.context.getSurfaceView().getModel(),
|
||||||
annotation = this.getSelectedLinkAnnotation();
|
annotations = this.getSelectedLinkAnnotations();
|
||||||
|
|
||||||
// Clear link annotation if it exists
|
// Clear link annotation if it exists
|
||||||
if ( annotation !== undefined ) {
|
for ( var hash in annotations ) {
|
||||||
surfaceModel.annotate( 'clear', annotation );
|
surfaceModel.annotate( 'clear', annotations[hash] );
|
||||||
}
|
}
|
||||||
surfaceModel.annotate( 'set', { 'type': 'link/wikiLink', 'data': { 'title': title } } );
|
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 ) {
|
ve.ui.AnnotationButtonTool.prototype.updateState = function( annotations, nodes ) {
|
||||||
if ( ve.dm.Document.annotationsContainAnnotation(annotations, this.annotation) ) {
|
var matches = ve.dm.Document.getMatchingAnnotations(
|
||||||
this.$.addClass( 'es-toolbarButtonTool-down' );
|
annotations, new RegExp( '^' + this.annotation.type + '$' )
|
||||||
this.active = true;
|
);
|
||||||
return;
|
if ( ve.isEmptyObject( matches ) ) {
|
||||||
|
this.$.removeClass( 'es-toolbarButtonTool-down' );
|
||||||
|
this.active = false;
|
||||||
|
} else {
|
||||||
|
this.$.addClass( 'es-toolbarButtonTool-down' );
|
||||||
|
this.active = true;
|
||||||
}
|
}
|
||||||
this.$.removeClass( 'es-toolbarButtonTool-down' );
|
|
||||||
this.active = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Registration */
|
/* Registration */
|
||||||
|
|
|
@ -18,7 +18,7 @@ ve.ui.ClearButtonTool = function( toolbar, name, title ) {
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
ve.ui.ClearButtonTool.prototype.getAnnotation = function(){
|
ve.ui.ClearButtonTool.prototype.getAnnotations = function(){
|
||||||
var surfaceView = this.toolbar.getSurfaceView(),
|
var surfaceView = this.toolbar.getSurfaceView(),
|
||||||
surfaceModel = surfaceView.getModel(),
|
surfaceModel = surfaceView.getModel(),
|
||||||
documentModel = surfaceModel.getDocument(),
|
documentModel = surfaceModel.getDocument(),
|
||||||
|
@ -26,10 +26,7 @@ ve.ui.ClearButtonTool.prototype.getAnnotation = function(){
|
||||||
|
|
||||||
if ( data.length ) {
|
if ( data.length ) {
|
||||||
if ( ve.isPlainObject( data[0][1] ) ) {
|
if ( ve.isPlainObject( data[0][1] ) ) {
|
||||||
var annotation = ve.dm.Document.getMatchingAnnotation( data[0][1], this.pattern );
|
return ve.dm.Document.getMatchingAnnotations( data[0][1], this.pattern );
|
||||||
if ( ve.isPlainObject( annotation ) ) {
|
|
||||||
return annotation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ;
|
return ;
|
||||||
|
@ -37,9 +34,11 @@ ve.ui.ClearButtonTool.prototype.getAnnotation = function(){
|
||||||
|
|
||||||
ve.ui.ClearButtonTool.prototype.onClick = function() {
|
ve.ui.ClearButtonTool.prototype.onClick = function() {
|
||||||
var surfaceView = this.toolbar.getSurfaceView(),
|
var surfaceView = this.toolbar.getSurfaceView(),
|
||||||
model = surfaceView.getModel();
|
model = surfaceView.getModel(),
|
||||||
|
annotations = this.getAnnotations();
|
||||||
model.annotate( 'clear', this.getAnnotation() );
|
for ( var hash in annotations ) {
|
||||||
|
model.annotate( 'clear', annotations[hash] );
|
||||||
|
}
|
||||||
surfaceView.showSelection( model.getSelection() );
|
surfaceView.showSelection( model.getSelection() );
|
||||||
surfaceView.contextView.closeInspector();
|
surfaceView.contextView.closeInspector();
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,27 +32,26 @@ ve.ui.Toolbar = function( $container, surfaceView, config ) {
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
ve.ui.Toolbar.prototype.updateTools = function( e ) {
|
/**
|
||||||
var _this = this,
|
* Triggers update events on all tools.
|
||||||
model = _this.surfaceView.getModel(),
|
*
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
ve.ui.Toolbar.prototype.updateTools = function() {
|
||||||
|
var model = this.surfaceView.getModel(),
|
||||||
doc = model.getDocument(),
|
doc = model.getDocument(),
|
||||||
annotations,
|
annotations,
|
||||||
nodes = [],
|
nodes = [],
|
||||||
|
range = model.getSelection(),
|
||||||
startNode,
|
startNode,
|
||||||
endNode;
|
endNode;
|
||||||
|
|
||||||
// On transact: set e, and redraw selection
|
if ( range !== null ) {
|
||||||
if ( e.from === undefined ) {
|
if ( range.from === range.to ){
|
||||||
e = model.getSelection();
|
nodes.push( doc.getNodeFromOffset( range.from ) );
|
||||||
this.surfaceView.showSelection( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( e !== null ) {
|
|
||||||
if ( e.from === e.to ){
|
|
||||||
nodes.push( doc.getNodeFromOffset( e.from ) );
|
|
||||||
} else {
|
} else {
|
||||||
startNode = doc.getNodeFromOffset( e.from );
|
startNode = doc.getNodeFromOffset( range.from );
|
||||||
endNode = doc.getNodeFromOffset ( e.end );
|
endNode = doc.getNodeFromOffset ( range.end );
|
||||||
// These should be different, alas just in case.
|
// These should be different, alas just in case.
|
||||||
if ( startNode === endNode ) {
|
if ( startNode === endNode ) {
|
||||||
nodes.push( startNode );
|
nodes.push( startNode );
|
||||||
|
@ -67,22 +66,24 @@ ve.ui.Toolbar.prototype.updateTools = function( e ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update Context
|
// Update Context
|
||||||
if ( e.getLength() > 0 ) {
|
if ( range.getLength() > 0 ) {
|
||||||
_this.surfaceView.contextView.set();
|
this.surfaceView.contextView.set();
|
||||||
|
annotations = doc.getAnnotationsFromRange( range );
|
||||||
} else {
|
} else {
|
||||||
_this.surfaceView.contextView.clear();
|
this.surfaceView.contextView.clear();
|
||||||
|
annotations = doc.getAnnotationsFromOffset(
|
||||||
|
doc.getNearestContentOffset( range.start - 1 )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
annotations = doc.getAnnotationsFromRange( e );
|
|
||||||
// Update state
|
// Update state
|
||||||
for ( i = 0; i < _this.tools.length; i++ ) {
|
for ( i = 0; i < this.tools.length; i++ ) {
|
||||||
_this.tools[i].updateState( annotations, nodes );
|
this.tools[i].updateState( annotations, nodes );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Clear state
|
// Clear state
|
||||||
_this.surfaceView.contextView.clear();
|
this.surfaceView.contextView.clear();
|
||||||
for ( i = 0; i < _this.tools.length; i++ ) {
|
for ( i = 0; i < this.tools.length; i++ ) {
|
||||||
_this.tools[i].clearState();
|
this.tools[i].clearState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -205,12 +205,9 @@ test( 'getAnnotationsFromOffset', 1, function() {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'getAnnotationsFromRange', 1, function() {
|
test( 'getAnnotationsFromRange', 1, function() {
|
||||||
var doc,
|
var cases = [
|
||||||
range,
|
|
||||||
annotations,
|
|
||||||
cases = [
|
|
||||||
{
|
{
|
||||||
'msg': 'all bold',
|
'msg': 'single annotations',
|
||||||
'data': [
|
'data': [
|
||||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||||
['b', { '{"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' } }
|
'expected': { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'msg': 'bold and italic',
|
'msg': 'mutliple annotations',
|
||||||
'data': [
|
'data': [
|
||||||
['a',
|
[
|
||||||
|
'a',
|
||||||
{
|
{
|
||||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
['b',
|
[
|
||||||
|
'b',
|
||||||
{
|
{
|
||||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'expected':
|
'expected': {
|
||||||
{
|
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'msg': 'bold and italic',
|
'msg': 'lowest common coverage',
|
||||||
'data': [
|
'data': [
|
||||||
['a',
|
[
|
||||||
|
'a',
|
||||||
{
|
{
|
||||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
['b',
|
[
|
||||||
|
'b',
|
||||||
{
|
{
|
||||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
'{"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': 'no common coverage due to plain character at the start',
|
||||||
|
'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/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'expected': {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'msg': 'none common, non annotated character at end',
|
'msg': 'no common coverage due to plain character in the middle',
|
||||||
'data': [
|
'data': [
|
||||||
['a',
|
[
|
||||||
|
'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/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
['b',
|
[
|
||||||
|
'b',
|
||||||
{
|
{
|
||||||
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
'{"type":"textStyle/bold"}': { 'type': 'textStyle/bold' },
|
||||||
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
'{"type":"textStyle/italic"}': { 'type': 'textStyle/italic'},
|
||||||
|
@ -284,27 +329,7 @@ test( 'getAnnotationsFromRange', 1, function() {
|
||||||
'expected': {}
|
'expected': {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'msg': 'none common, reverse of previous',
|
'msg': 'no common coverage due to mismatched annotations',
|
||||||
'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',
|
|
||||||
'data': [
|
'data': [
|
||||||
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
['a', { '{"type:"textStyle/bold"}': { 'type': 'textStyle/bold' } } ],
|
||||||
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ]
|
['b', { '{"type:"textStyle/italic"}': { 'type': 'textStyle/italic' } } ]
|
||||||
|
@ -312,22 +337,78 @@ test( 'getAnnotationsFromRange', 1, function() {
|
||||||
'expected': {}
|
'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'],
|
'data': ['a', 'b'],
|
||||||
'expected': {}
|
'expected': {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'msg': 'no common coverage using all from all plain characters',
|
||||||
|
'data': ['a', 'b'],
|
||||||
|
'all': true,
|
||||||
|
'expected': {}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
expect( cases.length );
|
expect( cases.length );
|
||||||
|
|
||||||
for ( var i = 0; i < cases.length; i++ ) {
|
for ( var i = 0; i < cases.length; i++ ) {
|
||||||
doc = new ve.dm.Document ( cases[i].data );
|
var doc = new ve.dm.Document ( cases[i].data );
|
||||||
range = new ve.Range( 0, doc.getData().length );
|
|
||||||
annotations = doc.getAnnotationsFromRange( range );
|
|
||||||
deepEqual(
|
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