2012-07-19 00:11:26 +00:00
|
|
|
/**
|
|
|
|
* VisualEditor data model Surface class.
|
2012-07-19 21:25:16 +00:00
|
|
|
*
|
2012-07-19 00:11:26 +00:00
|
|
|
* @copyright 2011-2012 VisualEditor Team and others; see AUTHORS.txt
|
|
|
|
* @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
|
|
|
|
* @constructor
|
2012-02-06 23:50:56 +00:00
|
|
|
* @extends {ve.EventEmitter}
|
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 ) {
|
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
|
|
|
// Parent constructor
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.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;
|
2012-08-16 20:16:48 +00:00
|
|
|
this.selection = new ve.Range( 0, 0 );
|
2011-12-09 23:52:41 +00:00
|
|
|
this.smallStack = [];
|
|
|
|
this.bigStack = [];
|
|
|
|
this.undoIndex = 0;
|
2012-06-20 01:20:28 +00:00
|
|
|
this.historyTrackingInterval = null;
|
2012-11-16 22:57:20 +00:00
|
|
|
this.insertionAnnotations = new ve.AnnotationSet();
|
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 */
|
|
|
|
|
|
|
|
ve.inheritClass( ve.dm.Surface, ve.EventEmitter );
|
|
|
|
|
2011-11-02 21:00:55 +00:00
|
|
|
/* Methods */
|
|
|
|
|
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-08-11 08:14:56 +00:00
|
|
|
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-06-20 01:20:28 +00:00
|
|
|
clearInterval( this.historyTrackingInterval );
|
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Removes all states from 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.purgeHistory = function () {
|
2011-12-09 20:40:26 +00:00
|
|
|
this.selection = null;
|
2011-12-12 22:51:32 +00:00
|
|
|
this.smallStack = [];
|
|
|
|
this.bigStack = [];
|
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
|
|
|
/**
|
|
|
|
* Gets a list of all history states.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {Array[]} List of transaction stacks
|
|
|
|
*/
|
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 () {
|
2011-12-13 00:56:29 +00:00
|
|
|
if ( this.smallStack.length > 0 ) {
|
2012-02-24 00:49:28 +00:00
|
|
|
return this.bigStack.slice( 0 ).concat( [{ 'stack': this.smallStack.slice(0) }] );
|
2011-12-13 00:56:29 +00:00
|
|
|
} else {
|
2012-02-07 00:42:16 +00:00
|
|
|
return this.bigStack.slice( 0 );
|
2011-12-13 00:56:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-16 22:57:20 +00:00
|
|
|
/**
|
|
|
|
* Gets annotations that will be used upon insertion.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {ve.AnnotationSet|null} Insertion anotations or null if not being used
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.getInsertionAnnotations = function () {
|
|
|
|
return this.insertionAnnotations.clone();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets annotations that will be used upon insertion.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.AnnotationSet|null} Insertion anotations to use or null to disable them
|
|
|
|
* @emits 'annotationChange'
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.setInsertionAnnotations = function ( annotations ) {
|
|
|
|
this.insertionAnnotations = annotations.clone();
|
|
|
|
this.emit( 'annotationChange' );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds an annotation to the insertion annotations.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.AnnotationSet} Insertion anotation to add
|
|
|
|
* @emits 'annotationChange'
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.addInsertionAnnotation = function ( annotation ) {
|
|
|
|
this.insertionAnnotations.push( annotation );
|
|
|
|
this.emit( 'annotationChange' );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes an annotation from the insertion annotations.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.AnnotationSet} Insertion anotation to remove
|
|
|
|
* @emits 'annotationChange'
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.removeInsertionAnnotation = function ( annotation ) {
|
|
|
|
this.insertionAnnotations.remove( annotation );
|
|
|
|
this.emit( 'annotationChange' );
|
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Checks if there is a state to redo.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {Boolean} Has a future state
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.hasFutureState = function() {
|
|
|
|
return this.undoIndex > 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if there is a state to undo.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {Boolean} Has a past state
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.hasPastState = function() {
|
|
|
|
return this.bigStack.length - this.undoIndex > 0;
|
|
|
|
};
|
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
/**
|
|
|
|
* Gets the document model of the surface.
|
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.dm.DocumentNode} 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
|
|
|
|
|
|
|
/**
|
2012-02-24 00:49:28 +00:00
|
|
|
* Gets the selection
|
|
|
|
*
|
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
|
|
|
/**
|
|
|
|
* Gets a fragment from this document and selection.
|
|
|
|
*
|
|
|
|
* @method
|
2012-10-13 00:29:32 +00:00
|
|
|
* @param {ve.Range} [range] Range within target document, current selection used by default
|
|
|
|
* @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
|
|
|
};
|
|
|
|
|
2012-04-06 15:43:14 +00:00
|
|
|
/**
|
2012-06-20 01:20:28 +00:00
|
|
|
* Applies a series of transactions to the content data and sets the selection.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2012-08-17 23:24:10 +00:00
|
|
|
* @param {ve.dm.Transaction|ve.dm.Transaction[]|null} transactions One or more transactions to
|
|
|
|
* process, or null to process none
|
Make use of new jshint options
* Restricting "camelcase":
No changes, we were passing all of these already
* Explicitly unrestricting "forin" and "plusplus"
These are off by default in node-jshint, but some distro of jshint
and editors that use their own wrapper around jshint instead of
node-jshint (Eclipse?) may have different defaults. Therefor
setting them to false explicitly. This also serves as a reminder
for the future so we'll always know we don't pass that, in case
we would want to change that.
* Fix order ("quotemark" before "regexp")
* Restricting "unused"
We're not passing all of this, which is why I've set it to false
for now. But I did put it in .jshintrc as placeholder.
I've fixed most of them, there's some left where there is no clean
solution.
* While at it fix a few issues:
- Unused variables ($target, $window)
- Bad practices (using jQuery context for find instead of creation)
- Redundant /*global */ comments
- Parameters that are not used and don't have documentation either
- Lines longer than 100 chars @ 4 spaces/tab
* Note:
- ve.ce.Surface.prototype.onChange takes two arguments but never
uses the former. And even the second one can be null/undefined.
Aside from that, the .change() function emits
another event for the transaction already. Looks like this
should be refactored a bit, two more separated events probably
or one that is actually used better.
- Also cleaned up a lot of comments, some of which were missing,
others were incorrect
- Reworked the contentChange event so we are no longer using the
word new as an object key; expanded a complex object into multiple
arguments being passed through the event to make it easier to work
with and document
Change-Id: I8490815a508c6c379d5f9a743bb4aefd14576aa6
2012-08-07 06:02:18 +00:00
|
|
|
* @param {ve.Range|undefined} selection
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
2012-08-17 23:24:10 +00:00
|
|
|
ve.dm.Surface.prototype.change = function ( transactions, selection ) {
|
2012-11-21 21:22:29 +00:00
|
|
|
var i, offset, annotations;
|
|
|
|
|
|
|
|
// Process transactions and apply selection changes
|
2012-08-17 23:24:10 +00:00
|
|
|
if ( transactions ) {
|
|
|
|
if ( transactions instanceof ve.dm.Transaction ) {
|
|
|
|
transactions = [transactions];
|
|
|
|
}
|
2012-11-20 22:51:24 +00:00
|
|
|
this.emit( 'lock' );
|
2012-10-22 22:52:19 +00:00
|
|
|
for ( i = 0; i < transactions.length; i++ ) {
|
2012-08-17 23:24:10 +00:00
|
|
|
if ( !transactions[i].isNoOp() ) {
|
|
|
|
this.bigStack = this.bigStack.slice( 0, this.bigStack.length - this.undoIndex );
|
|
|
|
this.undoIndex = 0;
|
|
|
|
this.smallStack.push( transactions[i] );
|
|
|
|
ve.dm.TransactionProcessor.commit( this.getDocument(), transactions[i] );
|
|
|
|
}
|
|
|
|
}
|
2012-11-20 22:51:24 +00:00
|
|
|
this.emit( 'unlock' );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-11-21 21:22:29 +00:00
|
|
|
|
|
|
|
// Only emit a select event if the selection actually changed
|
2012-06-20 01:20:28 +00:00
|
|
|
if ( selection && ( !this.selection || !this.selection.equals ( selection ) ) ) {
|
|
|
|
selection.normalize();
|
2012-02-24 00:49:28 +00:00
|
|
|
this.selection = selection;
|
2012-11-21 21:22:29 +00:00
|
|
|
this.emit( 'select', this.selection.clone() );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-11-21 21:22:29 +00:00
|
|
|
|
|
|
|
// Only emit a transact event if transactions were actually processed
|
2012-08-17 23:24:10 +00:00
|
|
|
if ( transactions ) {
|
|
|
|
this.emit( 'transact', transactions );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-09-27 22:34:19 +00:00
|
|
|
|
2012-11-21 21:22:29 +00:00
|
|
|
// Figure out which offset which we should get insertion annotations from
|
|
|
|
if ( this.selection.isCollapsed() ) {
|
|
|
|
// Get annotations from the left of the cursor
|
2012-11-16 22:57:20 +00:00
|
|
|
offset = this.documentModel.getNearestContentOffset(
|
2012-11-21 21:22:29 +00:00
|
|
|
Math.max( 0, this.selection.start - 1 ), -1
|
2012-11-16 22:57:20 +00:00
|
|
|
);
|
2012-11-21 21:22:29 +00:00
|
|
|
} else {
|
|
|
|
// Get annotations from the first character of the selection
|
|
|
|
offset = this.documentModel.getNearestContentOffset( this.selection.start );
|
|
|
|
}
|
|
|
|
if ( offset === -1 ) {
|
|
|
|
// Document is empty, use empty set
|
|
|
|
annotations = new ve.AnnotationSet();
|
|
|
|
} else {
|
|
|
|
annotations = this.documentModel.getAnnotationsFromOffset( offset );
|
|
|
|
}
|
|
|
|
// Only emit an annotations change event if there's a meaningful difference
|
|
|
|
if (
|
|
|
|
!annotations.containsAllOf( this.insertionAnnotations ) ||
|
|
|
|
!this.insertionAnnotations.containsAllOf( annotations )
|
|
|
|
) {
|
|
|
|
this.insertionAnnotations = annotations;
|
2012-09-27 22:34:19 +00:00
|
|
|
this.emit( 'annotationChange' );
|
|
|
|
}
|
|
|
|
|
2012-08-17 23:24:10 +00:00
|
|
|
this.emit( 'change', transactions, selection );
|
2011-12-06 01:52:38 +00:00
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Sets a history state breakpoint.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.Range} selection New selection range
|
|
|
|
*/
|
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 ) {
|
|
|
|
if ( this.smallStack.length > 0 ) {
|
2011-12-09 23:52:41 +00:00
|
|
|
this.bigStack.push( {
|
|
|
|
stack: this.smallStack,
|
|
|
|
selection: selection || this.selection.clone()
|
|
|
|
} );
|
|
|
|
this.smallStack = [];
|
2012-07-19 03:40:49 +00:00
|
|
|
this.emit( 'history' );
|
2012-04-02 22:28:26 +00:00
|
|
|
}
|
|
|
|
};
|
2011-12-09 23:52:41 +00:00
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Steps backwards in history.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {ve.Range} Selection or null if no further state could be reached
|
|
|
|
*/
|
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 () {
|
2012-10-10 18:08:33 +00:00
|
|
|
var item, i, transaction, selection;
|
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
|
|
|
|
2011-12-09 23:52:41 +00:00
|
|
|
if ( this.bigStack[this.bigStack.length - this.undoIndex] ) {
|
2012-10-01 20:05:06 +00:00
|
|
|
this.emit( 'lock' );
|
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
|
|
|
item = this.bigStack[this.bigStack.length - this.undoIndex];
|
2012-10-10 18:08:33 +00:00
|
|
|
selection = item.selection;
|
|
|
|
|
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
|
|
|
for ( i = item.stack.length - 1; i >= 0; i-- ) {
|
2012-10-10 18:08:33 +00:00
|
|
|
transaction = item.stack[i];
|
|
|
|
selection = transaction.translateRange( selection, true );
|
2012-06-20 01:20:28 +00:00
|
|
|
this.documentModel.rollback( item.stack[i] );
|
2011-12-01 19:07:40 +00:00
|
|
|
}
|
2012-10-01 20:05:06 +00:00
|
|
|
this.emit( 'unlock' );
|
2012-07-19 03:40:49 +00:00
|
|
|
this.emit( 'history' );
|
2012-06-20 01:20:28 +00:00
|
|
|
return selection;
|
2011-12-01 19:07:40 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
return null;
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|
|
|
|
|
2012-10-24 22:21:54 +00:00
|
|
|
/**
|
|
|
|
* Steps forwards in history.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {ve.Range} Selection or null if no further state could be reached
|
|
|
|
*/
|
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 () {
|
2012-10-10 18:08:33 +00:00
|
|
|
var selection, item, i;
|
2011-12-09 23:52:41 +00:00
|
|
|
this.breakpoint();
|
2012-10-10 18:08:33 +00:00
|
|
|
|
|
|
|
if ( this.undoIndex > 0 && this.bigStack[this.bigStack.length - this.undoIndex] ) {
|
2012-10-01 20:05:06 +00:00
|
|
|
this.emit( 'lock' );
|
2012-10-10 18:08:33 +00:00
|
|
|
item = this.bigStack[this.bigStack.length - this.undoIndex];
|
|
|
|
selection = item.selection;
|
|
|
|
for ( i = 0; i < item.stack.length; i++ ) {
|
|
|
|
this.documentModel.commit( item.stack[i] );
|
2011-12-09 23:52:41 +00:00
|
|
|
}
|
|
|
|
this.undoIndex--;
|
2012-10-01 20:05:06 +00:00
|
|
|
this.emit( 'unlock' );
|
2012-07-19 03:40:49 +00:00
|
|
|
this.emit( 'history' );
|
2012-06-20 01:20:28 +00:00
|
|
|
return selection;
|
2011-12-09 23:52:41 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
return null;
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|