2012-07-19 00:11:26 +00:00
|
|
|
/**
|
|
|
|
* VisualEditor Range 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
|
|
|
/**
|
|
|
|
* Range of content.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @class
|
|
|
|
* @constructor
|
|
|
|
* @param from {Integer} Starting offset
|
2012-08-02 00:59:38 +00:00
|
|
|
* @param [to=from] {Integer} Ending offset
|
2011-11-02 21:00:55 +00:00
|
|
|
* @property from {Integer} Starting offset
|
|
|
|
* @property to {Integer} Ending offset
|
|
|
|
* @property start {Integer} Normalized starting offset
|
|
|
|
* @property end {Integer} Normalized ending offset
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range = function ( from, to ) {
|
2011-11-02 21:00:55 +00:00
|
|
|
this.from = from || 0;
|
|
|
|
this.to = typeof to === 'undefined' ? this.from : to;
|
|
|
|
this.normalize();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2012-02-06 23:50:56 +00:00
|
|
|
* Creates a new ve.Range object that's a translated version of another.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @method
|
2012-02-06 23:50:56 +00:00
|
|
|
* @param {ve.Range} range Range to base new range on
|
2011-11-02 21:00:55 +00:00
|
|
|
* @param {Integer} distance Distance to move range by
|
2012-02-06 23:50:56 +00:00
|
|
|
* @returns {ve.Range} New translated range
|
2011-11-02 21:00:55 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.newFromTranslatedRange = function ( range, distance ) {
|
2012-02-06 23:50:56 +00:00
|
|
|
return new ve.Range( range.from + distance, range.to + distance );
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
/**
|
|
|
|
* Creates a new ve.Range object that covers all of the given ranges
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {Array} ranges Array of ve.Range objects (at least one)
|
|
|
|
* @returns {ve.Range} Range that spans all of the given ranges
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.newCoveringRange = function ( ranges ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
var minStart, maxEnd, i;
|
|
|
|
if ( !ranges || ranges.length === 0 ) {
|
2012-08-08 17:48:53 +00:00
|
|
|
throw new Error( 'newCoveringRange() requires at least one range' );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
minStart = ranges[0].start;
|
|
|
|
maxEnd = ranges[0].end;
|
|
|
|
for ( i = 1; i < ranges.length; i++ ) {
|
|
|
|
if ( ranges[i].start < minStart ) {
|
|
|
|
minStart = ranges[i].start;
|
|
|
|
}
|
|
|
|
if ( ranges[i].end > maxEnd ) {
|
|
|
|
maxEnd = ranges[i].end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new ve.Range( minStart, maxEnd );
|
|
|
|
};
|
|
|
|
|
2011-11-02 21:00:55 +00:00
|
|
|
/* Methods */
|
|
|
|
|
2011-11-10 01:28:01 +00:00
|
|
|
/**
|
|
|
|
* Gets a clone of this object.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-10 01:28:01 +00:00
|
|
|
* @method
|
2012-02-06 23:50:56 +00:00
|
|
|
* @returns {ve.Range} Clone of range
|
2011-11-10 01:28:01 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.prototype.clone = function () {
|
2012-02-06 23:50:56 +00:00
|
|
|
return new ve.Range( this.from, this.to );
|
2011-11-10 01:28:01 +00:00
|
|
|
};
|
|
|
|
|
2011-11-02 21:00:55 +00:00
|
|
|
/**
|
|
|
|
* Checks if an offset is within this range.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @method
|
|
|
|
* @param offset {Integer} Offset to check
|
|
|
|
* @returns {Boolean} If offset is within this range
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.prototype.containsOffset = function ( offset ) {
|
2011-11-02 21:00:55 +00:00
|
|
|
this.normalize();
|
|
|
|
return offset >= this.start && offset < this.end;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the length of the range.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @method
|
|
|
|
* @returns {Integer} Length of range
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.prototype.getLength = function () {
|
2011-11-02 21:00:55 +00:00
|
|
|
return Math.abs( this.from - this.to );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets start and end properties, ensuring start is always before end.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* This should always be called before using the start or end properties. Do not call this unless
|
|
|
|
* you are about to use these properties.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @method
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.prototype.normalize = function () {
|
2011-11-02 21:00:55 +00:00
|
|
|
if ( this.from < this.to ) {
|
|
|
|
this.start = this.from;
|
|
|
|
this.end = this.to;
|
|
|
|
} else {
|
|
|
|
this.start = this.to;
|
|
|
|
this.end = this.from;
|
|
|
|
}
|
|
|
|
};
|
2011-12-07 22:28:07 +00:00
|
|
|
|
2012-07-03 20:28:10 +00:00
|
|
|
/**
|
|
|
|
* Swaps from and to values, effectively changing the direction.
|
|
|
|
*
|
|
|
|
* The range will also be normalized when this is called.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.prototype.flip = function () {
|
2012-07-03 20:28:10 +00:00
|
|
|
var from = this.from;
|
|
|
|
this.from = this.to;
|
|
|
|
this.to = from;
|
|
|
|
this.normalize();
|
|
|
|
};
|
|
|
|
|
2011-12-07 22:28:07 +00:00
|
|
|
/**
|
|
|
|
* Determines if two Ranges are equal. Direction counts.
|
|
|
|
*
|
|
|
|
* @method
|
2012-02-06 23:50:56 +00:00
|
|
|
* @param {ve.Range}
|
2011-12-07 22:28:07 +00:00
|
|
|
* @returns {Boolean}
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.Range.prototype.equals = function ( other ) {
|
2011-12-07 22:28:07 +00:00
|
|
|
return this.from === other.from && this.to === other.to;
|
|
|
|
};
|