mediawiki-extensions-Visual.../modules/ve/actions/ve.AnnotationAction.js
Christian Williams d23c10fd8e Fix insertion annotations
Now comparing annotations in surface to insertionAnnotations
by comparable object to trigger pawn trick. Adding annotations
correctly to placeholder.

dm.Surface change method now uses setInsertionAnnotations()
and passes the AnnotationSet from offset-1. The set is cloned.

Added ve.ce.Surface.areAnnotationsCorrect() to compare either
annotations to the left or right to the insertionAnnotations.

Also use compareTo() and getComparableAnnotations() rather than
comparing by name, and fix SurfaceFragment.annotateContent() to
actually be selective when clearing rather than clearing everything.

Change-Id: I6116afa2e176daa0a0f2103a551501426829e2a6
2013-05-06 15:53:29 -07:00

110 lines
2.9 KiB
JavaScript

/*!
* VisualEditor AnnotationAction class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Annotation action.
*
* @class
* @extends ve.Action
* @constructor
* @param {ve.Surface} surface Surface to act on
*/
ve.AnnotationAction = function VeAnnotationAction( surface ) {
// Parent constructor
ve.Action.call( this, surface );
};
/* Inheritance */
ve.inheritClass( ve.AnnotationAction, ve.Action );
/* Static Properties */
/**
* List of allowed methods for the action.
*
* @static
* @property
*/
ve.AnnotationAction.static.methods = ['set', 'clear', 'toggle', 'clearAll'];
/* Methods */
/**
* Set an annotation.
*
* @method
* @param {string} name Annotation name, for example: 'textStyle/bold'
* @param {Object} [data] Additional annotation data
*/
ve.AnnotationAction.prototype.set = function ( name, data ) {
this.surface.getModel().getFragment().annotateContent( 'set', name, data );
};
/**
* Clear an annotation.
*
* @method
* @param {string} name Annotation name, for example: 'textStyle/bold'
* @param {Object} [data] Additional annotation data
*/
ve.AnnotationAction.prototype.clear = function ( name, data ) {
this.surface.getModel().getFragment().annotateContent( 'clear', name, data );
};
/**
* Toggle an annotation.
*
* If the selected text is completely covered with the annotation already the annotation will be
* cleared. Otherwise the annotation will be set.
*
* @method
* @param {string} name Annotation name, for example: 'textStyle/bold'
* @param {Object} [data] Additional annotation data
*/
ve.AnnotationAction.prototype.toggle = function ( name, data ) {
var existingAnnotations,
surfaceModel = this.surface.getModel(),
fragment = surfaceModel.getFragment(),
annotation = ve.dm.annotationFactory.create( name, data );
if ( !fragment.getRange().isCollapsed() ) {
fragment.annotateContent(
fragment.getAnnotations().containsComparable( annotation ) ? 'clear' : 'set', name, data
);
} else {
existingAnnotations = surfaceModel.getInsertionAnnotations().getComparableAnnotations( annotation );
if ( existingAnnotations.isEmpty() ) {
surfaceModel.addInsertionAnnotations( annotation );
} else {
surfaceModel.removeInsertionAnnotations( existingAnnotations );
}
}
};
/**
* Clear all annotations.
*
* @method
*/
ve.AnnotationAction.prototype.clearAll = function () {
var i, len, arr,
fragment = this.surface.getModel().getFragment(),
annotations = fragment.getAnnotations( true );
arr = annotations.get();
// TODO: Allow multiple annotations to be set or cleared by ve.dm.SurfaceFragment, probably
// using an annotation set and ideally building a single transaction
for ( i = 0, len = arr.length; i < len; i++ ) {
fragment.annotateContent( 'clear', arr[i].name, arr[i].data );
}
};
/* Registration */
ve.actionFactory.register( 'annotation', ve.AnnotationAction );