JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
/*!
|
2013-01-15 23:38:49 +00:00
|
|
|
* VisualEditor DataModel Surface class.
|
2012-07-19 21:25:16 +00:00
|
|
|
*
|
2013-02-19 23:37:34 +00:00
|
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
2012-07-19 00:11:26 +00:00
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
2011-11-02 21:00:55 +00:00
|
|
|
/**
|
2012-06-20 01:20:28 +00:00
|
|
|
* DataModel surface.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @class
|
2013-10-15 11:58:04 +00:00
|
|
|
* @mixins OO.EventEmitter
|
2013-05-01 22:21:32 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @constructor
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document model to create surface for
|
2011-11-02 21:00:55 +00:00
|
|
|
*/
|
2012-09-06 23:15:55 +00:00
|
|
|
ve.dm.Surface = function VeDmSurface( doc ) {
|
2013-05-01 22:21:32 +00:00
|
|
|
// Mixin constructors
|
2013-10-15 11:58:04 +00:00
|
|
|
OO.EventEmitter.call( this );
|
2012-09-17 23:53:03 +00:00
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
// Properties
|
2012-06-20 01:20:28 +00:00
|
|
|
this.documentModel = doc;
|
2013-04-11 21:49:17 +00:00
|
|
|
this.metaList = new ve.dm.MetaList( this );
|
2013-09-17 23:36:49 +00:00
|
|
|
this.selection = new ve.Range( 1, 1 );
|
2012-12-03 19:36:09 +00:00
|
|
|
this.selectedNodes = {};
|
2013-12-08 20:25:53 +00:00
|
|
|
this.newTransactions = [];
|
|
|
|
this.undoStack = [];
|
2011-12-09 23:52:41 +00:00
|
|
|
this.undoIndex = 0;
|
2012-06-20 01:20:28 +00:00
|
|
|
this.historyTrackingInterval = null;
|
2013-03-20 22:35:05 +00:00
|
|
|
this.insertionAnnotations = new ve.dm.AnnotationSet( this.documentModel.getStore() );
|
2012-12-12 00:28:39 +00:00
|
|
|
this.enabled = true;
|
2013-10-08 15:43:10 +00:00
|
|
|
this.transacting = false;
|
|
|
|
this.queueingContextChanges = false;
|
|
|
|
this.contextChangeQueued = false;
|
|
|
|
|
|
|
|
// Events
|
|
|
|
this.documentModel.connect( this, { 'transact': 'onDocumentTransact' } );
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
Object management: Object create/inherit/clone utilities
* For the most common case:
- replace ve.extendClass with ve.inheritClass (chose slightly
different names to detect usage of the old/new one, and I
like 'inherit' better).
- move it up to below the constructor, see doc block for why.
* Cases where more than 2 arguments were passed to
ve.extendClass are handled differently depending on the case.
In case of a longer inheritance tree, the other arguments
could be omitted (like in "ve.ce.FooBar, ve.FooBar,
ve.Bar". ve.ce.FooBar only needs to inherit from ve.FooBar,
because ve.ce.FooBar inherits from ve.Bar).
In the case of where it previously had two mixins with
ve.extendClass(), either one becomes inheritClass and one
a mixin, both to mixinClass().
No visible changes should come from this commit as the
instances still all have the same visible properties in the
end. No more or less than before.
* Misc.:
- Be consistent in calling parent constructors in the
same order as the inheritance.
- Add missing @extends and @param documentation.
- Replace invalid {Integer} type hint with {Number}.
- Consistent doc comments order:
@class, @abstract, @constructor, @extends, @params.
- Fix indentation errors
A fairly common mistake was a superfluous space before the
identifier on the assignment line directly below the
documentation comment.
$ ack "^ [^*]" --js modules/ve
- Typo "Inhertiance" -> "Inheritance".
- Replacing the other confusing comment "Inheritance" (inside
the constructor) with "Parent constructor".
- Add missing @abstract for ve.ui.Tool.
- Corrected ve.FormatDropdownTool to ve.ui.FormatDropdownTool.js
- Add function names to all @constructor functions. Now that we
have inheritance it is important and useful to have these
functions not be anonymous.
Example of debug shot: http://cl.ly/image/1j3c160w3D45
Makes the difference between
< documentNode;
> ve_dm_DocumentNode
...
: ve_dm_BranchNode
...
: ve_dm_Node
...
: ve_dm_Node
...
: Object
...
without names (current situation):
< documentNode;
> Object
...
: Object
...
: Object
...
: Object
...
: Object
...
though before this commit, it really looks like this
(flattened since ve.extendClass really did a mixin):
< documentNode;
> Object
...
...
...
Pattern in Sublime (case-sensitive) to find nameless
constructor functions:
"^ve\..*\.([A-Z])([^\.]+) = function \("
Change-Id: Iab763954fb8cf375900d7a9a92dec1c755d5407e
2012-09-05 06:07:47 +00:00
|
|
|
/* Inheritance */
|
|
|
|
|
2013-10-15 11:58:04 +00:00
|
|
|
OO.mixinClass( ve.dm.Surface, OO.EventEmitter );
|
Object management: Object create/inherit/clone utilities
* For the most common case:
- replace ve.extendClass with ve.inheritClass (chose slightly
different names to detect usage of the old/new one, and I
like 'inherit' better).
- move it up to below the constructor, see doc block for why.
* Cases where more than 2 arguments were passed to
ve.extendClass are handled differently depending on the case.
In case of a longer inheritance tree, the other arguments
could be omitted (like in "ve.ce.FooBar, ve.FooBar,
ve.Bar". ve.ce.FooBar only needs to inherit from ve.FooBar,
because ve.ce.FooBar inherits from ve.Bar).
In the case of where it previously had two mixins with
ve.extendClass(), either one becomes inheritClass and one
a mixin, both to mixinClass().
No visible changes should come from this commit as the
instances still all have the same visible properties in the
end. No more or less than before.
* Misc.:
- Be consistent in calling parent constructors in the
same order as the inheritance.
- Add missing @extends and @param documentation.
- Replace invalid {Integer} type hint with {Number}.
- Consistent doc comments order:
@class, @abstract, @constructor, @extends, @params.
- Fix indentation errors
A fairly common mistake was a superfluous space before the
identifier on the assignment line directly below the
documentation comment.
$ ack "^ [^*]" --js modules/ve
- Typo "Inhertiance" -> "Inheritance".
- Replacing the other confusing comment "Inheritance" (inside
the constructor) with "Parent constructor".
- Add missing @abstract for ve.ui.Tool.
- Corrected ve.FormatDropdownTool to ve.ui.FormatDropdownTool.js
- Add function names to all @constructor functions. Now that we
have inheritance it is important and useful to have these
functions not be anonymous.
Example of debug shot: http://cl.ly/image/1j3c160w3D45
Makes the difference between
< documentNode;
> ve_dm_DocumentNode
...
: ve_dm_BranchNode
...
: ve_dm_Node
...
: ve_dm_Node
...
: Object
...
without names (current situation):
< documentNode;
> Object
...
: Object
...
: Object
...
: Object
...
: Object
...
though before this commit, it really looks like this
(flattened since ve.extendClass really did a mixin):
< documentNode;
> Object
...
...
...
Pattern in Sublime (case-sensitive) to find nameless
constructor functions:
"^ve\..*\.([A-Z])([^\.]+) = function \("
Change-Id: Iab763954fb8cf375900d7a9a92dec1c755d5407e
2012-09-05 06:07:47 +00:00
|
|
|
|
2013-03-20 07:09:43 +00:00
|
|
|
/* Events */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @event select
|
2013-10-08 08:41:14 +00:00
|
|
|
* @param {ve.Range} selection
|
2013-03-20 07:09:43 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @event transact
|
|
|
|
* @param {ve.dm.Transaction[]} transactions Transactions that have just been processed
|
|
|
|
*/
|
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
/**
|
|
|
|
* @event documentUpdate
|
|
|
|
*
|
|
|
|
* Emitted when a transaction has been processed on the document and the selection has been
|
|
|
|
* translated to account for that transaction. You should only use this event if you need
|
|
|
|
* to access the selection; in most cases, you should use {ve.dm.Document#event-transact}.
|
|
|
|
*
|
|
|
|
* @param {ve.dm.Transaction} tx Transaction that was processed on the document
|
|
|
|
*/
|
|
|
|
|
2013-03-20 07:09:43 +00:00
|
|
|
/**
|
|
|
|
* @event contextChange
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @event history
|
|
|
|
*/
|
|
|
|
|
2011-11-02 21:00:55 +00:00
|
|
|
/* Methods */
|
|
|
|
|
2012-12-12 00:28:39 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Disable changes.
|
2012-12-12 00:28:39 +00:00
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.disable = function () {
|
|
|
|
this.stopHistoryTracking();
|
|
|
|
this.enabled = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Enable changes.
|
2012-12-12 00:28:39 +00:00
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.enable = function () {
|
|
|
|
this.enabled = true;
|
|
|
|
this.startHistoryTracking();
|
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Start tracking state changes in history.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.startHistoryTracking = function () {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2013-08-27 13:31:26 +00:00
|
|
|
if ( this.historyTrackingInterval === null ) {
|
|
|
|
this.historyTrackingInterval = setInterval( ve.bind( this.breakpoint, this ), 750 );
|
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Stop tracking state changes in history.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.stopHistoryTracking = function () {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2013-08-27 13:31:26 +00:00
|
|
|
if ( this.historyTrackingInterval !== null ) {
|
|
|
|
clearInterval( this.historyTrackingInterval );
|
|
|
|
this.historyTrackingInterval = null;
|
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Remove all states from history.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.purgeHistory = function () {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2013-08-27 13:34:55 +00:00
|
|
|
this.selection = new ve.Range( 0, 0 );
|
2013-12-08 20:25:53 +00:00
|
|
|
this.newTransactions = [];
|
|
|
|
this.undoStack = [];
|
2012-02-24 00:49:28 +00:00
|
|
|
this.undoIndex = 0;
|
2011-12-09 20:40:26 +00:00
|
|
|
};
|
2011-11-22 22:59:05 +00:00
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get a list of all history states.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-09-27 10:30:29 +00:00
|
|
|
* @returns {Object[]} List of transaction stacks
|
2012-10-24 22:21:54 +00:00
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.getHistory = function () {
|
2013-12-08 20:25:53 +00:00
|
|
|
if ( this.newTransactions.length > 0 ) {
|
|
|
|
return this.undoStack.slice( 0 ).concat( [{ 'transactions': this.newTransactions.slice( 0 ) }] );
|
2011-12-13 00:56:29 +00:00
|
|
|
} else {
|
2013-12-08 20:25:53 +00:00
|
|
|
return this.undoStack.slice( 0 );
|
2011-12-13 00:56:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-16 22:57:20 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get annotations that will be used upon insertion.
|
2012-11-16 22:57:20 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-06-27 21:56:16 +00:00
|
|
|
* @returns {ve.dm.AnnotationSet} Insertion anotations
|
2012-11-16 22:57:20 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.getInsertionAnnotations = function () {
|
|
|
|
return this.insertionAnnotations.clone();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Set annotations that will be used upon insertion.
|
2012-11-16 22:57:20 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-03-20 22:35:05 +00:00
|
|
|
* @param {ve.dm.AnnotationSet|null} Insertion anotations to use or null to disable them
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires contextChange
|
2012-11-16 22:57:20 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.setInsertionAnnotations = function ( annotations ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2013-05-01 18:36:32 +00:00
|
|
|
this.insertionAnnotations = annotations !== null ?
|
|
|
|
annotations.clone() :
|
|
|
|
new ve.dm.AnnotationSet( this.documentModel.getStore() );
|
|
|
|
|
2012-11-26 23:57:02 +00:00
|
|
|
this.emit( 'contextChange' );
|
2012-11-16 22:57:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Add an annotation to be used upon insertion.
|
2012-11-16 22:57:20 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-05-01 18:36:32 +00:00
|
|
|
* @param {ve.dm.Annotation|ve.dm.AnnotationSet} annotations Insertion annotation to add
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires contextChange
|
2012-11-16 22:57:20 +00:00
|
|
|
*/
|
2013-05-01 18:36:32 +00:00
|
|
|
ve.dm.Surface.prototype.addInsertionAnnotations = function ( annotations ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2013-05-01 18:36:32 +00:00
|
|
|
if ( annotations instanceof ve.dm.Annotation ) {
|
|
|
|
this.insertionAnnotations.push( annotations );
|
|
|
|
} else if ( annotations instanceof ve.dm.AnnotationSet ) {
|
|
|
|
this.insertionAnnotations.addSet( annotations );
|
|
|
|
} else {
|
|
|
|
throw new Error( 'Invalid annotations' );
|
|
|
|
}
|
2012-11-26 23:57:02 +00:00
|
|
|
this.emit( 'contextChange' );
|
2012-11-16 22:57:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Remove an annotation from those that will be used upon insertion.
|
2012-11-16 22:57:20 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-05-01 18:36:32 +00:00
|
|
|
* @param {ve.dm.Annotation|ve.dm.AnnotationSet} annotations Insertion annotation to remove
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires contextChange
|
2012-11-16 22:57:20 +00:00
|
|
|
*/
|
2013-05-01 18:36:32 +00:00
|
|
|
ve.dm.Surface.prototype.removeInsertionAnnotations = function ( annotations ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2013-05-01 18:36:32 +00:00
|
|
|
if ( annotations instanceof ve.dm.Annotation ) {
|
|
|
|
this.insertionAnnotations.remove( annotations );
|
|
|
|
} else if ( annotations instanceof ve.dm.AnnotationSet ) {
|
|
|
|
this.insertionAnnotations.removeSet( annotations );
|
|
|
|
} else {
|
|
|
|
throw new Error( 'Invalid annotations' );
|
|
|
|
}
|
2012-11-26 23:57:02 +00:00
|
|
|
this.emit( 'contextChange' );
|
2012-11-16 22:57:20 +00:00
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if there is a state to redo.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Has a future state
|
2012-10-24 22:21:54 +00:00
|
|
|
*/
|
2013-05-06 11:34:32 +00:00
|
|
|
ve.dm.Surface.prototype.hasFutureState = function () {
|
2012-10-24 22:21:54 +00:00
|
|
|
return this.undoIndex > 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if there is a state to undo.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Has a past state
|
2012-10-24 22:21:54 +00:00
|
|
|
*/
|
2013-05-06 11:34:32 +00:00
|
|
|
ve.dm.Surface.prototype.hasPastState = function () {
|
2013-12-08 20:25:53 +00:00
|
|
|
return this.undoStack.length - this.undoIndex > 0 || !!this.newTransactions.length;
|
2012-10-24 22:21:54 +00:00
|
|
|
};
|
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get the document model.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2013-07-09 23:46:55 +00:00
|
|
|
* @returns {ve.dm.Document} Document model of the surface
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.getDocument = function () {
|
2012-06-20 01:20:28 +00:00
|
|
|
return this.documentModel;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
2011-11-22 22:59:05 +00:00
|
|
|
|
2013-10-09 19:59:03 +00:00
|
|
|
/**
|
|
|
|
* Get the meta list.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {ve.dm.MetaList} Meta list of the surface
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.getMetaList = function () {
|
|
|
|
return this.metaList;
|
|
|
|
};
|
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get the selection.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2012-02-06 23:50:56 +00:00
|
|
|
* @returns {ve.Range} Current selection
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.getSelection = function () {
|
2011-11-22 22:59:05 +00:00
|
|
|
return this.selection;
|
|
|
|
};
|
|
|
|
|
2012-08-02 00:59:38 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get a fragment for a range.
|
2012-08-02 00:59:38 +00:00
|
|
|
*
|
|
|
|
* @method
|
2012-10-13 00:29:32 +00:00
|
|
|
* @param {ve.Range} [range] Range within target document, current selection used by default
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {boolean} [noAutoSelect] Don't update the surface's selection when making changes
|
2012-08-02 00:59:38 +00:00
|
|
|
*/
|
2012-10-13 00:29:32 +00:00
|
|
|
ve.dm.Surface.prototype.getFragment = function ( range, noAutoSelect ) {
|
|
|
|
return new ve.dm.SurfaceFragment( this, range || this.selection, noAutoSelect );
|
2012-08-02 00:59:38 +00:00
|
|
|
};
|
|
|
|
|
2013-04-29 20:57:32 +00:00
|
|
|
/**
|
|
|
|
* Prevent future states from being redone.
|
|
|
|
*
|
|
|
|
* @method
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires history
|
2013-04-29 20:57:32 +00:00
|
|
|
*/
|
2013-05-06 11:34:32 +00:00
|
|
|
ve.dm.Surface.prototype.truncateUndoStack = function () {
|
2013-07-25 13:33:51 +00:00
|
|
|
if ( this.undoIndex ) {
|
2013-12-08 20:25:53 +00:00
|
|
|
this.undoStack = this.undoStack.slice( 0, this.undoStack.length - this.undoIndex );
|
2013-07-25 13:33:51 +00:00
|
|
|
this.undoIndex = 0;
|
|
|
|
this.emit( 'history' );
|
|
|
|
}
|
2013-04-29 20:57:32 +00:00
|
|
|
};
|
|
|
|
|
2012-04-06 15:43:14 +00:00
|
|
|
/**
|
2013-10-08 15:43:10 +00:00
|
|
|
* Start queueing up calls to {#emitContextChange} until {#stopQueueingContextChanges} is called.
|
|
|
|
* While queueing is active, contextChanges are also collapsed, so if {#emitContextChange} is called
|
|
|
|
* multiple times, only one contextChange event will be emitted by {#stopQueueingContextChanges}.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* this.emitContextChange(); // emits immediately
|
|
|
|
* this.startQueueingContextChanges();
|
|
|
|
* this.emitContextChange(); // doesn't emit
|
|
|
|
* this.emitContextChange(); // doesn't emit
|
|
|
|
* this.stopQueueingContextChanges(); // emits one contextChange event
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2013-10-08 15:43:10 +00:00
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.startQueueingContextChanges = function () {
|
|
|
|
if ( !this.queueingContextChanges ) {
|
|
|
|
this.queueingContextChanges = true;
|
|
|
|
this.contextChangeQueued = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit a contextChange event. If {#startQueueingContextChanges} has been called, then the event
|
|
|
|
* is deferred until {#stopQueueingContextChanges} is called.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @private
|
|
|
|
* @fires contextChange
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.emitContextChange = function () {
|
|
|
|
if ( this.queueingContextChanges ) {
|
|
|
|
this.contextChangeQueued = true;
|
|
|
|
} else {
|
|
|
|
this.emit( 'contextChange' );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stop queueing contextChange events. If {#emitContextChange} was called previously, a contextChange
|
|
|
|
* event will now be emitted. Any future calls to {#emitContextChange} will once again emit the
|
|
|
|
* event immediately.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @private
|
|
|
|
* @fires contextChange
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.stopQueueingContextChanges = function () {
|
|
|
|
if ( this.queueingContextChanges ) {
|
|
|
|
this.queueingContextChanges = false;
|
|
|
|
if ( this.contextChangeQueued ) {
|
|
|
|
this.contextChangeQueued = false;
|
|
|
|
this.emit( 'contextChange' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change the selection
|
|
|
|
*
|
|
|
|
* @param {ve.Range} selection New selection
|
|
|
|
*
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires select
|
|
|
|
* @fires contextChange
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
2013-10-08 15:43:10 +00:00
|
|
|
ve.dm.Surface.prototype.setSelection = function ( selection ) {
|
|
|
|
var left, right, leftAnnotations, rightAnnotations, insertionAnnotations,
|
2012-12-03 19:36:09 +00:00
|
|
|
selectedNodes = {},
|
2013-10-08 08:41:14 +00:00
|
|
|
oldSelection = this.selection,
|
2013-05-06 20:08:52 +00:00
|
|
|
contextChange = false,
|
|
|
|
dataModelData = this.documentModel.data;
|
2012-11-21 21:22:29 +00:00
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-11-21 21:22:29 +00:00
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
if ( this.transacting ) {
|
|
|
|
// Update the selection but don't do any processing
|
2012-02-24 00:49:28 +00:00
|
|
|
this.selection = selection;
|
2013-10-08 15:43:10 +00:00
|
|
|
return;
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-11-21 21:22:29 +00:00
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
// Detect if selected nodes changed
|
|
|
|
selectedNodes.start = this.documentModel.getNodeFromOffset( selection.start );
|
|
|
|
if ( selection.getLength() ) {
|
|
|
|
selectedNodes.end = this.documentModel.getNodeFromOffset( selection.end );
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
selectedNodes.start !== this.selectedNodes.start ||
|
|
|
|
selectedNodes.end !== this.selectedNodes.end
|
|
|
|
) {
|
|
|
|
contextChange = true;
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-09-27 22:34:19 +00:00
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
// Update state
|
|
|
|
this.selectedNodes = selectedNodes;
|
|
|
|
this.selection = selection;
|
|
|
|
|
2013-05-06 20:08:52 +00:00
|
|
|
// Figure out which annotations to use for insertions
|
2012-11-21 21:22:29 +00:00
|
|
|
if ( this.selection.isCollapsed() ) {
|
|
|
|
// Get annotations from the left of the cursor
|
2013-05-06 20:08:52 +00:00
|
|
|
left = dataModelData.getNearestContentOffset( Math.max( 0, this.selection.start - 1 ), -1 );
|
|
|
|
right = dataModelData.getNearestContentOffset( Math.max( 0, this.selection.start ) );
|
2012-11-21 21:22:29 +00:00
|
|
|
} else {
|
|
|
|
// Get annotations from the first character of the selection
|
2013-05-06 20:08:52 +00:00
|
|
|
left = dataModelData.getNearestContentOffset( this.selection.start );
|
|
|
|
right = dataModelData.getNearestContentOffset( this.selection.end );
|
2012-11-21 21:22:29 +00:00
|
|
|
}
|
2013-05-06 20:08:52 +00:00
|
|
|
if ( left === -1 ) {
|
2012-11-21 21:22:29 +00:00
|
|
|
// Document is empty, use empty set
|
2013-05-06 20:08:52 +00:00
|
|
|
insertionAnnotations = new ve.dm.AnnotationSet( this.documentModel.getStore() );
|
2012-11-21 21:22:29 +00:00
|
|
|
} else {
|
2013-05-06 20:08:52 +00:00
|
|
|
// Include annotations on the left that should be added to appended content, or ones that
|
|
|
|
// are on both the left and the right that should not
|
|
|
|
leftAnnotations = dataModelData.getAnnotationsFromOffset( left );
|
|
|
|
rightAnnotations = dataModelData.getAnnotationsFromOffset( right );
|
|
|
|
insertionAnnotations = leftAnnotations.filter( function ( annotation ) {
|
|
|
|
return annotation.constructor.static.applyToAppendedContent ||
|
|
|
|
rightAnnotations.containsComparable( annotation );
|
|
|
|
} );
|
2012-11-21 21:22:29 +00:00
|
|
|
}
|
2013-05-06 20:08:52 +00:00
|
|
|
|
2012-11-21 21:22:29 +00:00
|
|
|
// Only emit an annotations change event if there's a meaningful difference
|
|
|
|
if (
|
2013-05-06 20:08:52 +00:00
|
|
|
!insertionAnnotations.containsAllOf( this.insertionAnnotations ) ||
|
|
|
|
!this.insertionAnnotations.containsAllOf( insertionAnnotations )
|
2012-11-21 21:22:29 +00:00
|
|
|
) {
|
2013-05-06 20:08:52 +00:00
|
|
|
this.setInsertionAnnotations( insertionAnnotations );
|
2012-11-26 23:57:02 +00:00
|
|
|
contextChange = true;
|
|
|
|
}
|
(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
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
// Emit events
|
|
|
|
if ( !oldSelection || !oldSelection.equals( this.selection ) ) {
|
|
|
|
this.emit( 'select', this.selection.clone() );
|
|
|
|
}
|
2013-05-06 11:34:32 +00:00
|
|
|
if ( contextChange ) {
|
2013-10-08 15:43:10 +00:00
|
|
|
this.emitContextChange();
|
2012-09-27 22:34:19 +00:00
|
|
|
}
|
2011-12-06 01:52:38 +00:00
|
|
|
};
|
|
|
|
|
2013-10-08 15:43:10 +00:00
|
|
|
/**
|
|
|
|
* Apply a transactions and selection changes to the document.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.dm.Transaction|ve.dm.Transaction[]|null} transactions One or more transactions to
|
|
|
|
* process, or null to process none
|
2013-10-09 13:21:50 +00:00
|
|
|
* @param {ve.Range} [selection] Selection to apply
|
2013-10-08 15:43:10 +00:00
|
|
|
* @fires contextChange
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.change = function ( transactions, selection ) {
|
2013-10-09 13:21:50 +00:00
|
|
|
this.changeInternal( transactions, selection, false );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal implementation of change(). Do not use this, use change() instead.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @method
|
|
|
|
* @param {ve.dm.Transaction|ve.dm.Transaction[]|null} transactions
|
|
|
|
* @param {ve.Range} [selection] [selection]
|
|
|
|
* @param {boolean} [skipUndoStack=false] If true, do not modify the undo stack. Used by undo/redo
|
|
|
|
* @fires contextChange
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.changeInternal = function ( transactions, selection, skipUndoStack ) {
|
2013-10-08 15:43:10 +00:00
|
|
|
var i, len, selectionAfter, selectionBefore = this.selection, contextChange = false;
|
|
|
|
|
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.startQueueingContextChanges();
|
|
|
|
|
|
|
|
// Process transactions
|
|
|
|
if ( transactions ) {
|
|
|
|
if ( transactions instanceof ve.dm.Transaction ) {
|
|
|
|
transactions = [transactions];
|
|
|
|
}
|
|
|
|
this.transacting = true;
|
|
|
|
for ( i = 0, len = transactions.length; i < len; i++ ) {
|
|
|
|
if ( !transactions[i].isNoOp() ) {
|
2013-10-09 13:21:50 +00:00
|
|
|
if ( !skipUndoStack ) {
|
|
|
|
this.truncateUndoStack();
|
2013-12-08 20:25:53 +00:00
|
|
|
this.newTransactions.push( transactions[i] );
|
2013-10-09 13:21:50 +00:00
|
|
|
}
|
2013-10-08 15:43:10 +00:00
|
|
|
// The .commit() call below indirectly invokes setSelection()
|
|
|
|
this.documentModel.commit( transactions[i] );
|
|
|
|
if ( transactions[i].hasElementAttributeOperations() ) {
|
|
|
|
contextChange = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.transacting = false;
|
|
|
|
}
|
|
|
|
selectionAfter = this.selection;
|
|
|
|
|
|
|
|
// Apply selection change
|
|
|
|
if ( selection ) {
|
|
|
|
this.setSelection( selection );
|
|
|
|
} else if ( transactions ) {
|
|
|
|
// Call setSelection() to trigger selection processing that was bypassed earlier
|
|
|
|
this.setSelection( this.selection );
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the selection changed while applying the transactions but not while applying the
|
|
|
|
// selection change, setSelection() won't have emitted a 'select' event. We don't want that
|
|
|
|
// to happen, so emit one anyway.
|
|
|
|
if ( !selectionBefore.equals( selectionAfter ) && selectionAfter.equals( this.selection ) ) {
|
|
|
|
this.emit( 'select', this.selection.clone() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( contextChange ) {
|
|
|
|
this.emitContextChange();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.stopQueueingContextChanges();
|
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Set a history state breakpoint.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.Range} selection New selection range
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires history
|
2013-06-18 15:55:03 +00:00
|
|
|
* @returns {boolean} A breakpoint was added
|
2012-10-24 22:21:54 +00:00
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.breakpoint = function ( selection ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
2013-06-18 15:55:03 +00:00
|
|
|
return false;
|
2012-12-12 00:28:39 +00:00
|
|
|
}
|
2013-12-08 20:25:53 +00:00
|
|
|
if ( this.newTransactions.length > 0 ) {
|
|
|
|
this.undoStack.push( {
|
|
|
|
'transactions': this.newTransactions,
|
|
|
|
'selection': selection || this.selection.clone()
|
2011-12-09 23:52:41 +00:00
|
|
|
} );
|
2013-12-08 20:25:53 +00:00
|
|
|
this.newTransactions = [];
|
2012-07-19 03:40:49 +00:00
|
|
|
this.emit( 'history' );
|
2013-06-18 15:55:03 +00:00
|
|
|
return true;
|
2012-04-02 22:28:26 +00:00
|
|
|
}
|
2013-06-18 15:55:03 +00:00
|
|
|
return false;
|
2012-04-02 22:28:26 +00:00
|
|
|
};
|
2011-12-09 23:52:41 +00:00
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Step backwards in history.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires history
|
2012-10-24 22:21:54 +00:00
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.undo = function () {
|
2013-10-09 13:21:50 +00:00
|
|
|
var i, item, selection, transaction, transactions = [];
|
2013-08-14 13:46:54 +00:00
|
|
|
if ( !this.enabled || !this.hasPastState() ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-10-09 13:21:50 +00:00
|
|
|
|
2011-12-09 23:52:41 +00:00
|
|
|
this.breakpoint();
|
2012-02-24 00:49:28 +00:00
|
|
|
this.undoIndex++;
|
2012-10-10 18:08:33 +00:00
|
|
|
|
2013-12-08 20:25:53 +00:00
|
|
|
item = this.undoStack[this.undoStack.length - this.undoIndex];
|
2013-10-09 13:21:50 +00:00
|
|
|
if ( item ) {
|
|
|
|
// Apply reversed transactions in reversed order, and translate the selection accordingly
|
2012-10-10 18:08:33 +00:00
|
|
|
selection = item.selection;
|
2013-12-08 20:25:53 +00:00
|
|
|
for ( i = item.transactions.length - 1; i >= 0; i-- ) {
|
|
|
|
transaction = item.transactions[i].reversed();
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
selection = transaction.translateRange( selection );
|
2013-10-09 13:21:50 +00:00
|
|
|
transactions.push( transaction );
|
2011-12-01 19:07:40 +00:00
|
|
|
}
|
2013-10-09 13:21:50 +00:00
|
|
|
this.changeInternal( transactions, selection, true );
|
2012-07-19 03:40:49 +00:00
|
|
|
this.emit( 'history' );
|
2011-12-01 19:07:40 +00:00
|
|
|
}
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Step forwards in history.
|
2012-10-24 22:21:54 +00:00
|
|
|
*
|
|
|
|
* @method
|
2013-10-22 17:54:59 +00:00
|
|
|
* @fires history
|
2012-10-24 22:21:54 +00:00
|
|
|
*/
|
Kranitor #3: jQuerlyfornication ft. The Cascaders
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
2012-07-28 19:15:23 +00:00
|
|
|
ve.dm.Surface.prototype.redo = function () {
|
2013-10-09 13:21:50 +00:00
|
|
|
var item;
|
2013-08-14 13:46:54 +00:00
|
|
|
if ( !this.enabled || !this.hasFutureState() ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-10-09 13:21:50 +00:00
|
|
|
|
2011-12-09 23:52:41 +00:00
|
|
|
this.breakpoint();
|
2012-10-10 18:08:33 +00:00
|
|
|
|
2013-12-08 20:25:53 +00:00
|
|
|
item = this.undoStack[this.undoStack.length - this.undoIndex];
|
2013-10-09 13:21:50 +00:00
|
|
|
if ( item ) {
|
2013-12-08 20:25:53 +00:00
|
|
|
// ve.copy( item.transactions ) invokes .clone() on each transaction in item.transactions
|
|
|
|
this.changeInternal( ve.copy( item.transactions ), item.selection, true );
|
2011-12-09 23:52:41 +00:00
|
|
|
this.undoIndex--;
|
2012-07-19 03:40:49 +00:00
|
|
|
this.emit( 'history' );
|
2011-12-09 23:52:41 +00:00
|
|
|
}
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|
2013-10-08 15:43:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to transactions processed on the document by translating the selection and updating
|
|
|
|
* other state.
|
|
|
|
*
|
|
|
|
* @param {ve.dm.Transaction} tx Transaction that was processed
|
|
|
|
* @fires documentUpdate
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.onDocumentTransact = function ( tx ) {
|
|
|
|
this.setSelection( tx.translateRange( this.selection ) );
|
|
|
|
this.emit( 'documentUpdate', tx );
|
|
|
|
};
|