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 );
|
2012-12-03 19:36:09 +00:00
|
|
|
this.selectedNodes = {};
|
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();
|
2012-12-12 00:28:39 +00:00
|
|
|
this.enabled = true;
|
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-12-12 00:28:39 +00:00
|
|
|
/**
|
|
|
|
* Disables changes.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.disable = function () {
|
|
|
|
this.stopHistoryTracking();
|
|
|
|
this.enabled = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enables changes.
|
|
|
|
*
|
|
|
|
* @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;
|
|
|
|
}
|
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-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
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 () {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
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
|
2012-11-26 23:57:02 +00:00
|
|
|
* @emits '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;
|
|
|
|
}
|
2012-11-16 22:57:20 +00:00
|
|
|
this.insertionAnnotations = annotations.clone();
|
2012-11-26 23:57:02 +00:00
|
|
|
this.emit( 'contextChange' );
|
2012-11-16 22:57:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds an annotation to the insertion annotations.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.AnnotationSet} Insertion anotation to add
|
2012-11-26 23:57:02 +00:00
|
|
|
* @emits 'contextChange'
|
2012-11-16 22:57:20 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.addInsertionAnnotation = function ( annotation ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2012-11-16 22:57:20 +00:00
|
|
|
this.insertionAnnotations.push( annotation );
|
2012-11-26 23:57:02 +00:00
|
|
|
this.emit( 'contextChange' );
|
2012-11-16 22:57:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes an annotation from the insertion annotations.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {ve.AnnotationSet} Insertion anotation to remove
|
2012-11-26 23:57:02 +00:00
|
|
|
* @emits 'contextChange'
|
2012-11-16 22:57:20 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Surface.prototype.removeInsertionAnnotation = function ( annotation ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2012-11-16 22:57:20 +00:00
|
|
|
this.insertionAnnotations.remove( annotation );
|
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
|
|
|
/**
|
|
|
|
* 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-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
2012-11-26 23:57:02 +00:00
|
|
|
var i, len, offset, annotations,
|
2012-12-03 19:36:09 +00:00
|
|
|
selectedNodes = {},
|
|
|
|
selectionChange = false,
|
2012-11-26 23:57:02 +00:00
|
|
|
contextChange = false;
|
2012-11-21 21:22:29 +00:00
|
|
|
|
(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
|
|
|
// Stop observation polling, things changing right now are known already
|
|
|
|
this.emit( 'lock' );
|
|
|
|
|
2012-11-21 21:22:29 +00:00
|
|
|
// 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-26 23:57:02 +00:00
|
|
|
for ( i = 0, len = transactions.length; i < len; 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] );
|
2012-11-26 23:57:02 +00:00
|
|
|
ve.dm.TransactionProcessor.commit( this.documentModel, transactions[i] );
|
2012-08-17 23:24:10 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
2012-11-21 21:22:29 +00:00
|
|
|
|
2012-12-03 19:36:09 +00:00
|
|
|
if ( selection ) {
|
|
|
|
// Detect if selection range changed
|
|
|
|
if ( !this.selection || !this.selection.equals( selection ) ) {
|
|
|
|
selection.normalize();
|
|
|
|
selectionChange = true;
|
|
|
|
}
|
|
|
|
// Detect if selected nodes changed
|
|
|
|
selectedNodes.start = this.documentModel.getNodeFromOffset( selection.start );
|
|
|
|
if ( selection.getLength() ) {
|
|
|
|
selectedNodes.end = this.documentModel.getNodeFromOffset( selection.end );
|
|
|
|
}
|
2012-11-26 23:57:02 +00:00
|
|
|
if (
|
2012-12-03 19:36:09 +00:00
|
|
|
selectedNodes.start !== this.selectedNodes.start ||
|
|
|
|
selectedNodes.end !== this.selectedNodes.end
|
2012-11-26 23:57:02 +00:00
|
|
|
) {
|
2012-12-07 21:17:31 +00:00
|
|
|
contextChange = true;
|
2012-12-03 19:36:09 +00:00
|
|
|
}
|
|
|
|
this.selectedNodes = selectedNodes;
|
2012-12-07 21:17:31 +00:00
|
|
|
if ( selectionChange ) {
|
2012-12-03 19:36:09 +00:00
|
|
|
this.emit( 'select', this.selection.clone() );
|
2012-11-26 23:57:02 +00:00
|
|
|
}
|
2012-02-24 00:49:28 +00:00
|
|
|
this.selection = selection;
|
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-11-26 23:57:02 +00:00
|
|
|
// Detect context change, if not detected already, when element attributes have changed
|
|
|
|
if ( !contextChange ) {
|
|
|
|
for ( i = 0, len = transactions.length; i < len; i++ ) {
|
|
|
|
if ( transactions[i].hasElementAttributeOperations() ) {
|
|
|
|
contextChange = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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-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
|
|
|
|
2012-11-26 23:57:02 +00:00
|
|
|
// Only emit one context change event
|
2012-12-07 21:17:31 +00:00
|
|
|
if ( contextChange ) {
|
2012-11-26 23:57:02 +00:00
|
|
|
this.emit( 'contextChange' );
|
2012-09-27 22:34:19 +00:00
|
|
|
}
|
|
|
|
|
2012-08-17 23:24:10 +00:00
|
|
|
this.emit( 'change', transactions, selection );
|
(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
|
|
|
|
|
|
|
// Continue observation polling, we want to know about things that change from here on out
|
|
|
|
this.emit( 'unlock' );
|
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 ) {
|
2012-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
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
|
|
|
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-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
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-12-12 00:28:39 +00:00
|
|
|
if ( !this.enabled ) {
|
|
|
|
return;
|
|
|
|
}
|
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
|
|
|
};
|