mediawiki-extensions-Visual.../modules/ve/dm/ve.dm.SurfaceFragment.js

692 lines
20 KiB
JavaScript
Raw Normal View History

/**
* VisualEditor data model Fragment class.
*
* @copyright 2011-2012 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* DataModel document fragment.
*
* @class
* @constructor
* @param {ve.dm.Surface} surface Target surface
* @param {ve.Range} [range] Range within target document, current selection used by default
* @param {Boolean} [noAutoSelect] Update the surface's selection when making changes
*/
ve.dm.SurfaceFragment = function VeDmSurfaceFragment( surface, range, noAutoSelect ) {
// Short-circuit for missing-surface null fragment
if ( !surface ) {
return this;
}
// Properties
this.range = range && range instanceof ve.Range ? range : surface.getSelection();
// Short-circuit for invalid range null fragment
if ( !this.range ) {
return this;
}
this.surface = surface;
this.document = surface.getDocument();
this.noAutoSelect = !!noAutoSelect;
// Events
surface.on( 'transact', ve.bind( this.onTransact, this ) );
// Initialization
var length = this.document.getLength();
this.range = new ve.Range(
// Clamp range to valid document offsets
Math.min( Math.max( this.range.from, 0 ), length ),
Math.min( Math.max( this.range.to, 0 ), length )
);
};
Fixed inspector behavior ve.ui.Inspector * Removed disabled state and interfaces - this isn't needed * Renamed prepareSelection to onInitialize * Using event emitter to run onInitialize, onOpen and onClose methods * Left removal up to the child class to handle in the onClose method * Replaced calls on context to close inspector to calling close directly * Renamed prepareSelection stub to onInitialize * Emitting initialize event from within the open method * Added recursion guarding to close method * Changed the close method's argument to be remove instead of accept - the more common case is to save changes, and the only time you wouldn't save changes is if you were to remove the annotation * Moved focus restore to close method ve.ui.Context * Moved the majority of the code in openInspector and closeInspector to event handlers for onInspectorOpen and onInspectorClose * Updated calls to closeInspector re: accept->remove argument change ve.ui.LinkInspector * Renamed prepareSelection to onInitialize and rewrote logic and documentation * Removed unused onLocationInputChange method * Moved restore focus (now it's in the inspector base class) ve.dm.SurfaceFragment * Added word mode for expandRange ve.dm.Surface * Added locking/unlocking while processing transactions - this was not an issue before because this was effectively being done manually throughout ce (which needs to be cleaned up) but once we started using the content action to insert content dm and ce started playing off each other and inserting in a loop - we already do this for undo/redo so it makes sense to do it here as well ve.InspectorAction * Updated arguments re: close method's accept->remove argument change Change-Id: I38995d4101fda71bfb2e6fe516603507ce820937
2012-11-20 22:51:24 +00:00
/* Static Members */
ve.dm.SurfaceFragment.static = {};
/* Methods */
/**
* Responds to transactions being processed on the document.
*
* This keeps the range of this fragment valid, even while other transactions are being processed.
*
* @method
* @param {ve.dm.Transaction[]} txs Transactions that have just been processed
*/
ve.dm.SurfaceFragment.prototype.onTransact = function ( txs ) {
for ( var i = 0; i < txs.length; i++ ) {
this.range = txs[i].translateRange( this.range );
}
};
/**
* Gets the surface this fragment is a part of.
*
* @method
* @returns {ve.dm.Surface} Surface of fragment
*/
ve.dm.SurfaceFragment.prototype.getSurface = function () {
return this.surface;
};
/**
* Gets the document of the surface this fragment is a part of.
*
* @method
* @returns {ve.dm.Document} Document of surface of fragment
*/
ve.dm.SurfaceFragment.prototype.getDocument = function () {
return this.document;
};
/**
* Gets the range of this fragment within the surface.
*
* @method
* @returns {ve.Range} Surface range
*/
ve.dm.SurfaceFragment.prototype.getRange = function () {
return this.range.clone();
};
/**
* Checks if this is a null fragment.
*
* @method
* @returns {Boolean} Fragment is a null fragment
*/
ve.dm.SurfaceFragment.prototype.isNull = function () {
return this.surface === undefined;
};
/**
* Gets a new fragment with an adjusted position
*
* @method
* @param {Number} [start] Adjustment for start position
* @param {Number} [end] Adjustment for end position
* @returns {ve.dm.SurfaceFragment} Adjusted fragment
*/
ve.dm.SurfaceFragment.prototype.adjustRange = function ( start, end ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
return new ve.dm.SurfaceFragment(
this.surface,
new ve.Range( this.range.start + ( start || 0 ), this.range.end + ( end || 0 ) ),
this.noAutoSelect
);
};
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
/**
* Gets a new fragment with a truncated length.
*
* @method
* @param {Number} limit Maximum length of range (negative for left-side truncation)
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
* @returns {ve.dm.SurfaceFragment} Truncated fragment
*/
ve.dm.SurfaceFragment.prototype.truncateRange = function ( limit ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
return new ve.dm.SurfaceFragment(
this.surface,
this.range.truncate( limit ),
this.noAutoSelect
);
};
/**
* Gets a new fragment with a zero-length selection at the start offset.
*
* @method
* @returns {ve.dm.SurfaceFragment} Collapsed fragment
*/
ve.dm.SurfaceFragment.prototype.collapseRange = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
return new ve.dm.SurfaceFragment(
this.surface, new ve.Range( this.range.start ), this.noAutoSelect
);
};
/**
* Gets a new fragment with a range that no longer includes leading and trailing whitespace.
*
* @method
* @returns {ve.dm.SurfaceFragment} Trimmed fragment
*/
ve.dm.SurfaceFragment.prototype.trimRange = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
// If range is only whitespace
if ( this.document.getText( this.range ).trim().length === 0 ) {
// Collapse range
return new ve.dm.SurfaceFragment(
this.surface, new ve.Range( this.range.start ), this.noAutoSelect
);
}
return new ve.dm.SurfaceFragment(
this.surface, this.document.trimOuterSpaceFromRange( this.range ), this.noAutoSelect
);
};
/**
* Gets a new fragment that covers an expanded range of the document.
*
* @method
* @param {String} [scope=parent] Method of expansion:
Fixed inspector behavior ve.ui.Inspector * Removed disabled state and interfaces - this isn't needed * Renamed prepareSelection to onInitialize * Using event emitter to run onInitialize, onOpen and onClose methods * Left removal up to the child class to handle in the onClose method * Replaced calls on context to close inspector to calling close directly * Renamed prepareSelection stub to onInitialize * Emitting initialize event from within the open method * Added recursion guarding to close method * Changed the close method's argument to be remove instead of accept - the more common case is to save changes, and the only time you wouldn't save changes is if you were to remove the annotation * Moved focus restore to close method ve.ui.Context * Moved the majority of the code in openInspector and closeInspector to event handlers for onInspectorOpen and onInspectorClose * Updated calls to closeInspector re: accept->remove argument change ve.ui.LinkInspector * Renamed prepareSelection to onInitialize and rewrote logic and documentation * Removed unused onLocationInputChange method * Moved restore focus (now it's in the inspector base class) ve.dm.SurfaceFragment * Added word mode for expandRange ve.dm.Surface * Added locking/unlocking while processing transactions - this was not an issue before because this was effectively being done manually throughout ce (which needs to be cleaned up) but once we started using the content action to insert content dm and ce started playing off each other and inserting in a loop - we already do this for undo/redo so it makes sense to do it here as well ve.InspectorAction * Updated arguments re: close method's accept->remove argument change Change-Id: I38995d4101fda71bfb2e6fe516603507ce820937
2012-11-20 22:51:24 +00:00
* 'word': Expands to cover the nearest word by looking for word boundary characters
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
* 'annotation': Expands to cover a given annotation (argument) within the current range
* 'root': Expands to cover the entire document
* 'siblings': Expands to cover all sibling nodes
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
* 'closest': Expands to cover the closest common ancestor node of a give type (argument)
* 'parent': Expands to cover the closest common parent node
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
* @param {Mixed} [type] Parameter to use with scope method if needed
* @returns {ve.dm.SurfaceFragment} Expanded fragment
*/
ve.dm.SurfaceFragment.prototype.expandRange = function ( scope, type ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
Fix even more inspector issues, and some ce ones as well ve.dm.SurfaceFragment * Removed flawed implementation of word mode for expandRange method and made use of new getNearestWordBoundary method in the document model ve.dm.Surface * Got rid of useInsertionAnnotations, which allowed disabling and enabling of insertion annotations - this isn't needed anymore because it was just a dirty hack around the improper starting and stopping of surface observer that's now solved more elegantly by emitting lock and unlock before committing or rolling back transactions * Get annotations from the first character of the selection if the selection is not collapsed * Only emit annotationChange events if it really changed ve.dm.Document * Added getNearestWordBoundary method which performs the work behind the surface fragment expandRange word method ve.ce.SurfaceObserver * Allow using an initial selection to avoid the observer thinking the selection has changed just because it started out with null * Only emit selectionChange event if there was a meaningful change ve.ce.Surface * (bug 42279) Only annotate characters if insertion annotations are not empty * Remove manual locking and unlocking, this is now done inside the change method of surface model * Provide an initial selection to surface observer when we clear it * Remove enabling and disabling of insertionAnnotations, this isn't needed anymore * Stop/start observer on key presses that execute actions as well as those that have no special handling ve.ce.Document * Make getNodeFromOffsetand getSlugAtOffset return null when given -1 as an offset Change-Id: Ibf6b26de299e54ae8688a2653bf5d5538927f8c3
2012-11-21 21:22:29 +00:00
var range, node, nodes, parent;
switch ( scope || 'parent' ) {
Fixed inspector behavior ve.ui.Inspector * Removed disabled state and interfaces - this isn't needed * Renamed prepareSelection to onInitialize * Using event emitter to run onInitialize, onOpen and onClose methods * Left removal up to the child class to handle in the onClose method * Replaced calls on context to close inspector to calling close directly * Renamed prepareSelection stub to onInitialize * Emitting initialize event from within the open method * Added recursion guarding to close method * Changed the close method's argument to be remove instead of accept - the more common case is to save changes, and the only time you wouldn't save changes is if you were to remove the annotation * Moved focus restore to close method ve.ui.Context * Moved the majority of the code in openInspector and closeInspector to event handlers for onInspectorOpen and onInspectorClose * Updated calls to closeInspector re: accept->remove argument change ve.ui.LinkInspector * Renamed prepareSelection to onInitialize and rewrote logic and documentation * Removed unused onLocationInputChange method * Moved restore focus (now it's in the inspector base class) ve.dm.SurfaceFragment * Added word mode for expandRange ve.dm.Surface * Added locking/unlocking while processing transactions - this was not an issue before because this was effectively being done manually throughout ce (which needs to be cleaned up) but once we started using the content action to insert content dm and ce started playing off each other and inserting in a loop - we already do this for undo/redo so it makes sense to do it here as well ve.InspectorAction * Updated arguments re: close method's accept->remove argument change Change-Id: I38995d4101fda71bfb2e6fe516603507ce820937
2012-11-20 22:51:24 +00:00
case 'word':
range = new ve.Range(
Fix even more inspector issues, and some ce ones as well ve.dm.SurfaceFragment * Removed flawed implementation of word mode for expandRange method and made use of new getNearestWordBoundary method in the document model ve.dm.Surface * Got rid of useInsertionAnnotations, which allowed disabling and enabling of insertion annotations - this isn't needed anymore because it was just a dirty hack around the improper starting and stopping of surface observer that's now solved more elegantly by emitting lock and unlock before committing or rolling back transactions * Get annotations from the first character of the selection if the selection is not collapsed * Only emit annotationChange events if it really changed ve.dm.Document * Added getNearestWordBoundary method which performs the work behind the surface fragment expandRange word method ve.ce.SurfaceObserver * Allow using an initial selection to avoid the observer thinking the selection has changed just because it started out with null * Only emit selectionChange event if there was a meaningful change ve.ce.Surface * (bug 42279) Only annotate characters if insertion annotations are not empty * Remove manual locking and unlocking, this is now done inside the change method of surface model * Provide an initial selection to surface observer when we clear it * Remove enabling and disabling of insertionAnnotations, this isn't needed anymore * Stop/start observer on key presses that execute actions as well as those that have no special handling ve.ce.Document * Make getNodeFromOffsetand getSlugAtOffset return null when given -1 as an offset Change-Id: Ibf6b26de299e54ae8688a2653bf5d5538927f8c3
2012-11-21 21:22:29 +00:00
this.document.getNearestWordBoundary( this.range.start, -1 ),
this.document.getNearestWordBoundary( this.range.end, 1 )
Fixed inspector behavior ve.ui.Inspector * Removed disabled state and interfaces - this isn't needed * Renamed prepareSelection to onInitialize * Using event emitter to run onInitialize, onOpen and onClose methods * Left removal up to the child class to handle in the onClose method * Replaced calls on context to close inspector to calling close directly * Renamed prepareSelection stub to onInitialize * Emitting initialize event from within the open method * Added recursion guarding to close method * Changed the close method's argument to be remove instead of accept - the more common case is to save changes, and the only time you wouldn't save changes is if you were to remove the annotation * Moved focus restore to close method ve.ui.Context * Moved the majority of the code in openInspector and closeInspector to event handlers for onInspectorOpen and onInspectorClose * Updated calls to closeInspector re: accept->remove argument change ve.ui.LinkInspector * Renamed prepareSelection to onInitialize and rewrote logic and documentation * Removed unused onLocationInputChange method * Moved restore focus (now it's in the inspector base class) ve.dm.SurfaceFragment * Added word mode for expandRange ve.dm.Surface * Added locking/unlocking while processing transactions - this was not an issue before because this was effectively being done manually throughout ce (which needs to be cleaned up) but once we started using the content action to insert content dm and ce started playing off each other and inserting in a loop - we already do this for undo/redo so it makes sense to do it here as well ve.InspectorAction * Updated arguments re: close method's accept->remove argument change Change-Id: I38995d4101fda71bfb2e6fe516603507ce820937
2012-11-20 22:51:24 +00:00
);
break;
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
case 'annotation':
range = this.document.getAnnotatedRangeFromSelection( this.range, type );
// Adjust selection if it does not contain the annotated range
if ( this.range.start > range.start || this.range.end < range.end ) {
// Maintain range direction
if ( this.range.from > this.range.to ) {
(bug 42925) Inspector doesn't open properly ve.Range * Rewrote truncate so that it works as expected, truncation should always reduce the length using the start/end values, not the from/to values ve.ui.Inspector * Added a comment about where the name argument to onBeforeInspectorOpen comes from, since it's a little bit confusing on first read (and I wrote it!) * Calling onInitialize, onOpen and onClose methods directly, since we need to control the before or after-ness of listeners getting in there and doing their stuff - plus it's more direct * Removed onRemove stub, which is never actually called * Added before/after versions of initialize, open and close events * Got rid of recursion guard since we don't need it anymore thanks to changes made in ve.dm.Surface (see below) ve.ui.Context * Updated event names to deal with new before/after naming of initialize, open and close events * Removed fade-in logic since fading in doesn't even work anymore - since now we now annotate first, then open the inspector, the menu will actually exist and be open when we open the inspector even though you don't see it because it's quickly obscured ve.ui.LinkInspector * Made fragments non-auto selecting, in the case of onInitialize we actually call select(), which is silly since we were using an auto-selecting fragment - it's clear that this was a mistake ve.dm.Surface * Moved locking (polling stop and start) to the far outside edges of the change method * I need a lot of eyes and testing on this change, it seems OK to me, but I'm suspicious that it may have side effects * What was happening is that selection changes were being applied and then the poll was picking them up, and then the selection was coming in again as a change, but it wasn't a change at all, it was just feedback - this change event was then closing the inspector the instant it was opened - the odd part was that this only occurred when you selected backwards, which seems to be caused by the range being normalized, so it looked like a new selection even though it wasn't ve.dm.Document * trimOuterSpace from Range didn't consider annotated spaces to be spaces, by using the [0] trick (first character of a plain text character string or first element in an annotated character's array both are the character's value - but elements don't have a property named '0' so it skips those safely as well) we can always get the right value for comparison Change-Id: I0873d906c058203b83b8d4bbe5a4b274f05a26fd
2012-12-10 21:36:28 +00:00
range = range.flip();
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
}
} else {
// Otherwise just keep the range as is
range = this.range.clone();
}
break;
case 'root':
range = new ve.Range( 0, this.document.getData().length );
break;
case 'siblings':
// Grow range to cover all siblings
nodes = this.document.selectNodes( this.range, 'siblings' );
if ( nodes.length === 1 ) {
range = nodes[0].node.getOuterRange();
} else {
range = new ve.Range(
nodes[0].node.getOuterRange().start,
nodes[nodes.length - 1].node.getOuterRange().end
);
}
break;
case 'closest':
// Grow range to cover closest common ancestor node of given type
node = this.document.selectNodes( this.range, 'siblings' )[0].node;
parent = node.getParent();
while ( parent && parent.getType() !== type ) {
node = parent;
parent = parent.getParent();
}
if ( !parent ) {
return new ve.dm.SurfaceFragment( null );
}
range = parent.getOuterRange();
break;
case 'parent':
// Grow range to cover the closest common parent node
node = this.document.selectNodes( this.range, 'siblings' )[0].node;
parent = node.getParent();
if ( !parent ) {
return new ve.dm.SurfaceFragment( null );
}
range = parent.getOuterRange();
break;
default:
throw new Error( 'Invalid scope argument: ' + scope );
}
return new ve.dm.SurfaceFragment( this.surface, range, this.noAutoSelect );
};
/**
* Checks if the surface's selection will be updated automatically when changes are made.
*
* @method
* @returns {Boolean} Will automatically update surface selection
*/
ve.dm.SurfaceFragment.prototype.willAutoSelect = function () {
return !this.noAutoSelect;
};
/**
* Get data for the fragment.
*
* @method
* @param {Boolean} [deep] Get a deep copy of the data
* @returns {Array} Fragment data
*/
ve.dm.SurfaceFragment.prototype.getData = function ( deep ) {
// Handle null fragment
if ( !this.surface ) {
return [];
}
return this.document.getData( this.range, deep );
};
/**
* Get plain text for the fragment.
*
* @method
* @returns {Array} Fragment text
*/
ve.dm.SurfaceFragment.prototype.getText = function () {
// Handle null fragment
if ( !this.surface ) {
return '';
}
var i, length,
text = '',
data = this.document.getData( this.range );
for ( i = 0, length = data.length; i < length; i++ ) {
if ( data[i].type === undefined ) {
// Annotated characters have a string at index 0, plain characters are 1-char strings
text += typeof data[i] === 'string' ? data[i] : data[i][0];
}
}
return text;
};
/**
* Get annotations in fragment.
*
* By default, this will only get annotations that completely cover the fragment. Use the {all}
* argument to get all annotations that occur within the fragment.
*
* @method
* @param {Boolean} [all] Get annotations cover some of the fragment
* @returns {ve.AnnotationSet} All annotation objects range is covered by
*/
ve.dm.SurfaceFragment.prototype.getAnnotations = function ( all ) {
// Handle null fragment
if ( !this.surface ) {
return new ve.AnnotationSet();
}
if ( this.range.getLength() ) {
return this.document.getAnnotationsFromRange( this.range, all );
} else {
return this.surface.getInsertionAnnotations();
}
};
/**
* Get all leaf nodes covered by the fragment.
*
* @see {ve.Document.selectNodes} for more information about the return value.
*
* @method
* @returns {Array} List of nodes and related information
*/
ve.dm.SurfaceFragment.prototype.getLeafNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return [];
}
return this.document.selectNodes( this.range, 'leaves' );
};
/**
* Get nodes covered by the fragment.
*
* Does not descend into nodes that are entirely covered by the range. The result is
* similar to that of {ve.dm.SurfaceFragment.prototype.getLeafNodes} except that if a node is
* entirely covered, its children aren't returned separately.
*
* @see {ve.Document.selectNodes} for more information about the return value.
*
* @method
* @returns {Array} List of nodes and related information
*/
ve.dm.SurfaceFragment.prototype.getCoveredNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return [];
}
return this.document.selectNodes( this.range, 'coveredNodes' );
};
/**
* Get nodes covered by the fragment.
*
* Includes adjacent siblings covered by the range, descending if the range is in a single node.
*
* @see {ve.Document.selectNodes} for more information about the return value.
*
* @method
* @returns {Array} List of nodes and related information
*/
ve.dm.SurfaceFragment.prototype.getSiblingNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return [];
}
return this.document.selectNodes( this.range, 'siblings' );
};
/**
* Chooses whether to automatically update the surface selection when making changes.
*
* @method
* @param {Boolean} [value=true] Automatically update surface selection
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.setAutoSelect = function ( value ) {
this.noAutoSelect = !value;
return this;
};
/**
* Applies the fragment's range to the surface as a selection.
*
* @method
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.select = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
this.surface.change( null, this.range );
return this;
};
/**
* Applies an annotation to content in the fragment.
*
* To avoid problems identified in bug 33108, use the {ve.dm.SurfaceFragment.trimRange} method.
*
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
* TODO: Optionally take an annotation set instead of name and data arguments and set/clear multiple
* annotations in a single transaction.
*
* @method
* @param {String} method Mode of annotation, either 'set' or 'clear'
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
* @param {String|ve.dm.Annotation} name Annotation name, for example: 'textStyle/bold' or
* Annotation object
* @param {Object} [data] Additional annotation data (not used if annotation object is given)
* @returns {ve.dm.SurfaceFragment} This fragment
*/
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
ve.dm.SurfaceFragment.prototype.annotateContent = function ( method, name, data ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
// Extract annotation information
if ( name instanceof ve.dm.Annotation ) {
data = name.data;
name = name.name;
}
var tx,
The great inspector and context rewrite of 2012 ve.AnnotationAction * Added filter to the clearAll method to allow clearing all matching annotations only ve.dm.Document * Some variable renaming for consistency ve.dm.SurfaceFragment * Added truncateRange method * Added annotation scope to expandRange method * Added support for passing an annotation object into annotateContent method * Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class * Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found ve.ui.LinkInspector * Moved most of the functionality elsewhere * General reorganization * Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow * Check for annotation object before extracting target information from it * Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined' icons.ai, inspector.png, inspector.svg * Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses ve.ui.Inspector.Icons * Added inspector icon * Renamed clear icon to remove to match it's actual image ve.ui.Context * Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others * Now always listening to resize events on the window rather than only while document is focused * Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore * Lots of cleanup and reorganization * No need to fallback to empty array since getInspectorsForAnnotations does so already * Only consider fully-covered annotations for inspectors ve.ui.Frame * Simplified the constructor by introducing the createFrame method * General cleanup * Typo fixes ve.ui.Inspector * Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.) * Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil) * Added getMatchingAnnotations method for convenience * Added prepareSelection stub * Lots of cleanup and documentation * Type pattern is now defined in base class * Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do * Removed checks for onOpen or onClose methods since they are now noop stubs and are always there * Added stub and removed checks for onRemove * Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance * Only consider fully-covered annotations when getting matching annotations ve.ui.InspectorFactory * Depending on type pattern now since it's always there * Added getInspectorsForAnnotations method * Return empty array if annotation set is empty VisualEditor, VisualEditor.i18n * Added default inspector message Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
2012-11-16 20:40:05 +00:00
annotation = ve.dm.annotationFactory.create( name );
// HACK: This seems wrong, the way we create annotations should be refactored
if ( data ) {
annotation.data = data;
}
if ( this.range.getLength() ) {
// Apply to selection
tx = ve.dm.Transaction.newFromAnnotation( this.document, this.range, method, annotation );
this.surface.change( tx, !this.noAutoSelect && tx.translateRange( this.range ) );
} else {
// Apply annotation to stack
if ( method === 'set' ) {
this.surface.addInsertionAnnotation( annotation );
} else if ( method === 'clear' ) {
this.surface.removeInsertionAnnotation( annotation );
}
}
return this;
};
/**
* Remove content in the fragment and insert content before it.
*
* This will move the fragment's range to the end of the insertion and make it zero-length.
*
* @method
* @param {String|Array} content Content to insert, can be either a string or array of data
* @param {Boolean} annotate Content should be automatically annotated to match surrounding content
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.insertContent = function ( content, annotate ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
var tx, annotations;
if ( this.range.getLength() ) {
this.removeContent();
}
// Auto-convert content to array of plain text characters
if ( typeof content === 'string' ) {
content = content.split( '' );
}
if ( content.length ) {
if ( annotate ) {
annotations = this.document.getAnnotationsFromOffset( this.range.start - 1 );
if ( annotations.getLength() > 0 ) {
ve.dm.Document.addAnnotationsToData( content, annotations );
}
}
tx = ve.dm.Transaction.newFromInsertion( this.document, this.range.start, content );
this.surface.change( tx, !this.noAutoSelect && tx.translateRange( this.range ) );
}
return this;
};
/**
* Removes content in the fragment.
*
* @method
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.removeContent = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
var tx;
if ( this.range.getLength() ) {
tx = ve.dm.Transaction.newFromRemoval( this.document, this.range );
// this.range will be translated via the onTransact event handler
this.surface.change( tx, !this.noAutoSelect && tx.translateRange( this.range ) );
// Check if the range didn't get collapsed automatically - this will occur when removing
// content across un-mergable nodes because the delete only strips out content leaving
// structure at the beginning and end of the range in place
if ( this.range.getLength() ) {
// Collapse the range manually
this.range = new ve.Range( this.range.start );
if ( !this.noAutoSelect ) {
// Update the surface selection
this.surface.change( null, this.range );
}
}
}
return this;
};
/**
* Converts each content branch in the fragment from one type to another.
*
* @method
* @param {String} type Element type to convert to
* @param {Object} [attr] Initial attributes for new element
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.convertNodes = function ( type, attr ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
var tx =
ve.dm.Transaction.newFromContentBranchConversion( this.document, this.range, type, attr );
this.surface.change( tx, !this.noAutoSelect && tx.translateRange( this.range ) );
return this;
};
/**
* Wraps each node in the fragment with one or more elements.
*
* A wrapper object is a linear model element; a plain object containing a type property and an
* optional attributes property.
*
* Example:
* // fragment is a selection of: <p>a</p><p>b</p>
* fragment.wrapNodes(
* [{ 'type': 'list', 'attributes': { 'style': 'bullet' } }, { 'type': 'listItem' }]
* )
* // fragment is now a selection of: <ul><li><p>a</p></li></ul><ul><li><p>b</p></li></ul>
*
* @method
* @param {Object|Object[]} wrapper Wrapper object, or array of wrapper objects (see above)
* @param {String} wrapper.type Node type of wrapper
* @param {Object} [wrapper.attributes] Attributes of wrapper
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.wrapNodes = function ( wrapper ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
if ( !ve.isArray( wrapper ) ) {
wrapper = [wrapper];
}
var tx = ve.dm.Transaction.newFromWrap( this.document, this.range, [], [], [], wrapper );
this.range = tx.translateRange( this.range );
this.surface.change( tx, !this.noAutoSelect && this.range );
return this;
};
/**
* Unwraps each node in the fragment out of one or more elements.
*
* @method
* @param {String|String[]} type Node types to unwrap, or array of node types to unwrap
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.unwrapNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
// TODO: Implement
return this;
};
/**
* Changes the wrapping of each node in the fragment from one type to another.
*
* A wrapper object is a linear model element; a plain object containing a type property and an
* optional attributes property.
*
* @method
* @param {String|String[]} type Node types to unwrap, or array of node types to unwrap
* @param {Object|Object[]} wrapper Wrapper object, or array of wrapper objects (see above)
* @param {String} wrapper.type Node type of wrapper
* @param {Object} [wrapper.attributes] Attributes of wrapper
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.rewrapNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
// TODO: Implement
return this;
};
/**
* Wraps nodes in the fragment with one or more elements.
*
* A wrapper object is a linear model element; a plain object containing a type property and an
* optional attributes property.
*
* Example:
* // fragment is a selection of: <p>a</p><p>b</p>
* fragment.wrapAllNodes(
* [{ 'type': 'list', 'attributes': { 'style': 'bullet' } }, { 'type': 'listItem' }]
* )
* // fragment is now a selection of: <ul><li><p>a</p><p>b</p></li></ul>
*
* @method
* @param {Object|Object[]} wrapper Wrapper object, or array of wrapper objects (see above)
* @param {String} wrapper.type Node type of wrapper
* @param {Object} [wrapper.attributes] Attributes of wrapper
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.wrapAllNodes = function ( wrapper ) {
// Handle null fragment
if ( !this.surface ) {
return this;
}
if ( !ve.isArray( wrapper ) ) {
wrapper = [wrapper];
}
var tx = ve.dm.Transaction.newFromWrap( this.document, this.range, [], wrapper, [], [] );
this.range = tx.translateRange( this.range );
this.surface.change( tx, !this.noAutoSelect && this.range );
return this;
};
/**
* Unwraps nodes in the fragment out of one or more elements.
*
* TODO: Figure out what the arguments for this function should be
*
* @method
* @param {String|String[]} type Node types to unwrap, or array of node types to unwrap
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.unwrapAllNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
// TODO: Implement
return this;
};
/**
* Changes the wrapping of nodes in the fragment from one type to another.
*
* A wrapper object is a linear model element; a plain object containing a type property and an
* optional attributes property.
*
* @method
* @param {String|String[]} type Node types to unwrap, or array of node types to unwrap
* @param {Object|Object[]} wrapper Wrapper object, or array of wrapper objects (see above)
* @param {String} wrapper.type Node type of wrapper
* @param {Object} [wrapper.attributes] Attributes of wrapper
* @returns {ve.dm.SurfaceFragment} This fragment
*/
ve.dm.SurfaceFragment.prototype.rewrapAllNodes = function () {
// Handle null fragment
if ( !this.surface ) {
return this;
}
// TODO: Implement
return this;
};