mediawiki-extensions-Visual.../modules/ve/ve.Position.js

227 lines
6.1 KiB
JavaScript
Raw Normal View History

/**
* VisualEditor Position class.
*
* @copyright 2011-2012 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Pixel position.
*
* This can also support an optional bottom field, to represent a vertical line, such as a cursor.
*
* @class
* @constructor
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
* @param left {Number} Horizontal position
* @param top {Number} Vertical top position
* @param bottom {Number} Vertical bottom position of bottom (optional, default: top)
* @property left {Number} Horizontal position
* @property top {Number} Vertical top position
* @property bottom {Number} Vertical bottom position of bottom
*/
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
ve.Position = function ve_Position( left, top, bottom ) {
this.left = left || 0;
this.top = top || 0;
this.bottom = bottom || this.top;
};
/* Static Methods */
/**
* Creates position object from the page position of an element.
*
* @static
* @method
* @param $element {jQuery} Element to get offset from
* @returns {ve.Position} Position with element data applied
*/
ve.Position.newFromElementPagePosition = function ( $element ) {
var offset = $element.offset();
return new ve.Position( offset.left, offset.top );
};
/**
* Creates position object from the layer position of an element.
*
* @static
* @method
* @param $element {jQuery} Element to get position from
* @returns {ve.Position} Position with element data applied
*/
ve.Position.newFromElementLayerPosition = function ( $element ) {
var position = $element.position();
return new ve.Position( position.left, position.top );
};
/**
* Creates position object from the screen position data in an Event object.
*
* @static
* @method
* @param event {Event} Event to get position data from
* @returns {ve.Position} Position with event data applied
*/
ve.Position.newFromEventScreenPosition = function ( event ) {
return new ve.Position( event.screenX, event.screenY );
};
/**
* Creates position object from the page position data in an Event object.
*
* @static
* @method
* @param event {Event} Event to get position data from
* @returns {ve.Position} Position with event data applied
*/
ve.Position.newFromEventPagePosition = function ( event ) {
return new ve.Position( event.pageX, event.pageY );
};
/**
* Creates position object from the layer position data in an Event object.
*
* @static
* @method
* @param event {Event} Event to get position data from
* @returns {ve.Position} Position with event data applied
*/
ve.Position.newFromEventLayerPosition = function ( event ) {
return new ve.Position( event.layerX, event.layerY );
};
/* Methods */
/**
* Adds the values of a given position to this one.
*
* @method
* @param position {ve.Position} Position to add values from
*/
ve.Position.prototype.add = function ( position ) {
this.top += position.top;
this.bottom += position.bottom;
this.left += position.left;
};
/**
* Subtracts the values of a given position to this one.
*
* @method
* @param position {ve.Position} Position to subtract values from
*/
ve.Position.prototype.subtract = function ( position ) {
this.top -= position.top;
this.bottom -= position.bottom;
this.left -= position.left;
};
/**
* Checks if this position is the same as another one.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If positions have the same left and top values
*/
ve.Position.prototype.at = function ( position ) {
return this.left === position.left && this.top === position.top;
};
/**
* Checks if this position perpendicular with another one, sharing either a top or left value.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If positions share a top or a left value
*/
ve.Position.prototype.perpendicularWith = function ( position ) {
return this.left === position.left || this.top === position.top;
};
/**
* Checks if this position is level with another one, having the same top value.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If positions have the same top value
*/
ve.Position.prototype.levelWith = function ( position ) {
return this.top === position.top;
};
/**
* Checks if this position is plumb with another one, having the same left value.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If positions have the same left value
*/
ve.Position.prototype.plumbWith = function ( position ) {
return this.left === position.left;
};
/**
* Checks if this position is nearby another one.
*
* Distance is measured radially.
*
* @method
* @param position {ve.Position} Position to compare with
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
* @param radius {Number} Pixel distance from this position to consider "near-by"
* @returns {Boolean} If positions are near-by each other
*/
ve.Position.prototype.near = function ( position, radius ) {
return Math.sqrt(
Math.pow( this.left - position.left, 2 ),
Math.pow( this.top - position.top )
) <= radius;
};
/**
* Checks if this position is above another one.
*
* This method utilizes the bottom property.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If this position is above the other
*/
ve.Position.prototype.above = function ( position ) {
return this.bottom < position.top;
};
/**
* Checks if this position is below another one.
*
* This method utilizes the bottom property.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If this position is below the other
*/
ve.Position.prototype.below = function ( position ) {
return this.top > position.bottom;
};
/**
* Checks if this position is to the left of another one.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If this position is the left the other
*/
ve.Position.prototype.leftOf = function ( left ) {
return this.left < left;
};
/**
* Checks if this position is to the right of another one.
*
* @method
* @param position {ve.Position} Position to compare with
* @returns {Boolean} If this position is the right the other
*/
ve.Position.prototype.rightOf = function ( left ) {
return this.left > left;
};